import type { RateLimiter } from "./rate-limiter.js"; import type { ToolDef } from "./tools.js"; export type ModelMessageRole = "system" | "user" | "assistant" | "tool"; export interface ModelMessage { role: ModelMessageRole; content: string; name?: string; toolCallId?: string; /** Tool definitions introduced at this result boundary for cache-safe deferred loading. */ addedToolNames?: string[]; toolCalls?: ModelToolCall[]; } export interface ModelToolCall { id: string; name: string; input: unknown; } export interface ModelToolSchema { name: string; description?: string; inputSchema?: unknown; } /** * Reasoning-effort input level, ordered from least to most thinking. Maps to * each provider's native control (Workers AI / OpenAI `reasoning_effort`, * Anthropic `thinking.budget_tokens`, Gemini `thinkingConfig`). `'off'` (the * default when unset) requests no reasoning. Providers that don't support * reasoning ignore the level — see `ModelMetadata.supportsReasoning`. */ export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high" | "xhigh"; export interface ModelRequest { model?: string; messages: ModelMessage[]; tools?: ModelToolSchema[]; maxToolCalls?: number; signal?: AbortSignal; /** * Requested reasoning effort for this call. Stamped by the loop from the * agent/session/prompt scope chain. Reasoning-capable providers map it to * their native control; others ignore it. */ thinkingLevel?: ThinkingLevel; /** * Opaque provider affinity key forwarded as `sessionId` where the * underlying API supports it (e.g. AWS Bedrock prompt caching). */ sessionId?: string; } export interface ModelResponse { message?: ModelMessage; toolCalls?: ModelToolCall[]; usage?: ModelUsage; /** * Reasoning / thinking content emitted by reasoning-capable models * (Anthropic extended thinking, OpenAI o-series reasoning summaries, * Gemini thought summaries). Optional; absent on non-reasoning providers. */ thinking?: string; } export interface ModelUsage { inputTokens?: number; outputTokens?: number; totalTokens?: number; costUsd?: number; /** Tokens read from the provider's prompt cache (Anthropic prompt caching). */ cachedInputTokens?: number; /** Tokens written to the provider's prompt cache during this call. */ cacheWriteTokens?: number; /** Audio tokens consumed by a Realtime / voice provider on the input side. */ audioInputTokens?: number; /** Audio tokens generated by a Realtime / voice provider on the output side. */ audioOutputTokens?: number; /** Audio seconds processed by a streaming STT provider (pipeline-mode voice). */ sttSeconds?: number; /** Characters synthesized by a streaming TTS provider (pipeline-mode voice). */ ttsCharacters?: number; /** * Attribution dimensions for cost tracking. Stamped by the loop from * the agent/session/model/provider/turn context. */ attribution?: import("./cost-budget.js").CostAttribution; } export interface ModelStreamChunk { /** Incremental output text content. */ textDelta?: string; /** Incremental thinking / reasoning content. */ thinkingDelta?: string; /** Live-only fragment of a tool call's JSON argument text. */ toolCallDelta?: { toolCallId: string; toolName: string; argumentTextDelta: string; }; /** * Final aggregated response — emitted exactly once at the end of the stream. * Includes the assembled message, tool calls, and usage. Consumers typically * use earlier `textDelta` chunks for live UI and the `done` payload for * persistence + cost telemetry. */ done?: ModelResponse; } export interface ModelMetadata { provider?: string; model?: string; contextWindowTokens?: number; maxOutputTokens?: number; supportsTools?: boolean; /** Whether the model accepts a reasoning-effort control (gates `thinkingLevel`). */ supportsReasoning?: boolean; gateway?: string; } export interface ModelProvider { name: string; generate(request: ModelRequest): Promise; /** Optional provider/model metadata used for context budgeting and routing UIs. */ getModelMetadata?(model?: string): ModelMetadata | undefined; /** * Optional: stream incremental chunks. Loop falls back to `generate()` * when this is absent. Implementations MUST emit a final chunk with * `done` populated so downstream code can persist usage and cost. */ stream?(request: ModelRequest): AsyncIterable; } export interface ModelRuntimeOptions { timeoutMs?: number; retries?: number; retryDelayMs?: number; signal?: AbortSignal; onAttempt?: (attempt: ModelAttemptEvent) => void | Promise; } export interface ModelAttemptEvent { provider: string; /** Provider-resolved model id (`request.model ?? defaultModel`). */ model?: string; attempt: number; maxAttempts: number; status: "start" | "success" | "retry" | "error"; durationMs?: number; error?: string; usage?: ModelUsage; } export interface OpenAICompatibleProviderOptions { name?: string; baseUrl: string; apiKey: string; defaultModel?: string; /** Static headers or headers resolved immediately before each request. */ headers?: Record | (() => Record | Promise>); /** * Optional per-request bearer token resolver. When set, it is awaited on every request and used * in place of `apiKey` for the `authorization` header. Required for providers whose credentials * rotate (e.g. Databricks OAuth principal tokens) so long-lived agents don't pin a stale token. */ tokenProvider?: () => string | Promise; /** Fetch implementation for tests, custom transports, and private-network enforcement. */ fetchImpl?: typeof fetch; /** Optional rate limiter. Acquire one token per request, keyed by `:`. */ rateLimiter?: RateLimiter; } export interface AnthropicProviderOptions { name?: string; baseUrl?: string; apiKey: string; defaultModel?: string; headers?: Record; maxTokens?: number; /** Optional rate limiter. Acquire one token per request. */ rateLimiter?: RateLimiter; } export interface AzureOpenAIProviderOptions { name?: string; baseUrl: string; apiKey: string; deployment: string; apiVersion?: string; headers?: Record; } export interface GeminiProviderOptions { name?: string; baseUrl?: string; apiKey: string; defaultModel?: string; headers?: Record; } export interface VertexAIProviderOptions { name?: string; project: string; location?: string; accessToken: string; defaultModel?: string; headers?: Record; } export interface CohereProviderOptions { name?: string; baseUrl?: string; apiKey: string; defaultModel?: string; headers?: Record; } export interface BedrockProviderOptions { name?: string; region: string; accessKeyId: string; secretAccessKey: string; sessionToken?: string; defaultModel?: string; headers?: Record; } export interface FallbackModelProviderOptions { name?: string; providers: ModelProvider[]; } export declare function toolsToModelSchemas(tools: Iterable): ModelToolSchema[]; export declare function generateWithRuntime(provider: ModelProvider, request: ModelRequest, options?: ModelRuntimeOptions): Promise; export declare class MockModelProvider implements ModelProvider { readonly name = "mock"; generate(request: ModelRequest): Promise; } /** Whether a model id (with or without provider prefix) is a known reasoning model. */ export declare function modelSupportsReasoning(model: string): boolean; export declare class OpenAICompatibleModelProvider implements ModelProvider { readonly name: string; private readonly baseUrl; private readonly apiKey; private readonly tokenProvider; private readonly defaultModel?; private readonly headers; private readonly rateLimiter; private readonly rateLimitKey; private readonly fetchImpl; constructor(options: OpenAICompatibleProviderOptions); /** Resolves the bearer token for a request: the rotating `tokenProvider` if set, else `apiKey`. */ protected authToken(): Promise; /** Resolve dynamic headers per attempt so request-scoped metadata never becomes stale. */ protected requestHeaders(): Promise>; generate(request: ModelRequest): Promise; stream(request: ModelRequest): AsyncGenerator; } export declare class AzureOpenAIModelProvider implements ModelProvider { readonly name: string; private readonly baseUrl; private readonly apiKey; private readonly deployment; private readonly apiVersion; private readonly headers; constructor(options: AzureOpenAIProviderOptions); generate(request: ModelRequest): Promise; } export declare class GeminiModelProvider implements ModelProvider { readonly name: string; private readonly baseUrl; private readonly apiKey; private readonly defaultModel?; private readonly headers; constructor(options: GeminiProviderOptions); generate(request: ModelRequest): Promise; } export declare class VertexAIModelProvider implements ModelProvider { readonly name: string; private readonly project; private readonly location; private readonly accessToken; private readonly defaultModel?; private readonly headers; constructor(options: VertexAIProviderOptions); generate(request: ModelRequest): Promise; } export declare class BedrockModelProvider implements ModelProvider { readonly name: string; private readonly region; private readonly accessKeyId; private readonly secretAccessKey; private readonly sessionToken?; private readonly defaultModel?; private readonly headers; constructor(options: BedrockProviderOptions); generate(request: ModelRequest): Promise; } export declare class CohereModelProvider implements ModelProvider { readonly name: string; private readonly baseUrl; private readonly apiKey; private readonly defaultModel?; private readonly headers; constructor(options: CohereProviderOptions); generate(request: ModelRequest): Promise; } export declare class FallbackModelProvider implements ModelProvider { readonly name: string; private readonly providers; constructor(options: FallbackModelProviderOptions); generate(request: ModelRequest): Promise; } export declare class AnthropicModelProvider implements ModelProvider { readonly name: string; private readonly baseUrl; private readonly apiKey; private readonly defaultModel?; private readonly headers; private readonly maxTokens; private readonly rateLimiter; private readonly rateLimitKey; constructor(options: AnthropicProviderOptions); generate(request: ModelRequest): Promise; stream(request: ModelRequest): AsyncGenerator; } export declare const defaultModelProvider: MockModelProvider; export declare function toOpenAIMessage(message: ModelMessage): Record; export declare function toOpenAITool(tool: ModelToolSchema): Record; export declare function openAIChatCompletionToModelResponse(json: OpenAIChatCompletion): ModelResponse; export declare class ProviderHttpError extends Error { readonly provider: string; readonly status: number; readonly statusText: string; readonly body: string; /** * Wait duration extracted from a `Retry-After` response header on 429 * responses. When set, the resilience wrapper waits exactly this long * instead of using exponential backoff. */ readonly retryAfterMs?: number; constructor(message: string, provider: string, status: number, statusText: string, body: string, retryAfterMs?: number); } /** * Parse a `Retry-After` header value (RFC 7231) into milliseconds. * Accepts both delta-seconds and HTTP-date forms. Returns undefined when * the value is missing or unparseable. */ export declare function parseRetryAfterMs(headerValue: string | null | undefined): number | undefined; export interface OpenAIChatCompletion { choices?: Array<{ message?: { content?: OpenAIMessageContent; reasoning_content?: string; tool_calls?: OpenAIToolCall[]; }; }>; usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number; }; } type OpenAIMessageContent = string | Array<{ type?: string; text?: string; summary?: Array<{ type?: string; text?: string; }>; }>; interface OpenAIToolCall { id: string; function: { name: string; arguments?: string; }; } export {}; //# sourceMappingURL=model.d.ts.map