Skip to content

Commit 1b75d59

Browse files
fix(ai-sdk): preserve reasoning parts in message conversion (RooCodeInc#11217)
* fix(ai-sdk): preserve reasoning parts in message conversion * fix(ai-sdk): convert message-level reasoning_content to reasoning part * fix(task): remove invalid openai-compatible from reasoning allowlist * feat: add isAiSdkProvider() method for dynamic AI SDK provider detection - Add isAiSdkProvider() method to ApiHandler interface - Default implementation in BaseProvider returns false - Override to return true in 11 AI SDK providers: deepseek, fireworks, mistral, groq, xai, cerebras, sambanova, huggingface, gemini, vertex, openai-compatible - Update Task.ts to use dynamic detection instead of hardcoded Set - Add method to FakeAIHandler and update test mocks * fix: handle reasoning parts in flattenAiSdkMessagesToStringContent - Strip reasoning parts when flattening messages for string-only models - Allow flattening when message contains only text and reasoning parts - Add tests for reasoning part handling in string-only model contexts This addresses the review feedback about ensuring flattenAiSdkMessagesToStringContent works correctly when reasoning parts are present (e.g., SambaNova DeepSeek). --------- Co-authored-by: daniel-lxs <ricciodaniel98@gmail.com>
1 parent 934f34e commit 1b75d59

19 files changed

Lines changed: 318 additions & 100 deletions

src/api/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ export interface ApiHandler {
117117
* @returns A promise resolving to the token count
118118
*/
119119
countTokens(content: Array<Anthropic.Messages.ContentBlockParam>): Promise<number>
120+
121+
/**
122+
* Indicates whether this provider uses the Vercel AI SDK for streaming.
123+
* AI SDK providers handle reasoning blocks differently and need to preserve
124+
* them in conversation history for proper round-tripping.
125+
*
126+
* @returns true if the provider uses AI SDK, false otherwise
127+
*/
128+
isAiSdkProvider(): boolean
120129
}
121130

122131
export function buildApiHandler(configuration: ProviderSettings): ApiHandler {

src/api/providers/base-provider.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,12 @@ export abstract class BaseProvider implements ApiHandler {
119119

120120
return countTokens(content, { useWorker: true })
121121
}
122+
123+
/**
124+
* Default implementation returns false.
125+
* AI SDK providers should override this to return true.
126+
*/
127+
isAiSdkProvider(): boolean {
128+
return false
129+
}
122130
}

src/api/providers/cerebras.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,8 @@ export class CerebrasHandler extends BaseProvider implements SingleCompletionHan
156156

157157
return text
158158
}
159+
160+
override isAiSdkProvider(): boolean {
161+
return true
162+
}
159163
}

src/api/providers/deepseek.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,8 @@ export class DeepSeekHandler extends BaseProvider implements SingleCompletionHan
166166

167167
return text
168168
}
169+
170+
override isAiSdkProvider(): boolean {
171+
return true
172+
}
169173
}

src/api/providers/fake-ai.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,8 @@ export class FakeAIHandler implements ApiHandler, SingleCompletionHandler {
7878
completePrompt(prompt: string): Promise<string> {
7979
return this.ai.completePrompt(prompt)
8080
}
81+
82+
isAiSdkProvider(): boolean {
83+
return false
84+
}
8185
}

src/api/providers/fireworks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,8 @@ export class FireworksHandler extends BaseProvider implements SingleCompletionHa
172172

173173
return text
174174
}
175+
176+
override isAiSdkProvider(): boolean {
177+
return true
178+
}
175179
}

src/api/providers/gemini.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,8 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
397397

398398
return totalCost
399399
}
400+
401+
override isAiSdkProvider(): boolean {
402+
return true
403+
}
400404
}

src/api/providers/groq.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,8 @@ export class GroqHandler extends BaseProvider implements SingleCompletionHandler
174174

175175
return text
176176
}
177+
178+
override isAiSdkProvider(): boolean {
179+
return true
180+
}
177181
}

src/api/providers/huggingface.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,8 @@ export class HuggingFaceHandler extends BaseProvider implements SingleCompletion
208208

209209
return text
210210
}
211+
212+
override isAiSdkProvider(): boolean {
213+
return true
214+
}
211215
}

src/api/providers/mistral.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,8 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
198198

199199
return text
200200
}
201+
202+
override isAiSdkProvider(): boolean {
203+
return true
204+
}
201205
}

0 commit comments

Comments
 (0)