/** * AgentRunner is the Go ↔ Node-sidecar contract for the Claude Agent SDK loop. * Loopback only — never on a Service port. */ export interface AgentRunner { } export type TurnRequest_payload_start = { type: 'start'; data: StartTurn; }; export type TurnRequest_payload_toolResult = { type: 'toolResult'; data: ToolResult; }; export type TurnRequest_payload = TurnRequest_payload_start | TurnRequest_payload_toolResult; export type TurnRequest = { payload: TurnRequest_payload; }; export type StartTurn = { systemPrompt: SystemPrompt; /** * History as persisted, oldest first. How the runner seeds a session from it is its * own business — that decision must not need a wire change. */ history: HistoryMessage[]; tools: ToolDef[]; model: string; maxTurns: number; /** Correlation only: the runner never reads the chat, it just labels its logs. */ chatId: number; /** * A prior SDK session, when Go has one. Absent means seed from `history`, which stays * the fallback for every failure on this path. */ session: SdkSession; }; /** * SdkSession is the CLI's own transcript, verbatim and opaque: Go stores the lines and * hands them back, the runner is the only side that parses them. */ export type SdkSession = { sessionId: string; /** JSONL, one entry per line, oldest first */ lines: string[]; }; /** * Split because the split is what makes cross-session caching possible: joined into one * string, the SDK treats the whole prompt as session-specific. */ export type SystemPrompt = { /** identical for every chat and account */ static: string; /** per-chat / per-account blocks, never cached */ dynamic: string[]; }; export type HistoryRole = 'HISTORY_ROLE_UNSPECIFIED' | 'HISTORY_ROLE_USER' | 'HISTORY_ROLE_ASSISTANT' /** assistant turn that called tools */ | 'HISTORY_ROLE_TOOL_REQUEST' | 'HISTORY_ROLE_TOOL_RESULT' /** supersedes everything before it */ | 'HISTORY_ROLE_CONTEXT_COMPACT'; export type HistoryMessage = { role: HistoryRole; /** USER / ASSISTANT / CONTEXT_COMPACT */ text: string; /** TOOL_REQUEST */ toolCalls: ToolCall[]; /** TOOL_RESULT */ toolResult: ToolResult; }; /** * ToolDef carries the schema verbatim as JSON: it is what the MCP server the * runner stands up advertises, and Go stays the only owner of the tool surface. */ export type ToolDef = { name: string; description: string; inputSchemaJson: string; /** * Keep the schema out of the cached prompt prefix; the model reaches it through ToolSearch. * False = pinned, so a caller that never sets it gets today's behaviour. */ deferred: boolean; }; export type ToolCall = { id: string; name: string; argsJson: string; }; export type ToolResult = { id: string; content: string; isError: boolean; }; export type TurnEvent_payload_delta = { type: 'delta'; data: StreamDelta; }; export type TurnEvent_payload_assistantMessage = { type: 'assistantMessage'; data: AssistantMessage; }; export type TurnEvent_payload_toolCall = { type: 'toolCall'; data: ToolCall; }; export type TurnEvent_payload_done = { type: 'done'; data: TurnDone; }; export type TurnEvent_payload_sessionAppend = { type: 'sessionAppend'; data: SessionAppend; }; export type TurnEvent_payload_rateLimit = { type: 'rateLimit'; data: RateLimit; }; export type TurnEvent_payload_messageStarted = { type: 'messageStarted'; data: Usage; }; export type TurnEvent_payload = TurnEvent_payload_delta | TurnEvent_payload_assistantMessage | TurnEvent_payload_toolCall | TurnEvent_payload_done | TurnEvent_payload_sessionAppend | TurnEvent_payload_rateLimit | TurnEvent_payload_messageStarted; export type TurnEvent = { payload: TurnEvent_payload; }; /** * Projection of the client-facing StreamEventType, mapped in one place in Go * (TestRunnerEnumsMapExhaustively), minus the events no runner can produce. */ export type StreamEvent = 'STREAM_EVENT_UNSPECIFIED' | 'STREAM_EVENT_MESSAGE_START' | 'STREAM_EVENT_CONTENT_BLOCK_START' | 'STREAM_EVENT_TEXT_DELTA' | 'STREAM_EVENT_TOOL_USE_START' | 'STREAM_EVENT_TOOL_USE_DELTA' | 'STREAM_EVENT_TOOL_USE_RESULT' | 'STREAM_EVENT_CONTENT_BLOCK_STOP' | 'STREAM_EVENT_MESSAGE_DELTA' | 'STREAM_EVENT_MESSAGE_STOP' | 'STREAM_EVENT_THINKING_DELTA' | 'STREAM_EVENT_ERROR'; export type StreamDelta = { type: StreamEvent; content: string; }; /** * AssistantMessage is the whole model turn, sent once it is complete. Go persists * this instead of re-accumulating deltas, and records usage against it. */ export type AssistantMessage = { text: string; toolCalls: ToolCall[]; usage: Usage; /** mirrored to Mattermost, never persisted, never streamed */ thinking: string; }; /** * SessionAppend carries transcript lines the SDK wrote during this turn, in write order. A * session_id Go has not seen replaces the stored session: that is how a fresh session resets it. */ export type SessionAppend = { sessionId: string; lines: string[]; }; /** * RateLimit is the CLI's view of the subscription's windows — the only place the remaining * allowance is visible to us at all, and it arrives only on a subscription profile. */ export type RateLimit = { /** allowed | allowed_warning | rejected */ status: string; /** five_hour | seven_day | seven_day_opus | … */ window: string; /** percent of the window spent */ utilization: number; /** unix seconds; 0 when the CLI did not say */ resetsAt: number; }; export type Usage = { model: string; inputTokens: number; outputTokens: number; cacheCreationInputTokens: number; cacheReadInputTokens: number; }; export type TurnDone = { stopReason: string; /** empty on success */ error: string; turns: number; turnCapHit: boolean; /** Turn totals from result.modelUsage; AssistantMessage.usage is a message_start snapshot. */ usage: Usage; };