fix(agents): update cacheControlTtl to cacheRetention for pi-ai 0.50.9

- Update @mariozechner/pi-ai and pi-agent-core to 0.50.9
- Rename cacheControlTtl to cacheRetention with values none/short/long
- Add backwards compatibility mapping: 5m->short, 1h->long
- Remove dead OpenRouter check (uses openai-completions API)
- Default new configs to cacheRetention: short
This commit is contained in:
Mario Zechner
2026-02-01 09:50:52 +01:00
parent 511b2c91e3
commit ba4a55f6d9
5 changed files with 65 additions and 38 deletions

View File

@@ -159,8 +159,8 @@
"@homebridge/ciao": "^1.3.4", "@homebridge/ciao": "^1.3.4",
"@line/bot-sdk": "^10.6.0", "@line/bot-sdk": "^10.6.0",
"@lydell/node-pty": "1.2.0-beta.3", "@lydell/node-pty": "1.2.0-beta.3",
"@mariozechner/pi-agent-core": "0.50.7", "@mariozechner/pi-agent-core": "0.50.9",
"@mariozechner/pi-ai": "0.50.7", "@mariozechner/pi-ai": "0.50.9",
"@mariozechner/pi-coding-agent": "0.50.7", "@mariozechner/pi-coding-agent": "0.50.7",
"@mariozechner/pi-tui": "0.50.7", "@mariozechner/pi-tui": "0.50.7",
"@mozilla/readability": "^0.6.0", "@mozilla/readability": "^0.6.0",

40
pnpm-lock.yaml generated
View File

@@ -40,11 +40,11 @@ importers:
specifier: 1.2.0-beta.3 specifier: 1.2.0-beta.3
version: 1.2.0-beta.3 version: 1.2.0-beta.3
'@mariozechner/pi-agent-core': '@mariozechner/pi-agent-core':
specifier: 0.50.7 specifier: 0.50.9
version: 0.50.7(ws@8.19.0)(zod@4.3.6) version: 0.50.9(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-ai': '@mariozechner/pi-ai':
specifier: 0.50.7 specifier: 0.50.9
version: 0.50.7(ws@8.19.0)(zod@4.3.6) version: 0.50.9(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-coding-agent': '@mariozechner/pi-coding-agent':
specifier: 0.50.7 specifier: 0.50.7
version: 0.50.7(ws@8.19.0)(zod@4.3.6) version: 0.50.7(ws@8.19.0)(zod@4.3.6)
@@ -1391,12 +1391,12 @@ packages:
resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==} resolution: {integrity: sha512-faGUlTcXka5l7rv0lP3K3vGW/ejRuOS24RR2aSFWREUQqzjgdsuWNo/IiPqL3kWRGt6Ahl2+qcDAwtdeWeuGUw==}
hasBin: true hasBin: true
'@mariozechner/pi-agent-core@0.50.7': '@mariozechner/pi-agent-core@0.50.9':
resolution: {integrity: sha512-iSNh+7QQFVge3co0Au1X6sqXAr+X6e3XlRXM7oE3m6zMWj76A1YCciV2sLI/imBcoFLum8blIaM0empwL477dQ==} resolution: {integrity: sha512-Zsgqs/f2Fxrub1k95vj8kg7M1eTDdS1lP3gTV7h9raBUQzoaPP+9jYGoUL5KKqxsBbt7WgeAQrK3nrev400EHA==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
'@mariozechner/pi-ai@0.50.7': '@mariozechner/pi-ai@0.50.9':
resolution: {integrity: sha512-mVqaTE/Ulijd1olduEU02IfIP91aNt6F0UYJQNLR+m3b/6bsn21csZJZnkjYia0kHX7PnOLtikO2jG7dJpYY6g==} resolution: {integrity: sha512-a6sLIHLH+wo5zTFoo/0AE/P6GPyJzaXnE86z89t6tINzeSdKMApZZ+B4Cy4U3GpsYfxuZ9gBJlcKbfj+oKP3wg==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
hasBin: true hasBin: true
@@ -1409,6 +1409,10 @@ packages:
resolution: {integrity: sha512-O8H8hXqoWdE+5eUUPiswq+WT+2eeshJHJmXKWMJMoSitNqdwzYZds9umAKdVLII6ZvjnFtd0awnf4VThYQBFIA==} resolution: {integrity: sha512-O8H8hXqoWdE+5eUUPiswq+WT+2eeshJHJmXKWMJMoSitNqdwzYZds9umAKdVLII6ZvjnFtd0awnf4VThYQBFIA==}
engines: {node: '>=20.0.0'} engines: {node: '>=20.0.0'}
'@mariozechner/pi-tui@0.50.9':
resolution: {integrity: sha512-suMWoh+XB3JKkwrXfXSwEAsvkrPUn6Zn8JQ1I+1hcNQqH/lY6e8LFRwVBkkvPt/jwoxBh8jGoiTNVh5i7Yod0g==}
engines: {node: '>=20.0.0'}
'@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0':
resolution: {integrity: sha512-+qqgpn39XFSbsD0dFjssGO9vHEP7sTyfs8yTpt8vuqWpUpF20QMwpCZi0jpYw7GxjErNTsMshopuo8677DfGEA==} resolution: {integrity: sha512-+qqgpn39XFSbsD0dFjssGO9vHEP7sTyfs8yTpt8vuqWpUpF20QMwpCZi0jpYw7GxjErNTsMshopuo8677DfGEA==}
engines: {node: '>= 22'} engines: {node: '>= 22'}
@@ -6389,10 +6393,10 @@ snapshots:
std-env: 3.10.0 std-env: 3.10.0
yoctocolors: 2.1.2 yoctocolors: 2.1.2
'@mariozechner/pi-agent-core@0.50.7(ws@8.19.0)(zod@4.3.6)': '@mariozechner/pi-agent-core@0.50.9(ws@8.19.0)(zod@4.3.6)':
dependencies: dependencies:
'@mariozechner/pi-ai': 0.50.7(ws@8.19.0)(zod@4.3.6) '@mariozechner/pi-ai': 0.50.9(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-tui': 0.50.7 '@mariozechner/pi-tui': 0.50.9
transitivePeerDependencies: transitivePeerDependencies:
- '@modelcontextprotocol/sdk' - '@modelcontextprotocol/sdk'
- aws-crt - aws-crt
@@ -6402,7 +6406,7 @@ snapshots:
- ws - ws
- zod - zod
'@mariozechner/pi-ai@0.50.7(ws@8.19.0)(zod@4.3.6)': '@mariozechner/pi-ai@0.50.9(ws@8.19.0)(zod@4.3.6)':
dependencies: dependencies:
'@anthropic-ai/sdk': 0.71.2(zod@4.3.6) '@anthropic-ai/sdk': 0.71.2(zod@4.3.6)
'@aws-sdk/client-bedrock-runtime': 3.980.0 '@aws-sdk/client-bedrock-runtime': 3.980.0
@@ -6430,8 +6434,8 @@ snapshots:
dependencies: dependencies:
'@mariozechner/clipboard': 0.3.0 '@mariozechner/clipboard': 0.3.0
'@mariozechner/jiti': 2.6.5 '@mariozechner/jiti': 2.6.5
'@mariozechner/pi-agent-core': 0.50.7(ws@8.19.0)(zod@4.3.6) '@mariozechner/pi-agent-core': 0.50.9(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-ai': 0.50.7(ws@8.19.0)(zod@4.3.6) '@mariozechner/pi-ai': 0.50.9(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-tui': 0.50.7 '@mariozechner/pi-tui': 0.50.7
'@silvia-odwyer/photon-node': 0.3.4 '@silvia-odwyer/photon-node': 0.3.4
chalk: 5.6.2 chalk: 5.6.2
@@ -6461,6 +6465,14 @@ snapshots:
marked: 15.0.12 marked: 15.0.12
mime-types: 3.0.2 mime-types: 3.0.2
'@mariozechner/pi-tui@0.50.9':
dependencies:
'@types/mime-types': 2.1.4
chalk: 5.6.2
get-east-asian-width: 1.4.0
marked: 15.0.12
mime-types: 3.0.2
'@matrix-org/matrix-sdk-crypto-nodejs@0.4.0': '@matrix-org/matrix-sdk-crypto-nodejs@0.4.0':
dependencies: dependencies:
https-proxy-agent: 7.0.6 https-proxy-agent: 7.0.6

View File

@@ -20,22 +20,38 @@ export function resolveExtraParams(params: {
return modelConfig?.params ? { ...modelConfig.params } : undefined; return modelConfig?.params ? { ...modelConfig.params } : undefined;
} }
type CacheControlTtl = "5m" | "1h"; type CacheRetention = "none" | "short" | "long";
function resolveCacheControlTtl( /**
* Resolve cacheRetention from extraParams, supporting both new `cacheRetention`
* and legacy `cacheControlTtl` values for backwards compatibility.
*
* Mapping: "5m" → "short", "1h" → "long"
*
* Only applies to Anthropic provider (OpenRouter uses openai-completions API
* with hardcoded cache_control, not the cacheRetention stream option).
*/
function resolveCacheRetention(
extraParams: Record<string, unknown> | undefined, extraParams: Record<string, unknown> | undefined,
provider: string, provider: string,
modelId: string, ): CacheRetention | undefined {
): CacheControlTtl | undefined { if (provider !== "anthropic") {
const raw = extraParams?.cacheControlTtl;
if (raw !== "5m" && raw !== "1h") {
return undefined; return undefined;
} }
if (provider === "anthropic") {
return raw; // Prefer new cacheRetention if present
const newVal = extraParams?.cacheRetention;
if (newVal === "none" || newVal === "short" || newVal === "long") {
return newVal;
} }
if (provider === "openrouter" && modelId.startsWith("anthropic/")) {
return raw; // Fall back to legacy cacheControlTtl with mapping
const legacy = extraParams?.cacheControlTtl;
if (legacy === "5m") {
return "short";
}
if (legacy === "1h") {
return "long";
} }
return undefined; return undefined;
} }
@@ -44,22 +60,21 @@ function createStreamFnWithExtraParams(
baseStreamFn: StreamFn | undefined, baseStreamFn: StreamFn | undefined,
extraParams: Record<string, unknown> | undefined, extraParams: Record<string, unknown> | undefined,
provider: string, provider: string,
modelId: string,
): StreamFn | undefined { ): StreamFn | undefined {
if (!extraParams || Object.keys(extraParams).length === 0) { if (!extraParams || Object.keys(extraParams).length === 0) {
return undefined; return undefined;
} }
const streamParams: Partial<SimpleStreamOptions> & { cacheControlTtl?: CacheControlTtl } = {}; const streamParams: Partial<SimpleStreamOptions> = {};
if (typeof extraParams.temperature === "number") { if (typeof extraParams.temperature === "number") {
streamParams.temperature = extraParams.temperature; streamParams.temperature = extraParams.temperature;
} }
if (typeof extraParams.maxTokens === "number") { if (typeof extraParams.maxTokens === "number") {
streamParams.maxTokens = extraParams.maxTokens; streamParams.maxTokens = extraParams.maxTokens;
} }
const cacheControlTtl = resolveCacheControlTtl(extraParams, provider, modelId); const cacheRetention = resolveCacheRetention(extraParams, provider);
if (cacheControlTtl) { if (cacheRetention) {
streamParams.cacheControlTtl = cacheControlTtl; streamParams.cacheRetention = cacheRetention;
} }
if (Object.keys(streamParams).length === 0) { if (Object.keys(streamParams).length === 0) {
@@ -102,7 +117,7 @@ export function applyExtraParamsToAgent(
) )
: undefined; : undefined;
const merged = Object.assign({}, extraParams, override); const merged = Object.assign({}, extraParams, override);
const wrappedStreamFn = createStreamFnWithExtraParams(agent.streamFn, merged, provider, modelId); const wrappedStreamFn = createStreamFnWithExtraParams(agent.streamFn, merged, provider);
if (wrappedStreamFn) { if (wrappedStreamFn) {
log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`); log.debug(`applying extraParams to agent streamFn for ${provider}/${modelId}`);

View File

@@ -100,8 +100,8 @@ describe("config pruning defaults", () => {
expect(cfg.agents?.defaults?.contextPruning?.ttl).toBe("1h"); expect(cfg.agents?.defaults?.contextPruning?.ttl).toBe("1h");
expect(cfg.agents?.defaults?.heartbeat?.every).toBe("30m"); expect(cfg.agents?.defaults?.heartbeat?.every).toBe("30m");
expect( expect(
cfg.agents?.defaults?.models?.["anthropic/claude-opus-4-5"]?.params?.cacheControlTtl, cfg.agents?.defaults?.models?.["anthropic/claude-opus-4-5"]?.params?.cacheRetention,
).toBe("1h"); ).toBe("short");
}); });
}); });

View File

@@ -392,12 +392,12 @@ export function applyContextPruningDefaults(cfg: OpenClawConfig): OpenClawConfig
} }
const current = entry ?? {}; const current = entry ?? {};
const params = (current as { params?: Record<string, unknown> }).params ?? {}; const params = (current as { params?: Record<string, unknown> }).params ?? {};
if (typeof params.cacheControlTtl === "string") { if (typeof params.cacheRetention === "string") {
continue; continue;
} }
nextModels[key] = { nextModels[key] = {
...(current as Record<string, unknown>), ...(current as Record<string, unknown>),
params: { ...params, cacheControlTtl: "1h" }, params: { ...params, cacheRetention: "short" },
}; };
modelsMutated = true; modelsMutated = true;
} }
@@ -410,10 +410,10 @@ export function applyContextPruningDefaults(cfg: OpenClawConfig): OpenClawConfig
const entry = nextModels[key]; const entry = nextModels[key];
const current = entry ?? {}; const current = entry ?? {};
const params = (current as { params?: Record<string, unknown> }).params ?? {}; const params = (current as { params?: Record<string, unknown> }).params ?? {};
if (typeof params.cacheControlTtl !== "string") { if (typeof params.cacheRetention !== "string") {
nextModels[key] = { nextModels[key] = {
...(current as Record<string, unknown>), ...(current as Record<string, unknown>),
params: { ...params, cacheControlTtl: "1h" }, params: { ...params, cacheRetention: "short" },
}; };
modelsMutated = true; modelsMutated = true;
} }