import type { AgentMessage, ThinkingLevel } from "@ch1nyzzz/pi-agent-core"; import { type AuthStorage, type ModelRegistry, type SessionStats, type ToolDefinition } from "@ch1nyzzz/pi-coding-agent"; export type ModelRunStreamEvent = { type: "text" | "thinking" | "tool-arguments"; delta: string; } | { type: "tool-call"; name: string; arguments: Record; } | { type: "tool-result"; name: string; text: string; isError: boolean; } | { type: "length-recovery"; attempt: number; maxAttempts: number; } | { type: "submission-retry"; attempt: number; maxAttempts: number; } | { type: "usage"; stopReason: string; input: number; output: number; cacheRead: number; cacheWrite: number; } | { type: "complete"; stopReason: string; }; /** * Typed result channel: the model delivers its result by calling a schema-validated * tool instead of emitting text for the orchestrator to parse. Schema violations and * `validate` rejections flow back to the model as tool errors, so retries happen * inside the session — free text is never a control signal. */ export interface ModelRunSubmission { toolName: string; description: string; parameters: ToolDefinition["parameters"]; /** * Optional semantic validation beyond the schema. Throw to reject the submission * (the model sees the message and can retry). A non-undefined return value * replaces the stored submission. */ validate?: (params: Record) => unknown | Promise; /** Reprompts when a run ends without a submission. Default 2; 0 disables reprompting. */ maxAttempts?: number; } export interface ModelRunRequest { cwd: string; agentDir?: string; systemPrompt: string; prompt: string; model?: string; thinkingLevel?: ThinkingLevel; history?: readonly AgentMessage[]; /** Explicit built-in/custom tool allowlist. Omit to run with no tools. */ tools?: string[]; /** * Execution budget per built-in read-family tool call (read/grep/find/ls). Headless * phases have no human to interrupt a runaway filesystem scan, so an over-budget call * is aborted and returned to the model as a tool error. Defaults to 120s. */ toolTimeoutMs?: number; customTools?: ToolDefinition[]; /** Structured result channel; when set, the run's result is the submitted object. */ submission?: ModelRunSubmission; /** Stable provider session identity used to reuse replay prompt caches. */ sessionIdentity?: string; /** * Prompt sent to the same session when a run stops with "length" (output space or * context window exhausted). The session compacts before this prompt is submitted, * so the retry runs against a freed window. Defaults to a generic finish-now prompt. */ recoveryPrompt?: string; /** Maximum recovery prompts after "length" stops. Defaults to 2; 0 disables recovery. */ maxLengthRecoveries?: number; signal?: AbortSignal; /** Receives the live headless-agent stream without retaining it in the model context. */ onStreamEvent?: (event: ModelRunStreamEvent) => void; /** * Receives the session stats (and active model, when known) exactly once, even when * the run fails — callers can persist usage for failed runs. */ onSessionStats?: (stats: SessionStats, model: { provider: string; id: string; } | undefined) => void; } export interface ModelRunResult { text: string; /** Validated object delivered through the submission tool, when one was requested. */ submission?: unknown; stats: SessionStats; model: { provider: string; id: string; }; } export interface ModelRunner { run(request: ModelRunRequest): Promise; } export interface PiModelRunnerOptions { /** Optional shared auth backend, primarily for embedded runtimes and tests. */ authStorage?: AuthStorage; /** Optional shared model registry, primarily for embedded runtimes and tests. */ modelRegistry?: ModelRegistry; } export declare function createPiModelRunner(options?: PiModelRunnerOptions): ModelRunner; //# sourceMappingURL=model-runner.d.ts.map