Reviewed GitHub issue and related code.
UnderstandChecked SDK cache control options.
UnderstandCommitted and pushed fix with auto-close message.
EditAnalyze GitHub issue(s): https://github.com/badlogic/pi-mono/issues/967
For each issue:
Read the issue in full, including all comments and linked issues/PRs.
For bugs:
For feature requests:
Do NOT implement unless explicitly asked. Analyze and propose only.
The user wants me to analyze GitHub issue #967. Let me fetch the issue details first.
>gh issue view 967 --json title,body,comments,labels,state --repo badlogic/pi-monoLet me analyze this issue. It's a feature request to add configurable cache retention for Anthropic and OpenAI APIs.
The discussion concluded that instead of exposing it as a user-facing setting, it should be an environment variable that the providers check (to avoid confusion for users who don't understand the cost implications).
Let me read the relevant code files to understand how the streaming works for Anthropic and OpenAI providers.
Let me read the relevant code files to understand the current implementation.
Now I have a good understanding of the current implementation. Let me look at where the cache control is set in the Anthropic provider. I can see it's using cache_control: { type: "ephemeral" } in several places:
buildParams() for system promptsconvertMessages() for the last user messageFor OpenAI Responses, I see prompt_cache_key: options?.sessionId but I don't see any cache retention settings. Let me check what OpenAI supports for this.
The issue discussion concluded that:
Let me check the Anthropic SDK types for cache_control to see what TTL options are available.
Let me check the Anthropic SDK types for cache control options and OpenAI's cache retention options:
>cd /Users/badlogic/workspaces/pi-mono && rg -n "cache_control" node_modules/@anthropic-ai/sdk/resources/messages.d.ts 2>/dev/null | head -50>cd /Users/badlogic/workspaces/pi-mono && rg -n "prompt_cache" node_modules/openai/resources/responses/responses.d.ts 2>/dev/null | head -20I can see OpenAI has prompt_cache_retention?: 'in-memory' | '24h' | null; in the responses API.
Now let me check Anthropic's types for the cache_control TTL options:
>cd /Users/badlogic/workspaces/pi-mono && rg -n "ephemeral" node_modules/@anthropic-ai/sdk --include="*.ts" --include="*.d.ts" 2>/dev/null | head -30>cd /Users/badlogic/workspaces/pi-mono && rg -n "ttl" node_modules/@anthropic-ai/sdk --include="*.ts" --include="*.d.ts" -i 2>/dev/null | head -30Let me search more broadly in the Anthropic SDK:
>cd /Users/badlogic/workspaces/pi-mono && rg -n "cache" node_modules/@anthropic-ai/sdk/resources/messages.d.ts 2>/dev/null | head -30Let me try a different approach:
>cd /Users/badlogic/workspaces/pi-mono && find node_modules/@anthropic-ai -name "*.d.ts" 2>/dev/null | head -10The SDK types might be in a different location. Let me search more broadly.
>cd /Users/badlogic/workspaces/pi-mono && rg -l "cache_control" node_modules/@anthropic-ai/sdk 2>/dev/null | head -5Let me check the type definition file:
>cd /Users/badlogic/workspaces/pi-mono && rg -n -A5 "cache_control" node_modules/@anthropic-ai/sdk/resources/messages/messages.d.ts 2>/dev/null | head -50Now let me see what CacheControlEphemeral is:
>cd /Users/badlogic/workspaces/pi-mono && rg -n "CacheControlEphemeral" node_modules/@anthropic-ai/sdk/resources/messages/messages.d.ts 2>/dev/null | head -10Let me see the actual definition of CacheControlEphemeral:
>cd /Users/badlogic/workspaces/pi-mono && rg -n -A10 "^export interface CacheControlEphemeral" node_modules/@anthropic-ai/sdk/resources/messages/messages.d.ts 2>/dev/nullNow I see the Anthropic TTL options. Let me also check if there's a ttl field:
>cd /Users/badlogic/workspaces/pi-mono && rg -n -A15 "^export interface CacheControlEphemeral" node_modules/@anthropic-ai/sdk/resources/messages/messages.d.ts 2>/dev/nullNow I have all the information I need. Let me also check where the current cache_control is set in the anthropic.ts file to understand all the places that need to be modified:
Now let me check the env-api-keys.ts file to see the pattern for environment variable handling:
Now I have a complete understanding of the issue and the codebase. Let me summarize my analysis:
Issue #967: Add configurable cache retention for Anthropic and OpenAI
This is a feature request to add support for extended cache retention:
5m (default) or 1h TTLin_memory (default) or 24hDiscussion outcome: Instead of exposing this as a user-facing setting (which could confuse users about cost implications), it should be controlled via environment variables that the providers check.
packages/ai/src/providers/anthropic.ts
PI_CACHE_RETENTION or ANTHROPIC_CACHE_TTL)cache_control objects to include ttl: '1h' when persistent cache is enabledbuildParams() - system prompt cache_controlconvertMessages() - last user message cache_controlpackages/ai/src/providers/openai-responses.ts
PI_CACHE_RETENTION or OPENAI_CACHE_RETENTION)buildParams() to add prompt_cache_retention: '24h' when persistent cache is enabledbuildParams() - add prompt_cache_retention fieldOptions:
PI_CACHE_RETENTION=persistent (maps to 1h for Anthropic, 24h for OpenAI)ANTHROPIC_CACHE_TTL=1h and OPENAI_CACHE_RETENTION=24hA unified approach makes more sense since both providers distinguish between ephemeral (default, short-lived) and persistent (longer-lived) cache modes. The implementation can map a single PI_CACHE_RETENTION value to the appropriate TTL for each provider. The variable needs browser-safe access via typeof process !== "undefined" ? process.env.PI_CACHE_RETENTION : undefined, should default to current behavior (ephemeral), and should follow the pattern established in env-api-keys.ts for compatibility.
Type: Feature request
Request: Add support for extended cache retention for Anthropic and OpenAI APIs, controlled via environment variable (not user-facing setting).
Agreed approach (from discussion): Environment variable to keep it hidden from users who don't understand cost implications.
| Provider | Default | Extended |
|---|---|---|
| Anthropic | 5m | 1h (costs more for cache writes) |
| OpenAI | in_memory | 24h (no extra cost) |
Anthropic (anthropic.ts):
cache_control: { type: "ephemeral" } without TTL (defaults to 5m)OpenAI Responses (openai-responses.ts):
prompt_cache_key: options?.sessionId (line 103)prompt_cache_retention field set (defaults to in_memory)Environment variable: PI_CACHE_RETENTION
persistent (extended retention)typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent"Files to modify:
packages/ai/src/providers/anthropic.ts
buildParams() (~line 319-335): Add ttl: '1h' to system prompt cache_control when persistentconvertMessages() (~line 454-460): Add ttl: '1h' to last user message cache_control when persistentpackages/ai/src/providers/openai-responses.ts
buildParams() (~line 97-127): Add prompt_cache_retention: '24h' when persistentpackages/ai/README.md
PI_CACHE_RETENTION environment variablepackages/ai/CHANGELOG.md
[Unreleased]anthropic.ts - Add helper and modify cache_control:
// Helper to get cache TTL based on envfunction getCacheTtl(): '5m' | '1h' { if (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") { return '1h'; } return '5m';}
// In buildParams() and convertMessages():cache_control: { type: "ephemeral", ttl: getCacheTtl() }openai-responses.ts - Add cache retention:
// In buildParams():prompt_cache_key: options?.sessionId,prompt_cache_retention: (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") ? '24h' : undefined,Could also support provider-specific overrides:
ANTHROPIC_CACHE_TTL=1hOPENAI_CACHE_RETENTION=24hWith PI_CACHE_RETENTION as unified fallback. This gives power users more control.
Add prompt_cache_retention: '24h' when persistent what does this mean? store: true? can't do that
The user is asking about the OpenAI implementation. Let me re-check the OpenAI Responses API types to understand what prompt_cache_retention actually does and whether it requires store: true.
Looking at the earlier search results:
449: prompt_cache_key?: string;456: prompt_cache_retention?: 'in-memory' | '24h' | null;Let me check the OpenAI documentation or types more carefully to understand the relationship between prompt_cache_key, prompt_cache_retention, and store.
Let me check the OpenAI types more carefully:
>cd /Users/badlogic/workspaces/pi-mono && rg -n -B5 -A10 "prompt_cache_retention" node_modules/openai/resources/responses/responses.d.ts 2>/dev/null | head -60The prompt_cache_retention is a separate field from store. It's specifically for controlling how long the prompt cache is retained. It doesn't require store: true.
Let me also check if there's any relationship between prompt_cache_key and prompt_cache_retention:
>cd /Users/badlogic/workspaces/pi-mono && rg -n -B5 -A10 "prompt_cache_key" node_modules/openai/resources/responses/responses.d.ts 2>/dev/null | head -40prompt_cache_retention is independent from store. It's specifically about how long the prompt cache is retained. The docs say:
in-memory: default, short-lived24h: keeps cached prefixes active for longer, up to 24 hoursThis is separate from the store field which is about whether to store responses for later retrieval/fine-tuning.
So the implementation for OpenAI is straightforward - just add prompt_cache_retention: '24h' when the env var is set. No store: true needed.
You're right to question. prompt_cache_retention is independent from store. It's specifically about prompt caching duration:
in-memory (default): short-lived cache24h: keeps cached prefixes active up to 24 hoursNo store: true required. The implementation for OpenAI is just:
// In buildParams():prompt_cache_retention: (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") ? '24h' : undefined,The store field is about storing responses for later retrieval/fine-tuning, which is a different feature entirely.
PI_CACHE_RETENTION shoule be either "short" or "long". no provider has any more granular shit than that. then @packages/ai/src/providers/openai-responses-shared.ts (?) and anthropic should interpret that env var.
The user wants:
PI_CACHE_RETENTION with values short or long (not persistent)openai-responses-shared.ts and anthropic.ts should read this env varLet me check openai-responses-shared.ts to see where the params are built:
I see - openai-responses-shared.ts is shared code for stream processing and message conversion, but the actual buildParams is in openai-responses.ts.
The prompt_cache_retention param needs to be added in openai-responses.ts in the buildParams function, not in the shared file.
Let me update my analysis:
Files to modify:
packages/ai/src/providers/anthropic.ts
PI_CACHE_RETENTION env varlong, set ttl: '1h' on cache_control objectspackages/ai/src/providers/openai-responses.ts
PI_CACHE_RETENTION env varlong, add prompt_cache_retention: '24h' to paramsThe shared file doesn't need to change since caching config is in the params building, not the message conversion or stream processing.
Got it. The cache retention param belongs in openai-responses.ts (in buildParams), not the shared file. The shared file is just for message conversion and stream processing.
Environment variable: PI_CACHE_RETENTION
short (default behavior) or long (extended retention)shortFiles to modify:
packages/ai/src/providers/anthropic.ts
long: set cache_control: { type: "ephemeral", ttl: "1h" }short/unset: keep current cache_control: { type: "ephemeral" } (defaults to 5m)buildParams() (system prompt) and convertMessages() (last user message)packages/ai/src/providers/openai-responses.ts
buildParams(): add prompt_cache_retention: '24h' when env var is longshort/unset: don't set the field (defaults to in-memory)packages/ai/README.md - Document PI_CACHE_RETENTION
packages/ai/CHANGELOG.md - Add entry
Helper pattern (browser-safe):
function useLongCacheRetention(): boolean { return typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long";}we should also only do this if the baseUrl matches the OG providers
The user is right - we should only apply these cache retention settings when using the actual Anthropic and OpenAI APIs, not when using proxies or other providers that happen to use the same API format.
Let me check how the baseUrl is structured for these providers and what the default URLs are.
Good point. Need to check the base URLs to avoid sending provider-specific params to proxies/third-parties.
>cd /Users/badlogic/workspaces/pi-mono && rg -n "baseUrl" packages/ai/src/providers/anthropic.ts packages/ai/src/providers/openai-responses.ts>cd /Users/badlogic/workspaces/pi-mono && rg -n "api.anthropic.com|api.openai.com" packages/ai/Now I have the full picture:
https://api.anthropic.comhttps://api.openai.com/v1The helper should check:
PI_CACHE_RETENTION === "long"model.baseUrl matches the OG provider URLHelper pattern:
function useLongCacheRetention(baseUrl: string, ogBaseUrl: string): boolean { return ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith(ogBaseUrl) );}For Anthropic: baseUrl.startsWith("https://api.anthropic.com")
For OpenAI: baseUrl.startsWith("https://api.openai.com")
Environment variable: PI_CACHE_RETENTION=long
Files to modify:
packages/ai/src/providers/anthropic.tsAdd helper and apply only for OG Anthropic:
function getCacheTtl(baseUrl: string): '5m' | '1h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith("https://api.anthropic.com") ) { return '1h'; } return undefined; // SDK defaults to 5m}In buildParams() and convertMessages():
cache_control: { type: "ephemeral", ttl: getCacheTtl(model.baseUrl) }// or if ttl is undefined, just { type: "ephemeral" }packages/ai/src/providers/openai-responses.tsIn buildParams():
function getPromptCacheRetention(baseUrl: string): '24h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith("https://api.openai.com") ) { return '24h'; } return undefined; // defaults to in-memory}
// In params:prompt_cache_retention: getPromptCacheRetention(model.baseUrl),packages/ai/README.md - Document env varpackages/ai/CHANGELOG.md - Add entryBehavior:
PI_CACHE_RETENTION | Anthropic (api.anthropic.com) | OpenAI (api.openai.com) | Other providers |
|---|---|---|---|
unset / short | 5m (default) | in-memory (default) | unchanged |
long | 1h | 24h | unchanged |
baseUrl.startsWith("https://api.anthropic.com") should be an includes without the https i think? do we check for that url in @packages/ai/src/providers/anthropic.ts already? sould mirror that then, same for openai
Let me check how URL matching is done in both providers currently.
>cd /Users/badlogic/workspaces/pi-mono && rg -n "baseUrl|baseURL" packages/ai/src/providers/anthropic.ts packages/ai/src/providers/openai-responses.ts | head -30>cd /Users/badlogic/workspaces/pi-mono && rg -n "includes.*openai|includes.*anthropic" packages/ai/src/providers/Let me check the openai-completions.ts file since that's likely where URL detection happens for compatibility checks:
>cd /Users/badlogic/workspaces/pi-mono && rg -n "baseUrl.*includes|includes.*url" packages/ai/src/providers/ -i>cd /Users/badlogic/workspaces/pi-mono && rg -n "api\.openai\.com|api\.anthropic\.com" packages/ai/src/providers/I see the pattern now. In openai-completions.ts, they use baseUrl.includes("domain") pattern, like:
baseUrl.includes("api.z.ai")baseUrl.includes("cerebras.ai")baseUrl.includes("api.x.ai")baseUrl.includes("mistral.ai")baseUrl.includes("openrouter.ai")So for our case:
baseUrl.includes("api.anthropic.com")baseUrl.includes("api.openai.com")There's no existing check for these URLs in the anthropic.ts or openai-responses.ts files, but the pattern from openai-completions.ts is clear: use .includes() with the domain.
No existing checks in those files, but openai-completions.ts uses the pattern:
baseUrl.includes("api.z.ai")baseUrl.includes("cerebras.ai")baseUrl.includes("api.x.ai")baseUrl.includes("mistral.ai")baseUrl.includes("openrouter.ai")Use .includes() with domain:
// anthropic.tsbaseUrl.includes("api.anthropic.com")
// openai-responses.tsbaseUrl.includes("api.openai.com")Helper functions:
// anthropic.tsfunction getCacheTtl(baseUrl: string): '1h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.includes("api.anthropic.com") ) { return '1h'; } return undefined;}
// openai-responses.ts function getPromptCacheRetention(baseUrl: string): '24h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.includes("api.openai.com") ) { return '24h'; } return undefined;}lgtm, implement, set up a simple etst in pi-ai package for both providers, see stream.test.ts as an example
The user wants me to implement the feature. Let me:
Let me start by reading the files I need to modify.
Now I understand the test pattern. The tests:
describe.skipIf(!process.env.XXX_API_KEY) to conditionally run tests based on env varsbasicTextGeneration, handleToolCall, etc.getModel to get model configurationsFor the cache retention test, I need to:
anthropic.ts and openai-responses.tsPI_CACHE_RETENTION env var is respectedLet me now implement the changes:
anthropic.ts to add cache TTL supportopenai-responses.ts to add cache retention supportLet me start with the implementation.
Now let me implement the changes. First, I'll update both provider files:
Now I need to find and update the places where cache_control is set. Let me look at the buildParams function and convertMessages function in anthropic.ts to update them.
Now let me update the buildParams function to use the cache TTL:
I need to find the buildParams function and the convertMessages function. Let me continue reading.
Now I can see the buildParams function. I need to update the cache_control objects to include the TTL. The cache_control is set in multiple places:
Let me continue reading to find the part where cache_control is added to the last user message.
Now I have all the locations where cache_control is set. I need to update:
buildParams function - OAuth token Claude Code identity (~line 473)buildParams function - OAuth token context.systemPrompt (~line 483)buildParams function - Non-OAuth token context.systemPrompt (~line 493)convertMessages function - last user message (~line 676)The issue is that buildParams doesn't have access to model.baseUrl directly. I need to pass the model to check the baseUrl. Let me look at how buildParams is called.Looking at the code:
const params = buildParams(model, context, isOAuthToken, options);So model is available in buildParams. Good. Now I need to update all the cache_control locations.
Let me do the edits one by one.
Now I have all the locations. Let me update the buildParams function to use the cache TTL:
Now I need to update the convertMessages function to also use the cache TTL for the last user message. The issue is that convertMessages doesn't have access to model.baseUrl. I need to pass the baseUrl or use a different approach.Looking at the function signature:```typescriptfunction convertMessages(
messages: Message[],
model: Model<"anthropic-messages">,
isOAuthToken: boolean,
): MessageParam[] {
The model is available! So I can use `model.baseUrl` directly. Let me update the cache_control for the last user message.Now update the convertMessages function for the last user message:
Now I need to update the openai-responses.ts file. Let me read it again to find where to add the cache retention.
Now let me update the openai-responses.ts file:
Let me continue reading to find the buildParams function:
Now I have the buildParams function. I need to add the helper function and update the params to include prompt_cache_retention. Let me add the helper after the imports and update the buildParams function.
Now I'll add the helper function and update buildParams in openai-responses.ts:
Now I need to update the buildParams function to use the cache retention. Let me update the params object to include prompt_cache_retention.
Now update the buildParams function to include the cache retention:
Now I need to create the test file. Let me create a simple test that verifies the cache retention env var is respected. The test should:1. Check that the payload includes the correct cache_retention/ttl when PI_CACHE_RETENTION=long 2. Check that it doesn't include them when not set or when baseUrl doesn't match
I'll use the onPayload callback to inspect the params being sent.
Now let me create a test file for cache retention:
Now let me run the check to make sure everything compiles and the tests pass:
Now let me run the check to ensure everything compiles:
>cd /Users/badlogic/workspaces/pi-mono && npm run check 2>&1Everything compiles. Now let me run the specific test to make sure it works:
Let me run the cache retention test:
>cd /Users/badlogic/workspaces/pi-mono && npm test -- packages/ai/test/cache-retention.test.ts 2>&1The test was run in the wrong package. Let me run it directly from the ai package:
Let me run the test directly from the ai package:
>cd /Users/badlogic/workspaces/pi-mono/packages/ai && npx vitest --run test/cache-retention.test.ts 2>&1All tests pass. Now let me update the CHANGELOG and README.
All tests pass. Now let me update the CHANGELOG and README:
I need to add an entry to the [Unreleased] section. I'll add it under a new "Added" section.
Now let me update the README to document the environment variable. Let me check the README structure first.
Now let me update the README:
I need to add documentation for the PI_CACHE_RETENTION environment variable. The best place seems to be in the "Environment Variables" section. Let me add it there.
Now let me run the full check again to make sure everything is still working:
Let me run the check one more time to ensure everything is good:
>cd /Users/badlogic/workspaces/pi-mono && npm run check 2>&1Everything is good. Let me provide a summary of what I implemented.
Implementation complete. Here's a summary:
packages/ai/src/providers/anthropic.tsgetCacheTtl() helper function that returns '1h' when PI_CACHE_RETENTION=long and baseUrl includes api.anthropic.combuildParams() to add ttl to cache_control for system prompts (both OAuth and non-OAuth)convertMessages() to add ttl to cache_control for the last user messagepackages/ai/src/providers/openai-responses.tsgetPromptCacheRetention() helper function that returns '24h' when PI_CACHE_RETENTION=long and baseUrl includes api.openai.combuildParams() to include prompt_cache_retention in the request paramspackages/ai/test/cache-retention.test.tspackages/ai/CHANGELOG.md[Unreleased] documenting the new featurepackages/ai/README.md# Enable extended cache retentionexport PI_CACHE_RETENTION=long
# Run your application - Anthropic gets 1h TTL, OpenAI gets 24h retentionok, please also pudate the env var section in @packages/coding-agent/README.md
The user wants me to update the environment variables section in the coding-agent README to include the new PI_CACHE_RETENTION variable. Let me read that file first.
I need to add PI_CACHE_RETENTION to the Environment Variables section. I can see there's a table at the end of the CLI Reference section.
Done. Let me run the check one more time to make sure everything is good:
>cd /Users/badlogic/workspaces/pi-mono && npm run check 2>&1All checks pass. The implementation is complete.
Done. Added PI_CACHE_RETENTION to the Environment Variables table in packages/coding-agent/README.md.
commit and push, leave a comment on the issue explaining things concisely in my tone
The user wants me to commit the changes, push, and leave a comment on the issue. Let me first check what files were changed.
>cd /Users/badlogic/workspaces/pi-mono && git statusThere's a modified file packages/coding-agent/docs/models.md that I didn't touch. Let me check what's in there - it might be from a previous session or something.
>cd /Users/badlogic/workspaces/pi-mono && git diff packages/coding-agent/docs/models.mdThis change is unrelated to my work. It appears to be from another session. I should NOT commit this file - I should only commit the files I modified.
Let me commit only my specific files:
>cd /Users/badlogic/workspaces/pi-mono && git add packages/ai/CHANGELOG.md packages/ai/README.md packages/ai/src/providers/anthropic.ts packages/ai/src/providers/openai-responses.ts packages/ai/test/cache-retention.test.ts packages/coding-agent/README.mdNow let me commit with a message that references the issue.
>cd /Users/badlogic/workspaces/pi-mono && git commit -m "feat(ai): add PI_CACHE_RETENTION env var for extended prompt caching
Adds support for extended cache retention via PI_CACHE_RETENTION=long:
- Anthropic: 5m -> 1h TTL
- OpenAI: in-memory -> 24h retention
Only applies to direct API calls (api.anthropic.com, api.openai.com).
Proxies and other providers are unaffected.
fixes #967"Good, commit succeeded. Now let me push and then leave a comment on the issue.
>cd /Users/badlogic/workspaces/pi-mono && git pushNow let me leave a comment on the issue. The user wants me to explain things concisely in their tone. Based on the issue discussion, the user (badlogic) prefers direct, technical communication without fluff. Let me write a comment that explains what was implemented.
>gh issue comment 967 --repo badlogic/pi-mono --body "Implemented via env var as discussed.
\`\`\`bash
export PI_CACHE_RETENTION=long
\`\`\`
- Anthropic: sets \`ttl: '1h'\` on cache_control (vs default 5m)
- OpenAI: sets \`prompt_cache_retention: '24h'\` (vs default in-memory)
Only kicks in for direct API calls (\`api.anthropic.com\`, \`api.openai.com\`). Proxies and third-party endpoints are unaffected.
@StaticShielding thanks for the suggestion. Should work for your extension use case too."Done. Committed, pushed, and left a comment on the issue. The commit message includes "fixes #967" which will automatically close the issue.
// Helper to get cache TTL based on envfunction getCacheTtl(): '5m' | '1h' { if (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") { return '1h'; } return '5m';}
// In buildParams() and convertMessages():cache_control: { type: "ephemeral", ttl: getCacheTtl() }// In buildParams():prompt_cache_key: options?.sessionId,prompt_cache_retention: (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") ? '24h' : undefined,449: prompt_cache_key?: string;456: prompt_cache_retention?: 'in-memory' | '24h' | null;// In buildParams():prompt_cache_retention: (typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "persistent") ? '24h' : undefined,function useLongCacheRetention(): boolean { return typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long";}function useLongCacheRetention(baseUrl: string, ogBaseUrl: string): boolean { return ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith(ogBaseUrl) );}function getCacheTtl(baseUrl: string): '5m' | '1h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith("https://api.anthropic.com") ) { return '1h'; } return undefined; // SDK defaults to 5m}cache_control: { type: "ephemeral", ttl: getCacheTtl(model.baseUrl) }// or if ttl is undefined, just { type: "ephemeral" }function getPromptCacheRetention(baseUrl: string): '24h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.startsWith("https://api.openai.com") ) { return '24h'; } return undefined; // defaults to in-memory}
// In params:prompt_cache_retention: getPromptCacheRetention(model.baseUrl),baseUrl.includes("api.z.ai")baseUrl.includes("cerebras.ai")baseUrl.includes("api.x.ai")baseUrl.includes("mistral.ai")baseUrl.includes("openrouter.ai")// anthropic.tsbaseUrl.includes("api.anthropic.com")
// openai-responses.tsbaseUrl.includes("api.openai.com")// anthropic.tsfunction getCacheTtl(baseUrl: string): '1h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.includes("api.anthropic.com") ) { return '1h'; } return undefined;}
// openai-responses.ts function getPromptCacheRetention(baseUrl: string): '24h' | undefined { if ( typeof process !== "undefined" && process.env.PI_CACHE_RETENTION === "long" && baseUrl.includes("api.openai.com") ) { return '24h'; } return undefined;}const params = buildParams(model, context, isOAuthToken, options);
The model is available! So I can use `model.baseUrl` directly. Let me update the cache_control for the last user message.# Enable extended cache retentionexport PI_CACHE_RETENTION=long
# Run your application - Anthropic gets 1h TTL, OpenAI gets 24h retention