Official
acp
ACP agents from the ACP registry (Gemini, Cursor, Droid, Kilo, pi, ...), Oh My Pi, and your own entries (custom.json in the plugin's data folder). Agents are discovered at runtime.
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/acp@0.2.0
Permissions in 0.2.0
Take care. This plugin asks for permissions that can do anything your account can. The app asks you to hold Enable for two seconds or to type the plugin's name before it turns on.
Files
wire.ts3.3 KB
// ACP JSON-RPC boundary schemas. ACP is forward compatible, so the
// records are loose while every field consumed by the provider is parsed.
import * as z from "zod";
const unknownRecord = z.looseObject({});
const string = z.string().nullish();
const number = z.number().nullish();
const capabilities = z.looseObject({
loadSession: z.boolean().optional(),
promptCapabilities: z
.looseObject({
image: z.boolean().optional(),
audio: z.boolean().optional(),
embeddedContext: z.boolean().optional(),
})
.nullish(),
mcpCapabilities: z.looseObject({ http: z.boolean().optional() }).nullish(),
sessionCapabilities: z
.looseObject({
list: z.unknown().optional(),
fork: z.unknown().optional(),
resume: z.unknown().optional(),
close: z.unknown().optional(),
additionalDirectories: z.unknown().optional(),
})
.nullish(),
});
const authMethod = z.looseObject({
id: z.string(),
name: string,
description: string,
type: string,
args: z.array(z.unknown()).nullish(),
});
const agentInfo = z.looseObject({ name: string, title: string, version: string });
export const message = z.looseObject({
sessionId: string,
sessionUpdate: string,
promptId: string,
elicitationId: string,
terminalId: string,
toolCallId: string,
path: string,
content: z.unknown().nullish(),
line: number,
limit: number,
mode: string,
url: string,
command: z.unknown().optional(),
cwd: string,
outputByteLimit: z.unknown().optional(),
args: z.unknown().optional(),
env: z.unknown().optional(),
options: z.array(unknownRecord).nullish(),
toolCall: unknownRecord.nullish(),
requestedSchema: unknownRecord.nullish(),
message: string,
_meta: unknownRecord.nullish(),
});
const catalog = z.looseObject({ currentModeId: string, availableModes: z.array(unknownRecord).nullish() });
const models = z.looseObject({ currentModelId: string, availableModels: z.array(unknownRecord).nullish() });
const session = z.looseObject({
sessionId: string,
cwd: string,
title: string,
updatedAt: string,
modes: catalog.nullish(),
models: models.nullish(),
configOptions: z.array(unknownRecord).nullish(),
});
const responseSchemas = {
initialize: z.looseObject({
protocolVersion: z.number().nullish(),
agentCapabilities: capabilities.nullish(),
authMethods: z.array(authMethod).nullish(),
agentInfo: agentInfo.nullish(),
_meta: unknownRecord.nullish(),
}),
"session/new": session,
"session/resume": session,
"session/load": session,
"session/fork": session,
"session/list": z.looseObject({ sessions: z.array(session).nullish(), nextCursor: string }),
"session/prompt": z.looseObject({ stopReason: string, usage: unknownRecord.nullish() }),
"session/set_mode": z.unknown(),
"session/set_model": z.unknown(),
"session/set_config_option": z.looseObject({ configOptions: z.array(unknownRecord).nullish() }),
"session/close": z.unknown(),
authenticate: z.unknown(),
logout: z.unknown(),
} satisfies Record<string, z.ZodType>;
export const responses: {
[M in keyof typeof responseSchemas]: z.ZodType<z.infer<(typeof responseSchemas)[M]>>;
} = responseSchemas;
export type Message = z.infer<typeof message>;
export type Response<M extends keyof typeof responses> = z.infer<(typeof responses)[M]>;Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 94.9 KB | 6 permissions | Listed |
No comments yet.