/** * Provider prompt caching. * * Anthropic-direct path (Eve layout — four breakpoints, Anthropic's max): * 1. Last ToolSet entry — caches tool definitions across turns * 2. Last stable SystemModelMessage — caches the system prefix * 3. Last conversation message regardless of role — writes newest * content (often a tool result) into the cache on the same request * 4. Most recent assistant message before it — automatic cache advance * * Gateway string models get `gateway.caching = "auto"` and never receive * breakpoints. OpenAI Responses models get `promptCacheKey` + truncation. * * Volatile system blocks (retrieval, memory, run notes) must sit AFTER the * stable head so the system breakpoint does not pull them into the cache. */ import type { JSONValue, ModelMessage, SystemModelMessage, ToolSet } from 'ai'; export type PromptCachePath = { readonly kind: 'gateway-auto'; } | { readonly kind: 'anthropic-direct'; } | { readonly kind: 'none'; }; /** * Dual-namespace marker: Anthropic Messages API reads `anthropic.cacheControl`; * Bedrock Converse reads `bedrock.cachePoint`. Providers ignore foreign namespaces. */ export interface AnthropicCacheMarker { readonly anthropic: { readonly cacheControl: { readonly type: 'ephemeral'; readonly ttl?: '1h'; }; }; readonly bedrock: { readonly cachePoint: { readonly type: 'default'; }; }; } /** @deprecated Prefer ephemeral default; TTL only applies to anthropic.cacheControl. */ export type AnthropicCacheTtl = '5m' | '1h'; export declare function detectPromptCachePath(model: unknown): PromptCachePath; export declare function getAnthropicCacheMarker(ttl?: AnthropicCacheTtl): AnthropicCacheMarker; /** * True when breakpoints should be placed (direct Anthropic / Bedrock-Anthropic). * String gateway ids are NOT anthropic-direct — they take gateway-auto. */ export declare function isAnthropicLanguageModel(model: unknown): boolean; export declare function mergeGatewayAutoCaching(base: Readonly> | undefined): Record; export declare function applyLastToolCacheBreakpoint(tools: ToolSet, marker: AnthropicCacheMarker): ToolSet; /** * Marks the STABLE HEAD — the first system message — so everything up to and including it * is cached. * * `composeSystem` returns [head, volatile]: the head is base instructions + skills and is * byte-identical across turns; the volatile message carries working memory and the flow * node prompt, which change every turn by design. Marking the LAST message here would put * the breakpoint on the volatile one, caching nothing across a flow transition — that is * the bug this exists to prevent, and it cost ~16 points of cache rate (93.20% on a plain * session vs 77.20% once a flow entered). */ export declare function applySystemCacheBreakpoint(instructions: readonly SystemModelMessage[], marker: AnthropicCacheMarker): SystemModelMessage[]; /** * Final breakpoint on the last message (any role) + assistant anchor before it. * A lagging final breakpoint caps effective hit rate near 50%. */ export declare function applyConversationCacheControl(messages: readonly ModelMessage[], marker: AnthropicCacheMarker): ModelMessage[]; /** * @deprecated Use {@link applyConversationCacheControl}. Kept as a named export * for existing callers; places the last-message + assistant-anchor breakpoints. */ export declare function applyAnthropicCacheControl(messages: ModelMessage[], ttl?: AnthropicCacheTtl): ModelMessage[]; export declare function isOpenAIResponsesModel(model: unknown): boolean; export interface OpenAIResponsesCompactOptions { truncationFallback?: 'auto' | 'disabled'; useSessionAsPromptCacheKey?: boolean; } /** * A cache key derived from the PREFIX, not the session. * * OpenAI's `prompt_cache_key` is a routing hint: requests sharing a key route to the same * cache. Keying it on `sessionId` gave every session its own lane, so two users talking to * the same agent — identical instructions, identical tools, therefore an identical cacheable * prefix — could never share an entry. The stable head plus the tool surface IS the shared * part, so it is what the key is derived from. * * Tool names are sorted: the same surface declared in a different order is the same prefix. */ export declare function promptCacheKeyFor(stableSystem: readonly SystemModelMessage[], tools: ToolSet | undefined): string; export declare function buildOpenAIResponsesProviderOptions(opts: OpenAIResponsesCompactOptions, sessionId: string): Record | null; export declare function appendVolatileSystemBlocks(stable: readonly SystemModelMessage[], blocks: Array): SystemModelMessage[]; export interface ApplyPromptCacheInput { model: unknown; sessionId: string; messages: ModelMessage[]; tools?: ToolSet; /** Stable system prefix (persona, node instructions). Receives the system breakpoint. */ stableSystem?: SystemModelMessage[]; /** Volatile blocks appended AFTER the system breakpoint (retrieval, memory, run notes). */ volatileSystemBlocks?: Array; providerOptions?: Record>; } export interface ApplyPromptCacheResult { messages: ModelMessage[]; system?: SystemModelMessage[]; tools?: ToolSet; providerOptions?: Record>; } /** * Single wiring point for provider prompt caching. Volatile system blocks are * always appended after the stable head — even on non-Anthropic paths — so * ordering is a contract of this function, not of call-site accident. */ export declare function applyPromptCache(input: ApplyPromptCacheInput): ApplyPromptCacheResult;