Visitar URL original
fix(provider): port upstream Bedrock tool-result image hoisting (anomalyco/opencode#50272) by devin-ai-integration[bot] · Pull Request #1715 · AltimateAI/altimate-code · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/opencode/src/session/message-v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,12 @@ export namespace MessageV2 {
const supportsMediaInToolResults = (() => {
if (model.api.npm === "@ai-sdk/anthropic") return true
if (model.api.npm === "@ai-sdk/openai") return true
if (model.api.npm === "@ai-sdk/amazon-bedrock") return true
// altimate_change start — upstream_fix: Bedrock Converse only accepts tool-result media for Claude, Nova and Llama 4 (anomalyco/opencode#50272)
if (model.api.npm === "@ai-sdk/amazon-bedrock") {
const id = model.api.id.toLowerCase()
return id.includes("anthropic.") || id.includes("nova") || id.includes("llama4") || id.includes("llama-4")
}
// altimate_change end
if (model.api.npm === "@ai-sdk/google-vertex/anthropic") return true
if (model.api.npm === "@ai-sdk/google") {
const id = model.api.id.toLowerCase()
Expand Down
87 changes: 87 additions & 0 deletions packages/opencode/test/session/message-v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,93 @@ describe("session.message-v2.toModelMessage", () => {
])
})

describe("bedrock tool-result images", () => {
const png = Buffer.from("png").toString("base64")
const bedrock = (apiID: string): Provider.Model => ({
...model,
id: ModelID.make(`amazon-bedrock/${apiID}`),
providerID: ProviderID.make("amazon-bedrock"),
api: { id: apiID, url: "https://bedrock-runtime.us-east-1.amazonaws.com", npm: "@ai-sdk/amazon-bedrock" },
capabilities: {
...model.capabilities,
attachment: true,
input: { ...model.capabilities.input, image: true },
},
})
const history = (): SessionV1.WithParts[] => [
{
info: userInfo("m-user-bedrock-png"),
parts: [{ ...basePart("m-user-bedrock-png", "u1"), type: "text", text: "read it" }] as SessionV1.Part[],
},
{
info: assistantInfo("m-assistant-bedrock-png", "m-user-bedrock-png"),
parts: [
{
...basePart("m-assistant-bedrock-png", "a1"),
type: "tool",
callID: "call-bedrock-png-1",
tool: "read",
state: {
status: "completed",
input: { filePath: "/tmp/a.png" },
output: "Image read successfully",
title: "Read",
metadata: {},
time: { start: 0, end: 1 },
attachments: [
{
...basePart("m-assistant-bedrock-png", "f1"),
type: "file",
mime: "image/png",
filename: "a.png",
url: `data:image/png;base64,${png}`,
},
],
},
},
] as SessionV1.Part[],
},
]

test.each(["us.anthropic.claude-sonnet-4-6", "amazon.nova-pro-v1:0", "us.meta.llama4-maverick-17b-instruct-v1:0"])(
"keeps images in the tool result for %s",
async (apiID) => {
const result = await MessageV2.toModelMessages(history() as unknown as MessageV2.WithParts[], bedrock(apiID))
expect(result).toHaveLength(3)
expect(result[2]?.content).toMatchObject([
{
type: "tool-result",
output: {
type: "content",
value: [
{ type: "text", text: "Image read successfully" },
{ type: "media", mediaType: "image/png", data: png },
],
},
},
])
},
)

test.each(["openai.gpt-oss-120b-1:0", "mistral.pixtral-large-2502-v1:0"])(
"hoists images into a user message for %s",
async (apiID) => {
const result = await MessageV2.toModelMessages(history() as unknown as MessageV2.WithParts[], bedrock(apiID))
expect(result).toHaveLength(4)
expect(result[2]?.content).toMatchObject([
{ type: "tool-result", output: { type: "text", value: "Image read successfully" } },
])
expect(result[3]).toMatchObject({
role: "user",
content: [
{ type: "text", text: MessageV2.SYNTHETIC_ATTACHMENT_PROMPT },
{ type: "file", mediaType: "image/png" },
],
})
},
)
})

test("omits provider metadata when assistant model differs", async () => {
const userID = "m-user"
const assistantID = "m-assistant"
Expand Down
Loading