/** * ACP (Agent Client Protocol) harness adapter. * * Lets Agent-Native act as an ACP *client* and drive a local coding agent — * Gemini CLI, Claude Code, or any other ACP-compliant agent — through the * existing {@link AgentHarnessAdapter} substrate. The agent runs as a local * subprocess that owns its own loop, tools, and workspace filesystem access, * which is exactly the shape ACP was designed for. See: * https://agentclientprotocol.com * * Scope: this adapter targets *local* coding. The agent is spawned as a child * process and speaks newline-delimited JSON-RPC over stdio. It reuses whatever * local CLI login the agent already has (e.g. `gemini`/`claude` auth in the * user's home dir) by inheriting the parent environment. It is not a hosted or * sandboxed transport, and it is not a chat/A2A transport. * * The protocol transport and framing are handled by the official * `@zed-industries/agent-client-protocol` package, loaded lazily as an optional * dependency so apps that never use ACP do not pay for it. Everything in this * file beyond the thin spawn/connection glue is pure mapping logic between ACP * `session/update` notifications and {@link AgentHarnessEvent}s. */ import type { AgentHarnessAdapter, AgentHarnessEvent, AgentHarnessMessage, AgentHarnessPermissionMode } from "./types.js"; /** * The optional package that carries the ACP protocol transport. Loaded lazily; * `resolveAgentHarness` surfaces a clear install error when it is missing. */ export declare const ACP_PACKAGE = "@zed-industries/agent-client-protocol"; export interface AcpHarnessAdapterOptions { /** Adapter id, e.g. "acp:gemini". Defaults to "acp". */ name?: string; /** Human-readable label for pickers. */ label?: string; /** Short description for pickers and diagnostics. */ description?: string; /** Executable to spawn (the ACP agent binary), e.g. "gemini" or "npx". */ command?: string; /** Arguments passed to the agent binary, e.g. ["--experimental-acp"]. */ args?: string[]; /** * Extra environment variables for the agent process. Merged over the parent * environment, which the agent inherits so it can reuse the user's local CLI * login. */ env?: Record; /** Default working directory when a turn does not specify one. */ cwd?: string; /** Hint shown when the optional ACP package is missing. */ installPackage?: string; } export declare function createAcpHarnessAdapter(options: AcpHarnessAdapterOptions): AgentHarnessAdapter; /** Build the ACP prompt content blocks for a turn. */ export declare function buildAcpPromptBlocks(input: { prompt?: string; messages?: AgentHarnessMessage[]; }): Array<{ type: "text"; text: string; }>; /** * Translate a single ACP `session/update` payload into harness events. Pure and * stateless; the caller supplies a resolver for tool titles seen on earlier * `tool_call` updates so completion events can be labelled. */ export declare function acpUpdateToHarnessEvents(update: AcpSessionUpdate, resolvers?: ((toolCallId: string) => string | undefined) | { titleFor?: (toolCallId: string) => string | undefined; inputFor?: (toolCallId: string) => Record | undefined; }): AgentHarnessEvent[]; /** Extract displayable text from an ACP content block. */ export declare function acpContentBlockToText(block: AcpContentBlock | undefined): string; /** Derive file-change events from a tool call's `diff` content blocks. */ export declare function acpFileChangeEventsFromToolContent(content: AcpToolCallContent[] | undefined | null): AgentHarnessEvent[]; /** * Map an Agent-Native permission mode onto a decision for an ACP permission * request, using the tool-call kind the agent reports. Reads always run; edits * run under `allow-edits`; everything risky prompts unless `allow-all`. */ export declare function acpAutoPermissionDecision(kind: string | undefined, mode: AgentHarnessPermissionMode): "allow" | "prompt"; /** * Pick the option id to return for an ACP permission request. Prefers the * "once" variant so approvals do not silently become "always". */ export declare function selectAcpPermissionOption(options: AcpPermissionOption[], approved: boolean): string | undefined; /** * Resolve a path requested by the agent against the session workspace, refusing * anything that escapes it. The agent already has its own filesystem tools; * this `fs/*` surface is a scoped convenience, not an arbitrary read/write hole. */ export declare function resolveAcpWorkspacePath(cwd: string, requestedPath: string): string; interface AcpContentBlock { type: string; text?: string; uri?: string; name?: string; [key: string]: unknown; } interface AcpToolCallContent { type: string; content?: AcpContentBlock; path?: string; oldText?: string | null; newText?: string; terminalId?: string; } interface AcpPlanEntry { content?: string; status?: string; priority?: string; } export type AcpSessionUpdate = { sessionUpdate: "agent_message_chunk" | "user_message_chunk" | "agent_thought_chunk"; content: AcpContentBlock; } | { sessionUpdate: "tool_call"; toolCallId: string; title: string; kind?: string; status?: string; content?: AcpToolCallContent[]; rawInput?: Record; rawOutput?: Record; locations?: unknown[]; } | { sessionUpdate: "tool_call_update"; toolCallId: string; title?: string | null; kind?: string | null; status?: string | null; content?: AcpToolCallContent[] | null; rawInput?: Record; rawOutput?: Record; } | { sessionUpdate: "plan"; entries: AcpPlanEntry[]; } | { sessionUpdate: "available_commands_update"; availableCommands: unknown[]; } | { sessionUpdate: "current_mode_update"; currentModeId: string; }; interface AcpPermissionOption { optionId: string; name: string; kind: "allow_once" | "allow_always" | "reject_once" | "reject_always"; } export {}; //# sourceMappingURL=acp-adapter.d.ts.map