mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
fix: handle Mistral thinking type in streaming responses
- Filter out "thinking" type from content arrays in Mistral responses - Only yield text content when actual text is present - Add comprehensive test coverage for thinking type handling - Fixes #6842: Magistral responses failing validation due to unsupported thinking type
This commit is contained in:
parent
ad0e33e2d9
commit
9fbaf516d8
2 changed files with 94 additions and 3 deletions
|
|
@ -118,6 +118,86 @@ describe("MistralHandler", () => {
|
|||
expect(results[0].text).toBe("Test response")
|
||||
})
|
||||
|
||||
it("should handle thinking type in content array", async () => {
|
||||
// Override the mock to return content with thinking type
|
||||
mockCreate.mockImplementationOnce(async (_options) => {
|
||||
const stream = {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
data: {
|
||||
choices: [
|
||||
{
|
||||
delta: {
|
||||
content: [
|
||||
{ type: "thinking", text: "Let me think about this..." },
|
||||
{ type: "text", text: "Here is my response" },
|
||||
],
|
||||
},
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
return stream
|
||||
})
|
||||
|
||||
const iterator = handler.createMessage(systemPrompt, messages)
|
||||
const results: ApiStreamTextChunk[] = []
|
||||
|
||||
for await (const chunk of iterator) {
|
||||
if ("text" in chunk) {
|
||||
results.push(chunk as ApiStreamTextChunk)
|
||||
}
|
||||
}
|
||||
|
||||
// Should only include the text type content, not thinking
|
||||
expect(results.length).toBe(1)
|
||||
expect(results[0].text).toBe("Here is my response")
|
||||
})
|
||||
|
||||
it("should handle mixed content types gracefully", async () => {
|
||||
// Override the mock to return various content types
|
||||
mockCreate.mockImplementationOnce(async (_options) => {
|
||||
const stream = {
|
||||
[Symbol.asyncIterator]: async function* () {
|
||||
yield {
|
||||
data: {
|
||||
choices: [
|
||||
{
|
||||
delta: {
|
||||
content: [
|
||||
{ type: "thinking", text: "Processing..." },
|
||||
{ type: "text", text: "First part" },
|
||||
{ type: "unknown", data: "some data" },
|
||||
{ type: "text", text: " Second part" },
|
||||
],
|
||||
},
|
||||
index: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
return stream
|
||||
})
|
||||
|
||||
const iterator = handler.createMessage(systemPrompt, messages)
|
||||
const results: ApiStreamTextChunk[] = []
|
||||
|
||||
for await (const chunk of iterator) {
|
||||
if ("text" in chunk) {
|
||||
results.push(chunk as ApiStreamTextChunk)
|
||||
}
|
||||
}
|
||||
|
||||
// Should concatenate only text type content
|
||||
expect(results.length).toBe(1)
|
||||
expect(results[0].text).toBe("First part Second part")
|
||||
})
|
||||
|
||||
it("should handle errors gracefully", async () => {
|
||||
mockCreate.mockRejectedValueOnce(new Error("API Error"))
|
||||
await expect(handler.createMessage(systemPrompt, messages).next()).rejects.toThrow("API Error")
|
||||
|
|
|
|||
|
|
@ -57,10 +57,17 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
|
|||
if (typeof delta.content === "string") {
|
||||
content = delta.content
|
||||
} else if (Array.isArray(delta.content)) {
|
||||
content = delta.content.map((c) => (c.type === "text" ? c.text : "")).join("")
|
||||
// Handle array content, filtering out "thinking" type and other non-text types
|
||||
content = delta.content
|
||||
.filter((c: any) => c.type === "text")
|
||||
.map((c: any) => c.text || "")
|
||||
.join("")
|
||||
}
|
||||
|
||||
yield { type: "text", text: content }
|
||||
// Only yield if we have actual content to send
|
||||
if (content) {
|
||||
yield { type: "text", text: content }
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk.data.usage) {
|
||||
|
|
@ -97,7 +104,11 @@ export class MistralHandler extends BaseProvider implements SingleCompletionHand
|
|||
const content = response.choices?.[0]?.message.content
|
||||
|
||||
if (Array.isArray(content)) {
|
||||
return content.map((c) => (c.type === "text" ? c.text : "")).join("")
|
||||
// Handle array content, filtering out "thinking" type and other non-text types
|
||||
return content
|
||||
.filter((c: any) => c.type === "text")
|
||||
.map((c: any) => c.text || "")
|
||||
.join("")
|
||||
}
|
||||
|
||||
return content || ""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue