import { PromptResult, ToolCallJSON, UserContentInput } from "smoltalk"; import type { DecisionPlan } from "./decision/questions.js"; import type { DecisionLog } from "../statelog/wireTypes.js"; import type { ProviderUsageKind as UsageKind } from "./invocationUsage.js"; import type { NormalizedLLMError, PromptConfig } from "./llmClient.js"; import type { LLMRetryReason, RetryPolicy } from "./llmRetry.js"; import type { StateStack } from "./state/stateStack.js"; import type { RuntimeContext } from "./state/context.js"; import { GraphState } from "./types.js"; import type { Run } from "./asyncContext.js"; export type DispatchResult = { completion: PromptResult; toolCalls: ToolCallJSON[]; /** Present on a decision call: the request and reply as the log records them. */ decision?: DecisionLog; }; /** Which usage kind a call books under: "decision" for a decision model, * "completion" for a text model. The one place that rule is spelled. */ export declare function usageKindFor(promptConfig: PromptConfig): UsageKind; /** Dispatch the LLM request and extract `{completion, toolCalls}`, * branching on the `stream` flag. Streaming uses `handleStreamingResponse` * to accumulate chunks; non-streaming awaits the single response Promise. * Throws on transport/protocol errors. */ export declare function dispatchLLMRequest({ run, ctx, promptConfig, prompt, stream, stateStack, decisionPlan, }: { run: Run; ctx: RuntimeContext; promptConfig: PromptConfig; prompt: string | UserContentInput; stream: boolean; stateStack?: StateStack; /** Present when this is a decision call. `dispatchWithRetry` decides * that once, before metering, and the plan is the only signal here. */ decisionPlan?: DecisionPlan; }): Promise; /** * Bound one LLM-call attempt by a per-call deadline. Returns a signal that * aborts (carrying a `callTimeout` cause) after `limitMs`, composed with the * parent (guard / Esc) signal so either source cancels the call. `limitMs <= 0` * means "no deadline" — the parent signal passes through unchanged. Structurally * a `TimeGuard`, scoped to a single call rather than a block. */ export declare function armCallTimeout(parentSignal: AbortSignal | undefined, limitMs: number): { signal: AbortSignal | undefined; dispose: () => void; }; type RetryHooks = { onRetry: (d: { attempt: number; maxRetries: number; delayMs: number; reason: LLMRetryReason; detail: string; }) => void | Promise; onTimeout: (d: { limitMs: number; attempt: number; }) => void | Promise; }; /** * Run `dispatch(signal)` under the retry policy. Each attempt is bounded by a * per-call timeout (armCallTimeout). On a classified-transient failure with * attempts remaining, fire onLLMRetry and wait a cancellable backoff, then * re-issue. A user/abort cause is always re-thrown untouched (never retried); * an exhausted provider error is converted by the catch ladder into a normal * Failure (we throw a plain Error so `try llm(...)` can handle it, rather than * a branded abort that would unwind the whole run). The policy decision lives * in the pure `decideRetry`; this loop is the thin driver. */ export declare function runWithRetry(dispatch: (signal: AbortSignal | undefined) => Promise, policy: RetryPolicy, parentSignal: AbortSignal | undefined, hooks: RetryHooks, normalizeError: (err: unknown) => NormalizedLLMError): Promise; /** * One LLM dispatch wrapped in the retry loop: builds the provider-neutral * error normalizer (from the active client) and the notification hooks, then * runs `dispatchLLMRequest` under `runWithRetry`. Kept out of `_runPrompt` so * that function stays focused. */ export declare function dispatchWithRetry(args: { run: Run; ctx: RuntimeContext; promptConfig: PromptConfig; prompt: string | UserContentInput; stream: boolean; retryPolicy: RetryPolicy; parentSignal: AbortSignal | undefined; stateStack?: StateStack; }): Promise; export {};