fix: ensure tool_use is always followed by tool_result (#22646)
Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
This commit is contained in:
@@ -75,7 +75,7 @@ export namespace ProviderTransform {
|
||||
|
||||
if (model.api.id.includes("claude")) {
|
||||
const scrub = (id: string) => id.replace(/[^a-zA-Z0-9_-]/g, "_")
|
||||
return msgs.map((msg) => {
|
||||
msgs = msgs.map((msg) => {
|
||||
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
||||
return {
|
||||
...msg,
|
||||
@@ -101,6 +101,31 @@ export namespace ProviderTransform {
|
||||
return msg
|
||||
})
|
||||
}
|
||||
if (["@ai-sdk/anthropic", "@ai-sdk/google-vertex/anthropic"].includes(model.api.npm)) {
|
||||
// Anthropic rejects assistant turns where tool_use blocks are followed by non-tool
|
||||
// content, e.g. [tool_use, tool_use, text], with:
|
||||
// `tool_use` ids were found without `tool_result` blocks immediately after...
|
||||
//
|
||||
// Reorder that invalid shape into [text] + [tool_use, tool_use]. Consecutive
|
||||
// assistant messages are later merged by the provider/SDK, so preserving the
|
||||
// original [tool_use...] then [text] order still produces the invalid payload.
|
||||
//
|
||||
// The root cause appears to be somewhere upstream where the stream is originally
|
||||
// processed. We were unable to locate an exact narrower reproduction elsewhere,
|
||||
// so we keep this transform in place for the time being.
|
||||
msgs = msgs.flatMap((msg) => {
|
||||
if (msg.role !== "assistant" || !Array.isArray(msg.content)) return [msg]
|
||||
|
||||
const parts = msg.content
|
||||
const first = parts.findIndex((part) => part.type === "tool-call")
|
||||
if (first === -1) return [msg]
|
||||
if (!parts.slice(first).some((part) => part.type !== "tool-call")) return [msg]
|
||||
return [
|
||||
{ ...msg, content: parts.filter((part) => part.type !== "tool-call") },
|
||||
{ ...msg, content: parts.filter((part) => part.type === "tool-call") },
|
||||
]
|
||||
})
|
||||
}
|
||||
if (
|
||||
model.providerID === "mistral" ||
|
||||
model.api.id.toLowerCase().includes("mistral") ||
|
||||
|
||||
Reference in New Issue
Block a user