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
state.ts4.1 KB
// Chat state belongs to the plugin scope; each pane reads only its chat's transcript.
// Drafts and queues retain their baseline storage and shared-state names.
import type {
AgentInfo,
ApprovalRequest,
AttachedImage,
Chat,
ComboMark,
ConfigOption,
Element,
Plan,
QuestionRequest,
SecurityRequest,
Skill,
SlashCommand,
TranscriptItem,
Usage,
ViewHandle,
Workspace,
} from "convergence";
import type { Cycle } from "./switcher.ts";
export type UserItem = Extract<TranscriptItem, { role: "user" }>;
export type TextItem = Extract<TranscriptItem, { role: "assistant" | "reasoning" }>;
export type ToolItem = Extract<TranscriptItem, { role: "tool" }>;
export type Question = QuestionRequest & { submitting?: boolean };
export type Prompt = { text: string; attachments: readonly { id: string; name?: string }[]; blocks?: readonly import("convergence").ContentBlock[]; id?: string };
/// A draft waiting to start. Its prompt stays in its composer, editable,
/// until no chat runs; then the queue sends it.
export type QueuedChat = { chatId: string };
export type Composer = {
text: string;
/// The agent the options, commands and skills below are from.
agentId: string | null;
options: readonly ConfigOption[];
commands: readonly SlashCommand[];
skills: readonly Skill[];
loading: boolean;
picker: { kind: "commands" | "skills" | "files"; query: string; index?: number } | null;
files: readonly string[];
queue: Prompt[];
attachments: AttachedImage[];
submitting?: boolean;
/// The input this composer is handing to the agent: it is already
/// acknowledged, so it shows as the user's message, not as held input.
dispatching?: string;
error?: string;
submission?: { id: string; signature: string };
pendingEdit?: { id: string; revision: number; text: string };
};
export type Transcript = {
items: TranscriptItem[];
approvals: ApprovalRequest[];
questions: Question[];
requests: readonly SecurityRequest[];
plan: Plan | null;
running: boolean;
checkpoints: Set<string>;
expanded: Set<string>;
folds: Map<string, boolean>;
answers: Record<string, Record<string, unknown>>;
editing: string | null;
editText: string;
loaded: boolean;
usage?: Usage;
finished?: Set<string>;
};
export type Pane = { chatId: string; view: ViewHandle };
export type ActivityProps = {
icon?: string | Element;
label?: string;
detail?: string;
extra?: Element | null;
status?: Element | null;
open?: boolean;
onClick?: () => void;
tone?: string;
compact?: boolean;
};
/** A workspace picker's trigger: the workspace's name and mark, and whether it can change. The kernel's combobox opens the list. */
export type AnchorProps = { name: string; mark: ComboMark; can: boolean };
export class ChatState {
chats: Record<string, Chat> = {};
agents: Record<string, AgentInfo> = {};
agentList: readonly AgentInfo[] = [];
composers: Record<string, Composer> = {};
transcripts: Record<string, Transcript> = {};
workspaces: Record<string, Workspace> = {};
// Pane views by chat id, the most recently shown first in recentPanes.
panes: Record<string, Pane> = {};
recentPanes: string[] = [];
paneViews: Record<string, { chatId: string; view: ViewHandle }> = {};
chatQueue: QueuedChat[] = [];
// The queued draft just sent: it holds the queue until the host reports
// it running, so a second chat cannot start in the gap.
releasing: string | null = null;
wsPicker: Record<string, boolean> = {};
recent: string[] = [];
itemImages: Record<string, string[] | "pending"> = {};
switcher: Cycle | null = null;
promptedChat: string | null = null;
historyRead: Record<string, number> = {};
historyChat: string | null = null;
restored: Record<string, string> | null = null;
saving = false;
unsaved = false;
draftTitles: Record<string, string> = {};
ticking = false;
}
export function initialTranscript(): Transcript {
return {
items: [],
approvals: [],
questions: [],
requests: [],
plan: null,
running: false,
checkpoints: new Set(),
expanded: new Set(),
folds: new Map(),
answers: {},
editing: null,
editText: "",
loaded: 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.