import type { Message, Provider, ThinkingLevel } from "@kenkaiiii/gg-ai"; import type { EventBus } from "../core/event-bus.js"; /** The ACP major version this mode implements. Bumped only for breaking changes. */ export declare const ACP_PROTOCOL_VERSION = 1; /** * The slice of {@link AgentSession} this mode uses. * * Narrowed to an interface so a test can drive the whole protocol without a * provider, credentials or a network — the transport is what is under test, * and a real model would make the frames non-deterministic. */ export interface AcpAgentSession { readonly eventBus: Pick; initialize(): Promise; prompt(content: string): Promise; getState(): { sessionId: string; provider: Provider; model: string; }; /** * Context accounting for the ACP `usage_update` notification. Optional so a * test double or an alternative session implementation need not carry token * accounting — a session without it simply reports no usage. */ getContextUsage?(): { used: number; size: number; costUsd?: number; }; dispose(): Promise; /** Replace the turn-cancellation signal so the session remains reusable. */ setSignal(signal: AbortSignal): void; /** Replay a session file from disk into this session. */ loadSession(sessionPath: string): Promise; /** The conversation as restored, used to replay history to the client. */ getMessages(): Message[]; switchModel(provider: string, model: string): Promise; getThinkingLevel(): ThinkingLevel | undefined; setThinkingLevel(level: ThinkingLevel | undefined): void; /** Plan mode is GG's session mode: read-only research until exit_plan. */ getPlanMode(): boolean; setPlanMode(active: boolean): Promise; /** Bake an approved plan into the prompt so [DONE:n] progress markers work. */ setApprovedPlan(planPath: string | undefined): Promise; /** * Registry commands (/model, /compact, …), including any an extension * registered during `initialize`. Optional so a test double need not carry a * registry — a session without one simply advertises no registry commands. */ readonly slashCommands?: { getAll(): { name: string; aliases: string[]; description: string; usage: string; }[]; }; } /** * The plan-mode callbacks the agent loop calls when the model uses the * `enter_plan` / `exit_plan` tools. * * Handed to the session factory rather than built inside it so a test double * can drive plan mode without a model: approving a plan is what turns it into * the client's to-do list, and that path is otherwise unreachable. */ export interface AcpPlanHooks { onEnterPlan: () => Promise; /** Returns the instruction handed back to the model after approval. */ onExitPlan: (planPath: string) => Promise; } export interface AcpModeOptions { provider: Provider; model: string; cwd: string; version: string; baseUrl?: string; systemPrompt?: string; thinkingLevel?: ThinkingLevel; /** Defaults to `process.stdin` / `process.stdout`. */ input?: NodeJS.ReadableStream; output?: NodeJS.WritableStream; /** * Builds the session for `session/new`. Overridden by tests; production * always gets a real {@link AgentSession}. */ createSession?: (signal: AbortSignal, hooks: AcpPlanHooks) => AcpAgentSession; } /** The selectors this agent exposes. Ids are part of the wire contract. */ export declare const MODEL_CONFIG_ID = "model"; export declare const THINKING_CONFIG_ID = "thinking"; export declare const MODE_CONFIG_ID = "mode"; /** * Turn a restored conversation into the `session/update` stream a client needs * to draw it. * * ACP has no "here is the transcript" response: a loaded session is replayed as * the same notifications a live turn produces, so the client needs no second * rendering path. Thinking is deliberately NOT replayed — it is transient by * design, and a wall of stale reasoning above a resumed conversation buries the * thing the user came back for. * * Each replayed chunk carries a `messageId` so a client can group chunks into * the messages they came from; ids are per-replay and positional, which is all * the protocol needs of them. */ export declare function historyUpdates(messages: readonly Message[]): Record[]; /** * Serve ACP on stdio until the input stream ends. * * Resolves when the client disconnects; the caller owns process exit. */ export declare function runAcpMode(options: AcpModeOptions): Promise; /** * CLI entry point: serve ACP on the real stdio, then exit. * * Split from {@link runAcpMode} so the protocol can be tested without the * process-level side effects (signal handlers, logger teardown, exit codes). */ export declare function runAcpModeCli(options: AcpModeOptions): Promise; //# sourceMappingURL=acp-mode.d.ts.map