Merge 166c48af24 into ae614d919f
commit
9dce870ca4
|
|
@ -153,36 +153,30 @@ export namespace ProviderTransform {
|
|||
|
||||
if (typeof model.capabilities.interleaved === "object" && model.capabilities.interleaved.field) {
|
||||
const field = model.capabilities.interleaved.field
|
||||
const key =
|
||||
model.api.npm === "@ai-sdk/anthropic" || model.api.npm === "@ai-sdk/google-vertex/anthropic"
|
||||
? "anthropic"
|
||||
: "openaiCompatible"
|
||||
return msgs.map((msg) => {
|
||||
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
||||
const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
|
||||
const reasoningText = reasoningParts.map((part: any) => part.text).join("")
|
||||
if (msg.role !== "assistant" || !Array.isArray(msg.content)) return msg
|
||||
|
||||
// Filter out reasoning parts from content
|
||||
const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
|
||||
const reasoningText = msg.content
|
||||
.filter((part: any) => part.type === "reasoning")
|
||||
.map((part: any) => part.text)
|
||||
.join("")
|
||||
if (!reasoningText) return msg
|
||||
|
||||
// Include reasoning_content | reasoning_details directly on the message for all assistant messages
|
||||
if (reasoningText) {
|
||||
return {
|
||||
...msg,
|
||||
content: filteredContent,
|
||||
providerOptions: {
|
||||
...msg.providerOptions,
|
||||
openaiCompatible: {
|
||||
...(msg.providerOptions as any)?.openaiCompatible,
|
||||
[field]: reasoningText,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...msg,
|
||||
content: filteredContent,
|
||||
}
|
||||
return {
|
||||
...msg,
|
||||
content: msg.content.filter((part: any) => part.type !== "reasoning"),
|
||||
providerOptions: {
|
||||
...msg.providerOptions,
|
||||
[key]: {
|
||||
...(msg.providerOptions as any)?.[key],
|
||||
[field]: reasoningText,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return msg
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -911,6 +911,122 @@ describe("ProviderTransform.message - DeepSeek reasoning content", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("ProviderTransform.message - kimi-k2.5 anthropic interleaved reasoning", () => {
|
||||
const kimiModel = {
|
||||
id: "anthropic/kimi-k2.5",
|
||||
providerID: "anthropic",
|
||||
api: {
|
||||
id: "kimi-k2.5",
|
||||
url: "https://api.anthropic.com",
|
||||
npm: "@ai-sdk/anthropic",
|
||||
},
|
||||
name: "Kimi K2.5",
|
||||
capabilities: {
|
||||
temperature: true,
|
||||
reasoning: true,
|
||||
attachment: false,
|
||||
toolcall: true,
|
||||
input: { text: true, audio: false, image: false, video: false, pdf: false },
|
||||
output: { text: true, audio: false, image: false, video: false, pdf: false },
|
||||
interleaved: { field: "reasoning_content" },
|
||||
},
|
||||
cost: { input: 0.001, output: 0.002, cache: { read: 0.0001, write: 0.0002 } },
|
||||
limit: { context: 128000, output: 8192 },
|
||||
status: "active",
|
||||
options: {},
|
||||
headers: {},
|
||||
release_date: "2025-01-01",
|
||||
} as any
|
||||
|
||||
test("injects reasoning_content into providerOptions.anthropic", () => {
|
||||
const msgs = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "reasoning", text: "Let me think..." },
|
||||
{ type: "text", text: "The answer is 42" },
|
||||
],
|
||||
},
|
||||
] as any[]
|
||||
|
||||
const result = ProviderTransform.message(msgs, kimiModel, {})
|
||||
|
||||
expect(result).toHaveLength(1)
|
||||
expect(result[0].providerOptions?.anthropic?.reasoning_content).toBe("Let me think...")
|
||||
expect(result[0].content).toEqual([{ type: "text", text: "The answer is 42" }])
|
||||
})
|
||||
|
||||
test("does not inject when no reasoning parts exist", () => {
|
||||
const msgs = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "No reasoning here" }],
|
||||
},
|
||||
] as any[]
|
||||
|
||||
const result = ProviderTransform.message(msgs, kimiModel, {})
|
||||
|
||||
expect(result[0].providerOptions?.anthropic?.reasoning_content).toBeUndefined()
|
||||
expect(result[0].content).toEqual([{ type: "text", text: "No reasoning here" }])
|
||||
})
|
||||
|
||||
test("concatenates multiple reasoning parts", () => {
|
||||
const msgs = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "reasoning", text: "First thought. " },
|
||||
{ type: "reasoning", text: "Second thought." },
|
||||
{ type: "text", text: "Result" },
|
||||
],
|
||||
},
|
||||
] as any[]
|
||||
|
||||
const result = ProviderTransform.message(msgs, kimiModel, {})
|
||||
|
||||
expect(result[0].providerOptions?.anthropic?.reasoning_content).toBe("First thought. Second thought.")
|
||||
expect(result[0].content).toEqual([{ type: "text", text: "Result" }])
|
||||
})
|
||||
|
||||
test("works with google-vertex/anthropic SDK", () => {
|
||||
const vertexModel = {
|
||||
...kimiModel,
|
||||
api: { ...kimiModel.api, npm: "@ai-sdk/google-vertex/anthropic" },
|
||||
}
|
||||
const msgs = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "reasoning", text: "Thinking via vertex..." },
|
||||
{ type: "text", text: "Done" },
|
||||
],
|
||||
},
|
||||
] as any[]
|
||||
|
||||
const result = ProviderTransform.message(msgs, vertexModel, {})
|
||||
|
||||
expect(result[0].providerOptions?.anthropic?.reasoning_content).toBe("Thinking via vertex...")
|
||||
})
|
||||
|
||||
test("leaves non-assistant messages unchanged", () => {
|
||||
const msgs = [
|
||||
{ role: "user", content: "Hello" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "reasoning", text: "Thinking..." },
|
||||
{ type: "text", text: "Hi" },
|
||||
],
|
||||
},
|
||||
] as any[]
|
||||
|
||||
const result = ProviderTransform.message(msgs, kimiModel, {})
|
||||
|
||||
expect(result[0].content).toBe("Hello")
|
||||
expect(result[1].providerOptions?.anthropic?.reasoning_content).toBe("Thinking...")
|
||||
})
|
||||
})
|
||||
|
||||
describe("ProviderTransform.message - empty image handling", () => {
|
||||
const mockModel = {
|
||||
id: "anthropic/claude-3-5-sonnet",
|
||||
|
|
|
|||
Loading…
Reference in New Issue