From 536c8a840bdade67be7694737df809861a417ba6 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 22 Jun 2026 13:29:23 +0800 Subject: [PATCH] refactor(llm): share cache retention resolution --- src/llm/providers/anthropic.ts | 15 +-------------- src/llm/providers/cache-retention.ts | 15 +++++++++++++++ src/llm/providers/openai-completions.ts | 11 +---------- src/llm/providers/openai-responses.ts | 15 +-------------- 4 files changed, 18 insertions(+), 38 deletions(-) create mode 100644 src/llm/providers/cache-retention.ts diff --git a/src/llm/providers/anthropic.ts b/src/llm/providers/anthropic.ts index 8ef3ecaa0501..bbda64673559 100644 --- a/src/llm/providers/anthropic.ts +++ b/src/llm/providers/anthropic.ts @@ -61,6 +61,7 @@ import { ANTHROPIC_OMITTED_REASONING_TEXT, findActiveAnthropicToolTurnAssistantIndex, } from "./anthropic-thinking-replay.js"; +import { resolveCacheRetention } from "./cache-retention.js"; import { resolveCloudflareBaseUrl } from "./cloudflare.js"; import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js"; import { adjustMaxTokensForThinking, buildBaseOptions } from "./simple-options.js"; @@ -68,20 +69,6 @@ import { transformMessages } from "./transform-messages.js"; const ANTHROPIC_CACHE_CONTROL_LIMIT = 4; -/** - * Resolve cache retention preference. - * Defaults to "short" and uses OPENCLAW_CACHE_RETENTION for backward compatibility. - */ -function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention { - if (cacheRetention) { - return cacheRetention; - } - if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") { - return "long"; - } - return "short"; -} - function getCacheControl( model: Model<"anthropic-messages">, cacheRetention?: CacheRetention, diff --git a/src/llm/providers/cache-retention.ts b/src/llm/providers/cache-retention.ts new file mode 100644 index 000000000000..9953895eba55 --- /dev/null +++ b/src/llm/providers/cache-retention.ts @@ -0,0 +1,15 @@ +import type { CacheRetention } from "../types.js"; + +/** + * Resolve cache retention preference. + * Defaults to "short" and uses OPENCLAW_CACHE_RETENTION for backward compatibility. + */ +export function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention { + if (cacheRetention) { + return cacheRetention; + } + if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") { + return "long"; + } + return "short"; +} diff --git a/src/llm/providers/openai-completions.ts b/src/llm/providers/openai-completions.ts index 0fa4d9b3ea06..b4e0e3ece1c3 100644 --- a/src/llm/providers/openai-completions.ts +++ b/src/llm/providers/openai-completions.ts @@ -46,6 +46,7 @@ import { AssistantMessageEventStream } from "../utils/event-stream.js"; import { headersToRecord } from "../utils/headers.js"; import { parseStreamingJson } from "../utils/json-parse.js"; import { sanitizeSurrogates } from "../utils/sanitize-unicode.js"; +import { resolveCacheRetention } from "./cache-retention.js"; import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js"; import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js"; import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js"; @@ -118,16 +119,6 @@ type ChatCompletionToolWithCacheControl = OpenAI.Chat.Completions.ChatCompletion cache_control?: OpenAICompatCacheControl; }; -function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention { - if (cacheRetention) { - return cacheRetention; - } - if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") { - return "long"; - } - return "short"; -} - export const streamOpenAICompletions: StreamFunction< "openai-completions", OpenAICompletionsOptions diff --git a/src/llm/providers/openai-responses.ts b/src/llm/providers/openai-responses.ts index a49db54c6cdf..c11b0167483b 100644 --- a/src/llm/providers/openai-responses.ts +++ b/src/llm/providers/openai-responses.ts @@ -13,6 +13,7 @@ import type { Usage, } from "../types.js"; import { AssistantMessageEventStream } from "../utils/event-stream.js"; +import { resolveCacheRetention } from "./cache-retention.js"; import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js"; import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js"; import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js"; @@ -27,20 +28,6 @@ import { buildBaseOptions } from "./simple-options.js"; const OPENAI_TOOL_CALL_PROVIDERS = new Set(["openai", "opencode"]); -/** - * Resolve cache retention preference. - * Defaults to "short" and uses OPENCLAW_CACHE_RETENTION for backward compatibility. - */ -function resolveCacheRetention(cacheRetention?: CacheRetention): CacheRetention { - if (cacheRetention) { - return cacheRetention; - } - if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") { - return "long"; - } - return "short"; -} - function getCompat(model: Model<"openai-responses">): Required { return { sendSessionIdHeader: model.compat?.sendSessionIdHeader ?? true,