Skip to content

Commit 68fb141

Browse files
committed
fix(bedrock): order tool results first
Keep Bedrock user tool_result blocks ahead of image and text blocks so parallel image tool results satisfy the native tool protocol. Bump extension package to 4.99.5.
1 parent 388bd49 commit 68fb141

3 files changed

Lines changed: 81 additions & 2 deletions

File tree

src/api/transform/__tests__/bedrock-converse-format.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,44 @@ describe("convertToBedrockConverseMessages", () => {
345345
expect("text" in userContent).toBe(false)
346346
})
347347

348+
it("moves all user tool results before images and text for Bedrock native tool protocol", () => {
349+
const messages: Anthropic.Messages.MessageParam[] = [
350+
{
351+
role: "assistant",
352+
content: [
353+
{ type: "tool_use", id: "call-1", name: "read_file", input: { path: "a.png" } },
354+
{ type: "tool_use", id: "call-2", name: "read_file", input: { path: "b.png" } },
355+
{ type: "tool_use", id: "call-3", name: "read_file", input: { path: "c.png" } },
356+
],
357+
},
358+
{
359+
role: "user",
360+
content: [
361+
{ type: "tool_result", tool_use_id: "call-1", content: "Read a.png" } as any,
362+
testImageBlock(),
363+
{ type: "tool_result", tool_use_id: "call-2", content: "Read b.png" } as any,
364+
testImageBlock(),
365+
{ type: "tool_result", tool_use_id: "call-3", content: "Read c.png" } as any,
366+
testImageBlock(),
367+
{ type: "text", text: "Screenshots attached." },
368+
],
369+
},
370+
]
371+
372+
const result = convertToBedrockConverseMessages(messages)
373+
const userContent = result[1]?.content ?? []
374+
375+
expect(userContent.map(bedrockBlockKind)).toEqual([
376+
"toolResult:call-1",
377+
"toolResult:call-2",
378+
"toolResult:call-3",
379+
"image",
380+
"image",
381+
"image",
382+
"text",
383+
])
384+
})
385+
348386
it("handles text content correctly", () => {
349387
const messages: Anthropic.Messages.MessageParam[] = [
350388
{
@@ -585,3 +623,27 @@ describe("convertToBedrockConverseMessages", () => {
585623
})
586624
})
587625
})
626+
627+
function testImageBlock(): Anthropic.Messages.ImageBlockParam {
628+
return {
629+
type: "image",
630+
source: {
631+
type: "base64",
632+
data: "SGVsbG8=",
633+
media_type: "image/png",
634+
},
635+
}
636+
}
637+
638+
function bedrockBlockKind(block: ContentBlock): string {
639+
if ("toolResult" in block && block.toolResult) {
640+
return `toolResult:${block.toolResult.toolUseId}`
641+
}
642+
if ("image" in block && block.image) {
643+
return "image"
644+
}
645+
if ("text" in block) {
646+
return "text"
647+
}
648+
return "unknown"
649+
}

src/api/transform/bedrock-converse-format.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ export function convertToBedrockConverseMessages(anthropicMessages: Anthropic.Me
4444
}
4545
}
4646

47+
const anthropicContent =
48+
role === "user" ? orderUserContentForBedrock(anthropicMessage.content) : anthropicMessage.content
49+
4750
// Process complex content types
48-
const content = anthropicMessage.content.map((block) => {
51+
const content = anthropicContent.map((block) => {
4952
const messageBlock = block as BedrockMessageContent & {
5053
id?: string
5154
tool_use_id?: string
@@ -209,3 +212,17 @@ export function convertToBedrockConverseMessages(anthropicMessages: Anthropic.Me
209212
}
210213
})
211214
}
215+
216+
function orderUserContentForBedrock(
217+
content: Anthropic.Messages.ContentBlockParam[],
218+
): Anthropic.Messages.ContentBlockParam[] {
219+
const toolResults = content.filter((block) => block.type === "tool_result")
220+
221+
if (toolResults.length === 0) {
222+
return content
223+
}
224+
225+
const remainingBlocks = content.filter((block) => block.type !== "tool_result")
226+
227+
return [...toolResults, ...remainingBlocks]
228+
}

src/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "%extension.displayName%",
44
"description": "%extension.description%",
55
"publisher": "allquixotic",
6-
"version": "4.99.4",
6+
"version": "4.99.5",
77
"icon": "assets/icons/icon.png",
88
"galleryBanner": {
99
"color": "#617A91",

0 commit comments

Comments
 (0)