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

  • Control chats chats.controlHighCreates chats, sends prompts and cancels runs.Send prompts, answer agent questions, and create, change, fork, revert, stop and group chats
  • Run other plugins' commands commands.runHighRuns commands of other plugins.Run the sidebar's New chat command from the title bar
  • Read chats chats.readMediumReads your transcripts and chat lists.Show workspaces, tasks, chats and transcripts, and follow them as agents work
  • Read files fs.readMediumReads files in the listed places.Suggest workspace files for @ mentionsPlaces: the open workspace
  • Show panels ui.slotsLowShows views in the listed parts of the window.Draw the chat grid and the title barSlots: centertitle

Files

composition.ts2.3 KB
// Capture a complete structured composition before acknowledging or clearing it.
// Reading one attachment fails the submission, never silently sends a subset.
import * as Effect from "effect/Effect";
import type { Chat, ContentBlock } from "convergence";
import type { Controller } from "./controller.ts";
import type { Prompt } from "./state.ts";
import { mentionInstructions, tagTokens } from "./mentions.ts";

let sequence = 0;
export const inputId = () => `chat:${Date.now()}:${++sequence}:${Math.random().toString(36).slice(2)}`;
export function steeringReason(c: Controller, chat: Chat): string | undefined {
  if (!c.isRunning(chat)) return;
  if (c.scheduler.available === false) return "Active steering needs an updated app; Queue retains the prompt";
  const capabilities = c.state.agents[chat.agentId]?.capabilities;
  if (!capabilities?.steer && !capabilities?.simulatedSteer) return "This agent does not support active steering; use Queue or Stop";
}
export const blocksFor = Effect.fn("Chat.blocksFor")(function* (c: Controller, chatId: string, text: string, attachments: Prompt["attachments"]) {
  const composer = c.composer(chatId);
  const blocks: ContentBlock[] = [];
  const [name = "", ...rest] = text.slice(1).split(/\s+/);
  if (text.startsWith("$") && composer.skills.some((skill) => skill.name === name))
    blocks.push({ type: "skill", name, input: rest.join(" ") });
  else if (text) blocks.push({ type: "text", text });
  const mentions = c.api.mentions.list(), tags = tagTokens(text, mentions);
  for (const token of text.split(/\s+/)) {
    if (tags.has(token)) continue;
    if (token.startsWith("@") && token.length > 1 && /[./]/.test(token))
      blocks.push({ type: "file_ref", path: token.slice(1).replace(/[,.;:]+$/, "") });
  }
  const instructions = mentionInstructions(text, mentions);
  if (instructions) blocks.push({ type: "text", text: instructions });
  for (const image of attachments) {
    const { mimeType, data } = yield* c.kernel.call("image_data", { id: image.id });
    blocks.push({ type: "image", mimeType, data });
  }
  return blocks;
});
export function amendedInput(snapshot: import("convergence").InputSnapshot, id: string) {
  return snapshot.inputs.find((input) => input.id === id) ?? snapshot.inputs.filter((input) => input.intent === "steer" && input.state === "held").at(-1);
}

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.2.0latestOct 5, 2026>=2 <3105.1 KB5 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.