/** * QueryRunner — The core runtime class that implements the Query interface. * * QueryRunner is an AsyncGenerator that the consumer * iterates via `for await (const msg of query)`. Internally it: * * 1. Runs a background message routing loop (readMessages) that reads * from the Transport and dispatches messages: * - control_response → resolves pending request Promises * - control_request → dispatches to handlers (permissions, hooks, MCP, etc.) * - control_cancel → aborts pending handler via AbortController * - keepalive / streamlined summaries → silently skipped * - result → recorded, optionally closes stdin for single-turn * - everything else → enqueued to the consumer's PushQueue * * 2. Manages the bidirectional control protocol: * - request(payload) sends a control request and returns a Promise * that resolves when the CLI responds with a matching request_id * - handleControlRequest() dispatches inbound requests from the CLI * * 3. Implements all Query interface methods for the consumer. */ import { type HostActionParams } from '../types/host-action.js'; import type { HostActionEvent } from '../protocol/feedback.js'; import { type DiagnosticsSink } from '../core/sdk-diagnostics.js'; import type { ModelPromptPatches } from '../protocol/model-prompt-patches.js'; import type { Transport } from '../core/transport.js'; import type { SDKMessage, SDKUserMessage } from '../types/messages.js'; import type { InternalQuery, OnElicitation, RemoteProjectionCheckpoint, RemoteProjectionEnableOptions } from '../types/options.js'; import type { FetchJobToken, FetchServiceAccountToken } from '../types/auth.js'; import type { SDKPlanModeSnapshot, SDKGoalSnapshot, SDKGoalStatus, SDKControlInterruptResponse, SDKControlInitializeResponse, SDKControlGetContextUsageResponse, SDKControlGenerateSessionTitleResponse, AskSideQuestionOptions, SideQuestionResult, SDKControlAddDirectoriesResponse, SDKControlReloadPluginsResponse, SDKControlReloadSkillsResponse } from '../types/control.js'; import type { PermissionMode, CanUseTool } from '../types/permissions.js'; import type { HookCallbackMatcher } from '../types/hooks.js'; import type { HookEvent as InternalHookEvent } from '../protocol/index.js'; import type { McpServerConfig, McpServerStatus, McpSetServersResult, OAuthToken } from '../types/mcp.js'; import type { McpToolRuntimeOverride } from '../protocol/mcp.js'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { SdkMcpTransport } from '../mcp/sdk-mcp-transport.js'; import { type PendingMcpResponse } from '../mcp/mcp-handler.js'; import type { AgentDefinition, AgentInfo } from '../types/agents.js'; import type { SessionStore, SessionStoreFlush } from '../session/session-store.js'; import type { PluginDetails } from '../types/plugins.js'; import type { ModelInfo, SlashCommand, AccountInfo, UsageInfo } from '../types/common.js'; import type { ModelPolicyProvider } from '../types/model-policy-provider.js'; import type { MemoryRuntimeCallbacks, SerializableMemoryConfig } from '../types/memory.js'; import type { SkillEvolutionRuntimeCallbacks, SerializableEvolutionConfig } from '../types/skill-evolution.js'; import type { ResolveSessionArtifacts } from '../types/artifacts.js'; import type { BYOKModelValidationInput, BYOKProviderInfo, ByokConfigCheckResult, ByokConfigInfo, ByokConfigReference, CheckByokConfigInput, CreateByokConfigInput, DeleteByokConfigInput, UpdateByokConfigInput } from '../types/byok.js'; /** Init config passed to the initialize control request. */ type InitConfig = { systemPrompt?: string; appendSystemPrompt?: string; modelRequestPatches?: ModelPromptPatches; agents?: Record; skills?: string[]; planMode?: boolean; promptSuggestions?: boolean; hostActions?: Record; goalMaxTurns?: number; enableFileCheckpointing?: boolean; memory?: SerializableMemoryConfig; evolution?: SerializableEvolutionConfig; customContext?: Record; /** Keep Permission and Plan independent on shared-daemon control calls. */ independentPlanModeControls?: boolean; /** Initial shared-daemon Permission, applied as part of initialize. */ permissionMode?: PermissionMode; /** Resolves transport-specific initialization settings before initialize. */ beforeInitialize?: () => Promise; /** * 远端创建的会话:不向 worker 发 initialize 控制帧, * 初始化结果从流中的 init 帧解析(daemon 侧负责驱动 worker 初始化)。 */ resolveInitializationFromStream?: boolean; /** Resolve initialization only after the Fork transcript is durable. */ requireSessionStoreForkBarrier?: boolean; }; export declare class QueryRunner implements InternalQuery { private readonly hostActionDirect; private static readonly CUSTOM_CONTEXT_CAPABILITY; private static readonly SELECTED_SKILLS_CAPABILITY; private static readonly INITIALIZE_TIMEOUT_MS; private static readonly BACKGROUND_TASKS_CAPABILITY; private static readonly SIDE_QUESTION_CAPABILITY; private static readonly GOAL_CAPABILITY; private static readonly GOAL_MAX_TURNS_CAPABILITY; private static readonly PLAN_MODE_CAPABILITY; private static readonly SESSION_STORE_FORK_BARRIER_CAPABILITY; private static readonly HOST_ACTION_CAPABILITY; private static readonly BYOK_CONFIG_MANAGEMENT_CAPABILITY; private static readonly REMOTE_PROJECTION_REQUEST_ID_PREFIX; private readonly transport; private readonly inputStream; private readonly pendingRequests; private readonly pendingInboundRequests; private readonly hooks; private readonly hookCallbacks; private nextHookCallbackId; private readonly sdkMcpServers; private readonly sdkMcpTransports; private readonly pendingMcpResponses; private readonly sdkMcpToolOverrides; private readonly isSingleTurn; private readonly canUseTool?; private readonly abortController?; private readonly initConfig; private readonly onElicitation?; private readonly onAuthExpired?; private readonly fetchJobToken?; private readonly fetchServiceAccountToken?; private readonly diagnostics?; private readonly controlRequestTimeoutMs; private readonly resolveModel?; private readonly resolveModelTimeoutMs; private readonly transcriptMirrorBatcher?; private readonly memoryCallbacks?; private readonly skillEvolutionCallbacks?; private readonly hostActionFallback?; private readonly resolveSessionArtifacts?; private resolveStreamInitialization; private initResponse?; private latestCommands; private initializationPromise?; private resultMessage?; /** * True only while the latest completed turn is an error result and no newer * user or assistant turn has started. A following exit code 1 is the shell * status for that structured result, not a second SDK failure. */ private pendingErrorResultExit; private readLoopPromise?; private closed; private authExpiredFired; private protocolHandshakeValidated; private cliCapabilities?; private customContextCapabilityWarningEmitted; private firstResultReceived; private firstResultReceivedResolve?; private memoryFlushPromise?; private endInputFlushPromise?; private skillEvolutionFlushPromise?; private closePromise?; private sessionStoreForkBarrierComplete; private inputEnded; constructor(transport: Transport, isSingleTurn: boolean, canUseTool?: CanUseTool, hooks?: Partial>, abortController?: AbortController, sdkMcpServers?: Map, initConfig?: InitConfig, onElicitation?: OnElicitation, diagnostics?: DiagnosticsSink, onAuthExpired?: () => void, controlRequestTimeoutMs?: number, sdkMcpTransports?: Map, pendingMcpResponses?: Map, fetchJobToken?: FetchJobToken, resolveModel?: ModelPolicyProvider, resolveModelTimeoutMs?: number, sessionStore?: SessionStore, sessionStoreFlush?: SessionStoreFlush, sdkMcpToolOverrides?: Record>, fetchServiceAccountToken?: FetchServiceAccountToken, memoryCallbacks?: MemoryRuntimeCallbacks, skillEvolutionCallbacks?: SkillEvolutionRuntimeCallbacks, resolveSessionArtifacts?: ResolveSessionArtifacts, hostActionFallback?: (event: HostActionEvent) => Promise, hostActionDirect?: boolean); private getRecord; private normalizeLogPreview; private extractMessagePreview; private getMessagePreviewSuffix; private getMessageType; private getMessageSubtype; private getMessageUuid; private recordInboundSessionMessage; private recordOutboundSessionMessage; [Symbol.asyncIterator](): AsyncGenerator; next(): Promise>; return(): Promise>; throw(e?: unknown): Promise>; /** * Reads messages from the transport and routes them. * * This runs as a background task for the lifetime of the query. * When the transport's readMessages generator completes (process exited), * this method finishes and signals the consumer queue. */ private readMessages; private isStructuredResultExit; private notifyAuthExpiredIfNeeded; private dispatchMemoryCallbacks; private dispatchSkillEvolutionCallbacks; private flushBeforeEndInput; private performFlushBeforeEndInput; private endTransportInput; /** * Send a control request to the CLI and wait for the response. * * Enforces an upper-bound `controlRequestTimeoutMs` so a stuck cli * can't wedge consumers indefinitely — on timeout the pending Promise * rejects AND a `control_cancel_request` is written to let the cli * clean up. Pass `timeoutMs: 0` to opt a specific call out of the * timeout (useful for long-running operations like bulk restarts). * * @param payload - The inner request payload * @param opts.timeoutMs - Override the default timeout (0 disables) * @returns The response data from the CLI * @throws Error if the CLI responds with an error, the transport * closes, or the timeout elapses. */ private request; /** * Handle an inbound control response from the CLI. * * Resolves or rejects the pending Promise associated with the request_id. */ private handleControlResponse; private processPendingPermissionRequests; /** * Handle an inbound control request from the CLI. * * The CLI sends control requests for: * - Permission prompts * - Hook callbacks * - MCP message routing * - Elicitation requests */ private handleControlRequest; /** * Cancel a pending inbound control request. * * The CLI sends this when it no longer needs a response (e.g., user * interrupted while a permission prompt was pending). */ private handleControlCancelRequest; private throwIfAborted; /** * Validate the wire-protocol version handshake against the * `system/init` message. * * Throws ProtocolVersionMismatchError on cross-major mismatch. Logs a * warning when the CLI is older than the SDK's minor version (some new * fields may be missing) or when the field is absent (older CLI build * predating the handshake). */ private validateProtocolHandshake; private awaitAbortable; /** * Dispatch an inbound control request to the appropriate handler. * * @param req - The control request from the CLI * @param signal - AbortSignal for cancellation * @returns The response data to send back */ private processControlRequest; /** * Send the initialize control request and wait for the response. * * This must be called before iterating messages. It sends the * initialization configuration (system prompt, agents, etc.) to the * CLI and waits for the system init message. */ initialize(): Promise; private performInitialize; private completeSessionStoreForkBarrier; private flushTranscriptMirrorForLifecycle; private invokeRegisteredHookCallback; /** * Get the cached initialization response. * * Returns a Promise that resolves when the initialization response * is available, matching the Query interface contract. */ initializationResult(): Promise; private replaceLatestCommands; private getLatestCommands; /** 远端创建的会话:等流中的 init 帧,不向 worker 发 initialize。 */ private waitForStreamInitialization; /** * Stream user messages into the session. * * Consumes an async iterable of user messages and writes each one * to the transport as JSONL. This is used for multi-turn conversations * where the caller provides messages dynamically. */ streamInput(stream: AsyncIterable): Promise; /** * Interrupt the current operation. */ interrupt(): Promise; sendHostAction(params: HostActionParams): Promise; /** * Drop a UUID-stamped async user message while it is still queued. */ cancelAsyncMessage(messageUuid: string): Promise; /** Stop one task without aborting the active main-session turn. */ stopTask(taskId: string): Promise; /** Move one or all eligible foreground tasks into the background. */ backgroundTasks(toolUseId?: string): Promise; /** * Create, redirect, transition, or re-budget the session goal. * * Omitted fields are left unchanged; `creditsBudget: null` explicitly * clears the credits budget. Setting `status: 'active'` while the session * is idle starts the goal loop. Returns the goal snapshot after the change * (null only if no goal exists afterwards). */ setGoal(params: { objective?: string; status?: SDKGoalStatus; creditsBudget?: number | null; }): Promise; setGoalMaxTurns(maxTurns: number | null): Promise; /** Read the current goal, or null when the session has none. */ getGoal(): Promise; /** Clear the session goal. Returns whether a goal was actually cleared. */ clearGoal(): Promise; /** Enter or leave Plan Mode without changing the current permission mode. */ setPlanMode(active: boolean): Promise; /** Read the authoritative Plan Mode state from the running CLI session. */ getPlanMode(): Promise; private requireCliCapability; /** * Set the permission mode. */ setPermissionMode(mode: PermissionMode): Promise; private waitForFirstResult; /** * Set the model. */ setModel(model?: string): Promise; /** 启用当前 worker 会话的 Remote Control 事件投影。 */ enableRemoteProjection(remoteSessionId: string, options?: RemoteProjectionEnableOptions): Promise; /** 关闭当前 worker 会话的 Remote Control 事件投影。 */ disableRemoteProjection(options?: { timeoutMs?: number; }): Promise; setProxy(proxy?: string | null): Promise; /** * Generate a concise display title for the current session. */ generateSessionTitle(description: string, options?: { persist?: boolean; }): Promise; askSideQuestion(question: string, options?: AskSideQuestionOptions): Promise; /** * Add directories to the running session workspace. */ addDirectories(directories: string[]): Promise; /** * Apply flag settings. */ applyFlagSettings(settings: import('../types/settings.js').Settings): Promise; /** * Get supported slash commands. */ supportedCommands(): Promise; /** * Fetch available models from the CLI in real-time. * Sends a `get_models` control request; the CLI responds with the * current model catalog filtered by the catalog's default scene * (set at CLI process boot via the `QODER_SCENE` env var). */ getAvailableModels(options?: { fetchStrategy?: 'live' | 'cache'; uid?: string; outerProviders?: string[]; }): Promise; /** * List the available BYOK (Bring Your Own Key) providers and their supported models. * The CLI in turn queries the server-side BYOK provider catalog (cached for 5 min). * * Returns `null` if BYOK is disabled or the CLI does not support this request. */ listByokProviders(): Promise; /** * Validate a BYOK provider/model/API-key combination through the CLI. */ validateByokModel(input: BYOKModelValidationInput): Promise; listByokConfigs(): Promise; createByokConfig(input: CreateByokConfigInput): Promise; updateByokConfig(input: UpdateByokConfigInput): Promise; deleteByokConfig(target: DeleteByokConfigInput): Promise; checkByokConfig(input: CheckByokConfigInput): Promise; /** * Get supported agents. */ supportedAgents(): Promise; /** * Get account info. * * Always re-queries the CLI so callers see the freshest fields — the CLI * fills in `email` / `organization` asynchronously after device-flow login, * and a stale init-time snapshot can leave the SDK with only `userId`. * Falls back to the initialization snapshot when the CLI is older and does * not implement the `account_info` control request. */ accountInfo(): Promise; /** * Get MCP server status. */ mcpServerStatus(): Promise; /** * Get context usage information. */ getContextUsage(): Promise; /** * Get account quota and usage information. */ getUsageInfo(): Promise; /** * Reload plugins. */ reloadPlugins(): Promise; reloadSkills(): Promise; listPlugins(): Promise; /** * Rewind files to a previous user message. */ rewindFiles(userMessageId: string, options?: { dryRun?: boolean; }): Promise; /** * Rewind the active conversation branch, its file checkpoints, or both. */ rewind(userMessageId: string, options?: { scope?: import('../types/session.js').RewindScope; dryRun?: boolean; }): Promise; /** * Seed read state for a file. */ seedReadState(path: string, mtime: number): Promise; flushMemory(): Promise; flushSkillEvolution(): Promise; private performSkillEvolutionFlush; private requireSkillEvolutionEnabled; private performMemoryFlush; refreshMemory(): Promise; private requireSdkMemoryEnabled; /** * Reconnect an MCP server. */ reconnectMcpServer(name: string): Promise; /** * Toggle an MCP server on/off. */ toggleMcpServer(name: string, enabled: boolean): Promise; /** * Set MCP servers configuration. */ setMcpServers(servers: Record): Promise; /** * Inject an OAuth token for an MCP server. **InternalQuery-only.** * * Skips the standard OAuth flow and writes a host-supplied token straight * into the cli's token store, then reconnects the server. The host is * fully responsible for token validity (scope, expiry, refresh). Public * code should use {@link mcpAuthenticate} + {@link mcpSubmitOAuthCallbackUrl} * instead. */ injectMcpToken(name: string, token: OAuthToken): Promise; /** * Initiate an OAuth flow for an MCP server and let the host drive the * user-agent step. * * Two outcomes: * - `{ requiresUserAction: false }` — cli completed silently via cached * client + valid refresh token. The host should NOT show any UI. * - `{ authUrl, requiresUserAction: true }` — host needs to open the URL * (browser, Electron window, manual paste) and then call * {@link mcpSubmitOAuthCallbackUrl} once the redirect is captured. * * `redirectUri` is optional and overrides the OAuth redirect target * (Electron custom protocol, enterprise callback host, etc.). */ mcpAuthenticate(serverName: string, redirectUri?: string): Promise<{ authUrl?: string; requiresUserAction: boolean; }>; /** * Submit a pasted-back OAuth callback URL for a flow previously started * with {@link mcpAuthenticate}. The cli extracts the authorization code, * validates the state parameter, completes token exchange, and reconnects * the server. */ mcpSubmitOAuthCallbackUrl(serverName: string, callbackUrl: string): Promise; /** * Delete any stored OAuth credentials for a server and force a reconnect. * Use to "sign out" of an MCP server — the next tool call will re-trigger * auth. */ mcpClearAuth(serverName: string): Promise; /** * Close the query session. * * Closes the transport, rejects pending requests, and signals the * consumer queue that no more messages will arrive. */ close(): Promise; private performClose; /** * Async dispose support. * * Allows using the QueryRunner with `await using`: * ```ts * await using query = createQuery(...); * for await (const msg of query) { ... } * ``` */ [Symbol.asyncDispose](): Promise; } export {};