@@ -11,9 +11,12 @@ import {
1111 OPTIONAL_PROMPT_CACHING_MODELS ,
1212 REASONING_MODELS ,
1313} from "../../shared/api"
14+
1415import { convertToOpenAiMessages } from "../transform/openai-format"
1516import { ApiStreamChunk } from "../transform/stream"
1617import { convertToR1Format } from "../transform/r1-format"
18+ import { addCacheBreakpoints as addAnthropicCacheBreakpoints } from "../transform/caching/anthropic"
19+ import { addCacheBreakpoints as addGeminiCacheBreakpoints } from "../transform/caching/gemini"
1720
1821import { getModelParams , SingleCompletionHandler } from "../index"
1922import { DEFAULT_HEADERS , DEEP_SEEK_DEFAULT_TEMPERATURE } from "./constants"
@@ -93,42 +96,11 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
9396
9497 const isCacheAvailable = promptCache . supported && ( ! promptCache . optional || this . options . promptCachingEnabled )
9598
96- // Prompt caching: https://openrouter.ai/docs/prompt-caching
97- // Now with Gemini support: https://openrouter.ai/docs/features/prompt-caching
98- // Note that we don't check the `ModelInfo` object because it is cached
99- // in the settings for OpenRouter and the value could be stale.
99+ // https://openrouter.ai/docs/features/prompt-caching
100100 if ( isCacheAvailable ) {
101- openAiMessages [ 0 ] = {
102- role : "system" ,
103- // @ts -ignore-next-line
104- content : [ { type : "text" , text : systemPrompt , cache_control : { type : "ephemeral" } } ] ,
105- }
106-
107- // Add cache_control to the last two user messages
108- // (note: this works because we only ever add one user message at a time, but if we added multiple we'd need to mark the user message before the last assistant message)
109- const lastTwoUserMessages = openAiMessages . filter ( ( msg ) => msg . role === "user" ) . slice ( - 2 )
110-
111- lastTwoUserMessages . forEach ( ( msg ) => {
112- if ( typeof msg . content === "string" ) {
113- msg . content = [ { type : "text" , text : msg . content } ]
114- }
115-
116- if ( Array . isArray ( msg . content ) ) {
117- // NOTE: This is fine since env details will always be added
118- // at the end. But if it wasn't there, and the user added a
119- // image_url type message, it would pop a text part before
120- // it and then move it after to the end.
121- let lastTextPart = msg . content . filter ( ( part ) => part . type === "text" ) . pop ( )
122-
123- if ( ! lastTextPart ) {
124- lastTextPart = { type : "text" , text : "..." }
125- msg . content . push ( lastTextPart )
126- }
127-
128- // @ts -ignore-next-line
129- lastTextPart [ "cache_control" ] = { type : "ephemeral" }
130- }
131- } )
101+ modelId . startsWith ( "google" )
102+ ? addGeminiCacheBreakpoints ( systemPrompt , openAiMessages , 10 ) // Pass frequency
103+ : addAnthropicCacheBreakpoints ( systemPrompt , openAiMessages )
132104 }
133105
134106 // https://openrouter.ai/docs/transforms
0 commit comments