mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 14:22:09 +03:00
fix(cc-compatible): keep cache ttl ordering valid (#948)
This commit is contained in:
@@ -397,8 +397,14 @@ function buildClaudeCodeCompatibleSystemBlocks({
|
||||
}) {
|
||||
const customSystemBlocks =
|
||||
Array.isArray(systemBlocks) && systemBlocks.length > 0
|
||||
? systemBlocks
|
||||
? systemBlocks.map((block) => ({ ...block }))
|
||||
: extractCustomSystemBlocks(messages);
|
||||
const useLongSystemTtl =
|
||||
!preserveCacheControl ||
|
||||
customSystemBlocks.some((block) => readCacheControlTtl(block) === "1h");
|
||||
const systemCacheControl = useLongSystemTtl
|
||||
? { type: "ephemeral", ttl: "1h" }
|
||||
: { type: "ephemeral" };
|
||||
|
||||
const dateText = formatDate(now);
|
||||
const blocks: Array<Record<string, unknown>> = [
|
||||
@@ -409,17 +415,21 @@ function buildClaudeCodeCompatibleSystemBlocks({
|
||||
{
|
||||
type: "text",
|
||||
text: "You are a Claude agent, built on Anthropic's Claude Agent SDK.",
|
||||
cache_control: { type: "ephemeral" },
|
||||
cache_control: { ...systemCacheControl },
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: `You are Claude Code, Anthropic's official CLI for Claude.\n\nCWD: ${cwd}\nDate: ${dateText}`,
|
||||
cache_control: { type: "ephemeral" },
|
||||
cache_control: { ...systemCacheControl },
|
||||
},
|
||||
];
|
||||
|
||||
for (const systemBlock of customSystemBlocks) {
|
||||
blocks.push(systemBlock);
|
||||
const preparedBlock = { ...systemBlock };
|
||||
if (!preserveCacheControl || useLongSystemTtl) {
|
||||
preparedBlock.cache_control = { ...systemCacheControl };
|
||||
}
|
||||
blocks.push(preparedBlock);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -427,8 +437,8 @@ function buildClaudeCodeCompatibleSystemBlocks({
|
||||
customSystemBlocks.length > 0 &&
|
||||
!customSystemBlocks.some((block) => hasCacheControl(block))
|
||||
) {
|
||||
const lastCustomSystemBlock = customSystemBlocks[customSystemBlocks.length - 1];
|
||||
lastCustomSystemBlock.cache_control = { type: "ephemeral", ttl: "1h" };
|
||||
const lastCustomSystemBlock = blocks[blocks.length - 1];
|
||||
lastCustomSystemBlock.cache_control = { ...systemCacheControl };
|
||||
}
|
||||
|
||||
return blocks;
|
||||
@@ -650,7 +660,7 @@ function convertClaudeCodeCompatibleClaudeMessage(
|
||||
function extractCustomSystemBlocks(messages: MessageLike[] | undefined) {
|
||||
if (!Array.isArray(messages)) return [];
|
||||
|
||||
const blocks = messages
|
||||
return messages
|
||||
.filter((message) => {
|
||||
const role = String(message?.role || "").toLowerCase();
|
||||
return role === "system" || role === "developer";
|
||||
@@ -660,14 +670,7 @@ function extractCustomSystemBlocks(messages: MessageLike[] | undefined) {
|
||||
.map((text) => ({
|
||||
type: "text",
|
||||
text,
|
||||
cache_control: { type: "ephemeral" },
|
||||
}));
|
||||
|
||||
if (blocks.length > 0) {
|
||||
blocks[blocks.length - 1].cache_control = { type: "ephemeral", ttl: "1h" };
|
||||
}
|
||||
|
||||
return blocks;
|
||||
}
|
||||
|
||||
function applyClaudeCodeCompatibleMessageCacheStrategy(
|
||||
@@ -762,6 +765,10 @@ function hasCacheControl(value: unknown) {
|
||||
return !!readRecord(value)?.cache_control && typeof readRecord(value)?.cache_control === "object";
|
||||
}
|
||||
|
||||
function readCacheControlTtl(value: unknown) {
|
||||
return toNonEmptyString(readRecord(readRecord(value)?.cache_control)?.ttl);
|
||||
}
|
||||
|
||||
function findLastCacheableToolIndex(tools: Array<Record<string, unknown>>) {
|
||||
for (let i = tools.length - 1; i >= 0; i--) {
|
||||
if (!tools[i].defer_loading) {
|
||||
|
||||
@@ -109,6 +109,9 @@ test("buildClaudeCodeCompatibleRequest keeps prior role history while dropping t
|
||||
assert.deepEqual(payload.messages[2].content.at(-1).cache_control, { type: "ephemeral" });
|
||||
assert.equal(payload.system.length, 4);
|
||||
assert.equal(payload.system.at(-1).text, "sys");
|
||||
assert.deepEqual(payload.system[1].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[2].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[3].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.equal(payload.tools.length, 1);
|
||||
const { cache_control, ...toolWithoutCacheControl } = payload.tools[0];
|
||||
assert.deepEqual(toolWithoutCacheControl, {
|
||||
@@ -230,9 +233,38 @@ test("buildClaudeCodeCompatibleRequest supplements missing Claude cache markers
|
||||
assert.deepEqual(payload.messages[0].content[0].cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.messages[1].content[0].cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.messages[2].content[0].cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.system.at(-1).cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.tools[0].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
});
|
||||
|
||||
test("buildClaudeCodeCompatibleRequest upgrades built-in system cache markers when preserved system uses 1h", () => {
|
||||
const payload = buildClaudeCodeCompatibleRequest({
|
||||
sourceBody: {
|
||||
max_tokens: 64,
|
||||
},
|
||||
normalizedBody: {
|
||||
max_tokens: 64,
|
||||
messages: [{ role: "user", content: "fallback" }],
|
||||
},
|
||||
claudeBody: {
|
||||
system: [
|
||||
{ type: "text", text: "prefix", cache_control: { type: "ephemeral" } },
|
||||
{ type: "text", text: "stable", cache_control: { type: "ephemeral", ttl: "1h" } },
|
||||
],
|
||||
messages: [{ role: "user", content: [{ type: "text", text: "u1" }] }],
|
||||
tools: [],
|
||||
},
|
||||
model: "claude-sonnet-4-6",
|
||||
sessionId: "session-preserve-system-upgrade",
|
||||
preserveCacheControl: true,
|
||||
});
|
||||
|
||||
assert.deepEqual(payload.system[1].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[2].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[3].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[4].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
});
|
||||
|
||||
test("buildClaudeCodeCompatibleRequest marks final user turn and 1h system cache in non-preserve mode", () => {
|
||||
const largeUserPrompt = Array.from(
|
||||
{ length: 200 },
|
||||
@@ -257,10 +289,9 @@ test("buildClaudeCodeCompatibleRequest marks final user turn and 1h system cache
|
||||
preserveCacheControl: false,
|
||||
});
|
||||
|
||||
assert.deepEqual(payload.system.at(-1).cache_control, {
|
||||
type: "ephemeral",
|
||||
ttl: "1h",
|
||||
});
|
||||
assert.deepEqual(payload.system[1].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[2].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.system[3].cache_control, { type: "ephemeral", ttl: "1h" });
|
||||
assert.deepEqual(payload.messages[0].content[0].cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.messages[1].content[0].cache_control, { type: "ephemeral" });
|
||||
assert.deepEqual(payload.messages[2].content[0].cache_control, { type: "ephemeral" });
|
||||
|
||||
Reference in New Issue
Block a user