@@ -14,7 +14,6 @@ import {
1414import {
1515 type AnthropicAssistantContentBlock ,
1616 type AnthropicAssistantMessage ,
17- type AnthropicMessage ,
1817 type AnthropicMessagesPayload ,
1918 type AnthropicResponse ,
2019 type AnthropicTextBlock ,
@@ -38,9 +37,9 @@ export function translateToOpenAI(
3837 return {
3938 model : modelId ,
4039 messages : translateAnthropicMessagesToOpenAI (
41- payload . messages ,
42- payload . system ,
40+ payload ,
4341 modelId ,
42+ thinkingBudget ,
4443 ) ,
4544 max_tokens : payload . max_tokens ,
4645 stop : payload . stop_sequences ,
@@ -86,32 +85,74 @@ function translateModelName(model: string): string {
8685}
8786
8887function translateAnthropicMessagesToOpenAI (
89- anthropicMessages : Array < AnthropicMessage > ,
90- system : string | Array < AnthropicTextBlock > | undefined ,
88+ payload : AnthropicMessagesPayload ,
9189 modelId : string ,
90+ thinkingBudget : number | undefined ,
9291) : Array < Message > {
93- const systemMessages = handleSystemPrompt ( system )
94-
95- const otherMessages = anthropicMessages . flatMap ( ( message ) =>
92+ const systemMessages = handleSystemPrompt (
93+ payload . system ,
94+ modelId ,
95+ thinkingBudget ,
96+ )
97+ const otherMessages = payload . messages . flatMap ( ( message ) =>
9698 message . role === "user" ?
9799 handleUserMessage ( message )
98100 : handleAssistantMessage ( message , modelId ) ,
99101 )
100-
102+ if ( modelId . startsWith ( "claude" ) && thinkingBudget ) {
103+ const reminder =
104+ "<system-reminder>you MUST follow interleaved_thinking_protocol</system-reminder>"
105+ const firstUserIndex = otherMessages . findIndex ( ( m ) => m . role === "user" )
106+ if ( firstUserIndex !== - 1 ) {
107+ const userMessage = otherMessages [ firstUserIndex ]
108+ if ( typeof userMessage . content === "string" ) {
109+ userMessage . content = reminder + "\n\n" + userMessage . content
110+ } else if ( Array . isArray ( userMessage . content ) ) {
111+ userMessage . content = [
112+ { type : "text" , text : reminder } ,
113+ ...userMessage . content ,
114+ ] as Array < ContentPart >
115+ }
116+ }
117+ }
101118 return [ ...systemMessages , ...otherMessages ]
102119}
103120
104121function handleSystemPrompt (
105122 system : string | Array < AnthropicTextBlock > | undefined ,
123+ modelId : string ,
124+ thinkingBudget : number | undefined ,
106125) : Array < Message > {
107126 if ( ! system ) {
108127 return [ ]
109128 }
110129
130+ let extraPrompt = ""
131+ if ( modelId . startsWith ( "claude" ) && thinkingBudget ) {
132+ extraPrompt = `
133+ <interleaved_thinking_protocol>
134+ ABSOLUTE REQUIREMENT - NON-NEGOTIABLE:
135+ The current thinking_mode is interleaved, Whenever you have the result of a function call, think carefully , MUST output a thinking block
136+ RULES:
137+ Tool result → thinking block (ALWAYS, no exceptions)
138+ This is NOT optional - it is a hard requirement
139+ The thinking block must contain substantive reasoning (minimum 3-5 sentences)
140+ Think about: what the results mean, what to do next, how to answer the user
141+ NEVER skip this step, even if the result seems simple or obvious
142+ </interleaved_thinking_protocol>`
143+ }
144+
111145 if ( typeof system === "string" ) {
112- return [ { role : "system" , content : system } ]
146+ return [ { role : "system" , content : system + extraPrompt } ]
113147 } else {
114- const systemText = system . map ( ( block ) => block . text ) . join ( "\n\n" )
148+ const systemText = system
149+ . map ( ( block , index ) => {
150+ if ( index === 0 ) {
151+ return block . text + extraPrompt
152+ }
153+ return block . text
154+ } )
155+ . join ( "\n\n" )
115156 return [ { role : "system" , content : systemText } ]
116157 }
117158}
0 commit comments