diff --git a/open-sse/translator/helpers/claudeHelper.ts b/open-sse/translator/helpers/claudeHelper.ts index bf4e589d0f..d42c86dc08 100644 --- a/open-sse/translator/helpers/claudeHelper.ts +++ b/open-sse/translator/helpers/claudeHelper.ts @@ -148,11 +148,14 @@ export function prepareClaudeRequest( ): ClaudeRequestBody { // 1. System: remove all cache_control, add only to last block with ttl 1h // In passthrough mode, preserve existing cache_control markers + const supportsPromptCaching = + provider === "claude" || provider?.startsWith?.("anthropic-compatible-"); + const systemBlocks = body.system; if (systemBlocks && Array.isArray(systemBlocks) && !preserveCacheControl) { body.system = systemBlocks.map((block, i) => { const { cache_control, ...rest } = block; - if (i === systemBlocks.length - 1) { + if (i === systemBlocks.length - 1 && supportsPromptCaching) { return { ...rest, cache_control: { type: "ephemeral", ttl: "1h" } }; } return rest; @@ -217,7 +220,7 @@ export function prepareClaudeRequest( // - cache the second-to-last user turn for conversation reuse // - cache the last assistant turn so the next user turn can reuse it // Skip in passthrough mode to preserve client's cache_control markers - if (!preserveCacheControl) { + if (!preserveCacheControl && supportsPromptCaching) { const userMessageIndexes = filtered.reduce((indexes, msg, index) => { if (msg?.role === "user") indexes.push(index); return indexes; @@ -238,7 +241,12 @@ export function prepareClaudeRequest( if (msg.role === "assistant" && content.length > 0) { // Add cache_control to last block of first (from end) assistant with content // Skip in passthrough mode to preserve client's cache_control markers - if (!preserveCacheControl && !lastAssistantProcessed && markMessageCacheControl(msg)) { + if ( + !preserveCacheControl && + supportsPromptCaching && + !lastAssistantProcessed && + markMessageCacheControl(msg) + ) { lastAssistantProcessed = true; } @@ -283,10 +291,12 @@ export function prepareClaudeRequest( const { cache_control, ...rest } = tool; return rest; }); - for (let i = body.tools.length - 1; i >= 0; i--) { - if (!body.tools[i].defer_loading) { - body.tools[i].cache_control = { type: "ephemeral", ttl: "1h" }; - break; + if (supportsPromptCaching) { + for (let i = body.tools.length - 1; i >= 0; i--) { + if (!body.tools[i].defer_loading) { + body.tools[i].cache_control = { type: "ephemeral", ttl: "1h" }; + break; + } } } } diff --git a/open-sse/translator/request/openai-to-gemini.ts b/open-sse/translator/request/openai-to-gemini.ts index 69b3075c9e..5e854ec996 100644 --- a/open-sse/translator/request/openai-to-gemini.ts +++ b/open-sse/translator/request/openai-to-gemini.ts @@ -538,27 +538,23 @@ function wrapInCloudCodeEnvelopeForClaude(model, claudeRequest, credentials = nu }); if (geminiTools) { envelope.request.tools = geminiTools; - envelope.request.toolConfig = { - functionCallingConfig: { mode: "VALIDATED" }, - }; } } // Add system instruction (Antigravity default) - const defaultPart = { text: ANTIGRAVITY_DEFAULT_SYSTEM }; - const systemParts = [defaultPart]; + let combinedSystemText = ANTIGRAVITY_DEFAULT_SYSTEM; if (claudeRequest.system) { if (Array.isArray(claudeRequest.system)) { for (const block of claudeRequest.system) { - if (block.text) systemParts.push({ text: block.text }); + if (block.text) combinedSystemText += "\n\n" + block.text; } } else if (typeof claudeRequest.system === "string") { - systemParts.push({ text: claudeRequest.system }); + combinedSystemText += "\n\n" + claudeRequest.system; } } - envelope.request.systemInstruction = { role: "user", parts: systemParts }; + envelope.request.systemInstruction = { role: "user", parts: [{ text: combinedSystemText }] }; const changedToolNameMap = buildChangedToolNameMap(toolNameMap); if (changedToolNameMap) {