import type { StoreEventEmitter } from '../store/event-emitter.js'; import type { PDRuntimeAdapter, RuntimeKind, RuntimeCapabilities, RuntimeHealth, RunHandle, RunStatus, StartRunInput, StructuredRunOutput, RuntimeArtifactRef } from '../runtime-protocol.js'; /** Output path strategy for structured output (PRI-271 B3). */ export type OutputPathStrategy = 'tool_call_first' | 'json_mode_first' | 'free_form_only'; /** Result of a specific output path attempt (PRI-271 B3). */ export type OutputPathLabel = 'tool_call' | 'json_object_mode' | 'free_form_with_repair'; /** * Configuration for PiAiRuntimeAdapter. * * provider, model, apiKeyEnv — required, consumed from workflows.yaml policy. * maxRetries, timeoutMs — optional overrides with sensible defaults. */ export interface PiAiRuntimeAdapterConfig { /** LLM provider name (e.g., 'openrouter', 'anthropic'). Must be a valid KnownProvider. */ provider: string; /** Model ID (e.g., 'anthropic/claude-sonnet-4'). */ model: string; /** Name of the environment variable containing the API key. */ apiKeyEnv: string; /** Maximum retry attempts for transient LLM failures. Default: 2. */ maxRetries?: number; /** Timeout in milliseconds for LLM completion. Default: 300_000 (5 min). */ timeoutMs?: number; /** Custom base URL for OpenAI-compatible providers not in pi-ai's built-in registry. */ baseUrl?: string; /** Optional workspace directory (reserved for future use). */ workspace?: string; /** Optional StoreEventEmitter for telemetry. Falls back to global storeEmitter. */ eventEmitter?: StoreEventEmitter; /** Reasoning/thinking level. Set to false to disable thinking for models that enable it by default. Default: undefined (use model default). */ reasoning?: 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | false; /** * Output path strategy for structured output (PRI-271 B3). * - 'tool_call_first': Try tool calling → JSON mode → free-form + repair (default) * - 'json_mode_first': Try JSON mode → free-form + repair (skip tool calling) * - 'free_form_only': Only use current free-form + repair path */ outputPathStrategy?: OutputPathStrategy; /** Maximum repair attempts for structured output repair loop (PRI-271 A1). Default: 3. */ maxRepairAttempts?: number; /** * Explicit profile-level completion budget override (PRI-621). * When unset, the budget is delegated to pi-ai's native defaulting * (`min(model.maxTokens, 32000)` + thinking-budget management) instead of * a PD-side heuristic cap. */ maxTokens?: number; /** * Optional profile-level system prompt (append layer, PRI-633). * Appended AFTER the run's base-layer systemPrompt (from * `StartRunInput.systemPrompt`, produced by the run's prompt builder) and * sent via pi-ai Context.systemPrompt — enabling Anthropic system-prompt * caching and OpenAI developer-role priority. When neither layer is present, * behavior is unchanged (no systemPrompt field in Context). Semantics per * DPB-07 as revised by PRI-633: the profile remains the owner of this * append-only configuration surface. */ systemPrompt?: string; /** Internal override for the retry delay backoff, primarily for fast unit testing. */ _testBackoffDelayMs?: number; } export declare class PiAiRuntimeAdapter implements PDRuntimeAdapter { private readonly config; private readonly runs; private readonly eventEmitter; private readonly runtimeKind; private readonly defaultCapabilities; constructor(config: PiAiRuntimeAdapterConfig); kind(): RuntimeKind; /** * Resolve the effective max_tokens budget for LLM calls. * * PRI-621: pass through ONLY the explicit profile config. When unset, the * budget is left to pi-ai's native defaulting — `options.maxTokens ?? * min(model.maxTokens, 32000)` with thinking-budget management that keeps * answer tokens available when chain-of-thought shares the ceiling. The old * heuristic (forced 4096, or 16K when `/deepseek/i` matched the PROVIDER * name) misfired on relays (provider "Bai" serving deepseek-v4-flash got * the 4096 cap that BUG-007a was written to prevent) and bypassed pi-ai's * catalog metadata entirely. Catalog-first resolveModel() now supplies the * correct per-model ceiling, so the heuristic is retired. */ private resolveMaxTokens; getCapabilities(): Promise; /** * Three-stage health probe (per M6 lesson: binary/list-only checks are fake probes). * * 1. apiKey exists in environment * 2. getModel validates without throwing * 3. Minimal complete probe with {"ok":true} verification */ healthCheck(): Promise; /** * One-shot run: call LLM via pi-ai complete(), parse and validate output. * Blocks until LLM responds (or times out). Run is terminal on return. * * Timeout priority: input.timeoutMs (from runner) > this.config.timeoutMs (from workflows.yaml) > 300_000 (default) * The resolved effectiveTimeoutMs is passed through to completeWithRetry and pi-ai complete() * so that the provider request timeout always matches the runner's intent. */ startRun(input: StartRunInput): Promise; pollRun(runId: string): Promise; cancelRun(runId: string): Promise; fetchOutput(runId: string): Promise; fetchArtifacts(runId: string): Promise; /** * Path 1: Tool calling (PRI-271 B2). * * Passes a schema-derived tool definition via context.tools and injects * `tool_choice: 'required'` via onPayload. If the provider supports tool * calling, the response contains ToolCall content blocks with pre-parsed * arguments that we validate against the schema. * * PRI-284: Tool definition uses params.schema (per-runner) instead of * hardcoded DiagnosticianOutputV1Schema. */ private tryToolCallPath; /** * Path 2: JSON mode (PRI-271 B1). * * Injects `response_format: { type: 'json_object' }` via onPayload * to force the provider to output valid JSON. Then parses and validates. */ private tryJsonModePath; /** * Emit output_path_chosen telemetry (PRI-271 B3). * * Every path selection and fallback emits structured telemetry. * `path` is set when a path succeeds; null when recording a fallback reason. */ private emitOutputPathTelemetry; /** * Make a single LLM call for output repair (PRI-71). * Returns extracted text response or null if no content. * Reuses same provider/model/apiKey as the original call. * * Uses an independent AbortSignal (fixed 60s timeout) to avoid the repair * call immediately timing out when the original call consumed most of the * original timeout budget (e.g., 5min original → 4m50s elapsed → 10s left). */ private repairLLMCall; /** * Call pi-ai complete() with retry and exponential backoff. * Disables pi-ai built-in retry (maxRetries: 0) to avoid double-retry. */ private completeWithRetry; private emitAttemptTelemetry; } //# sourceMappingURL=pi-ai-runtime-adapter.d.ts.map