Official
chat
Built-in chat UI (JavaScript UI plugin).
The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/chat@0.2.0
Permissions in 0.2.0
Files
views/styles.ts4.4 KB
// Shared template metrics and tones preserve the existing chat surface.
// Chat disables embedded HTML formatting: template spaces become real UI nodes.
import { html } from "convergence";
import type { ComboMark, Workspace } from "convergence";
import type { AnchorProps } from "../state.ts";
export const READING_WIDTH = 880;
export const FIELD_INSET_X = 10;
export const PILL_INSET_X = 5;
export const column = { display: "flex", flexDirection: "column" };
export const row = { display: "flex", flexDirection: "row", alignItems: "center" };
export const fill = { flexGrow: 1, flexShrink: 1, flexBasis: "0%", minWidth: 0, minHeight: 0 };
export const full = { width: "100%", height: "100%" };
export const HOVER = { background: "hover" };
export const clickable = { group: "hover", cursor: "pointer" };
export const revealOnHover = { visibility: "hidden", groupHover: { group: "hover", visibility: "visible" } };
export const centred = { width: "100%", marginX: "auto" };
export const BORDER = { width: 1, color: "border" };
export const TINT: Record<string, string> = {
foreground: "foreground",
muted: "mutedForeground",
faint: "faint",
primary: "primary",
info: "info",
success: "success",
warning: "warning",
danger: "danger",
};
export const tint = (tone: string | undefined) => TINT[tone ?? "muted"];
export const ROW_TEXT = { size: "xs", weight: 560, lineHeight: 14.6 };
export const TOOL_ICONS = {
read: "file-text",
edit: "file-pen-line",
delete: "delete",
move: "arrow-right",
search: "search",
execute: "square-terminal",
think: "brain",
fetch: "globe",
task: "layout-dashboard",
switch_mode: "toggle-left",
other: "cpu",
};
export const TOOL_LABELS = {
read: "Read",
edit: "Edit",
delete: "Delete",
move: "Move",
search: "Search",
execute: "Run",
think: "Think",
fetch: "Fetch",
task: "Task",
switch_mode: "Mode",
other: "",
};
export const CARD_SPACE = 8;
export const PHASE_MARK = {
done: { icon: "circle-check", tone: "success" },
failed: { icon: "circle-x", tone: "danger" },
waiting: { icon: "circle-pause", tone: "warning" },
queued: { icon: "circle-dashed", tone: "muted" },
pending: { icon: "circle-dashed", tone: "faint" },
stopped: { icon: "circle-stop", tone: "muted" },
};
export const AGENT_MARK = {
completed: { icon: "circle-check", tone: "success" },
idle: { icon: "circle-check", tone: "success" },
failed: { icon: "circle-x", tone: "danger" },
waiting: { icon: "circle-pause", tone: "warning" },
queued: { icon: "circle-dashed", tone: "faint" },
cancelled: { icon: "circle-stop", tone: "muted" },
};
// A workspace's mark: its project icon, else the icon the app gives it
// (the Plugins puzzle), else a folder in its colour; the coloured folder
// too when the user chose it over the icon.
export const markOf = (w: Workspace | undefined): ComboMark => {
if (w?.icon && !w.useColor) return { image: w.icon };
if (w?.mark && !w.useColor) return { icon: w.mark };
return w?.color ? { icon: "folder-solid", color: w.color } : { icon: "folder" };
};
const markIcon = (mark: ComboMark, size: number, small = false) =>
mark.image
? html`<image path=${mark.image} width=${size} height=${size} radius=${3} />`
: html`<icon name=${mark.icon ?? "folder"} color=${mark.color} small=${small} tone="muted" />`;
// The triggers of the workspace picker; the kernel's combobox around them
// opens the list on the press.
export const headlineAnchor =
(headline: { size: string; bold: boolean }) =>
({ name, mark, can }: AnchorProps) =>
html`
<div ...${row} ...${can ? clickable : null} gap=${6} padding="small" paddingX=${6} paddingY=${2} borderRadius="md" hover=${can ? HOVER : undefined}>
${markIcon(mark, 20)}
<text style="body" ...${headline}>${name}</text>
${can ? html`<icon name="chevron-down" small tone="muted" />` : null}
</div>`;
export const chipAnchor = ({ name, mark, can }: AnchorProps, small = true) =>
html`
<div ...${row} ...${can ? clickable : null} gap=${5} padding="small" paddingX=${8} paddingY=${2} maxWidth=${220} background="subtle"
borderRadius=${11} hover=${can ? HOVER : undefined}>
${markIcon(mark, small ? 12 : 14, small)}
<text style="body" size="xs" tone="muted" truncate>${name}</text>
${can ? html`<icon name="chevron-down" small=${small} tone="faint" />` : null}
</div>`;
export const titleChipAnchor = (props: AnchorProps) => chipAnchor(props, false);Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 105.1 KB | 5 permissions | Listed |
No comments yet.