diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts index d326976f1ae..e4cd17a6890 100644 --- a/packages/opencode/src/session/message-v2.ts +++ b/packages/opencode/src/session/message-v2.ts @@ -527,7 +527,7 @@ export namespace MessageV2 { toolCallId: part.callID, input: part.state.input, output: part.state.time.compacted ? "[Old tool result content cleared]" : part.state.output, - callProviderMetadata: part.metadata, + callProviderMetadata: part.metadata ?? {}, }) } if (part.state.status === "error") diff --git a/packages/opencode/test/session/issue-8862.test.ts b/packages/opencode/test/session/issue-8862.test.ts new file mode 100644 index 00000000000..aa19d77e07d --- /dev/null +++ b/packages/opencode/test/session/issue-8862.test.ts @@ -0,0 +1,96 @@ +import { describe, expect, test } from "bun:test" +import { MessageV2 } from "../../src/session/message-v2" + +const sessionID = "session" + +function assistantInfo(id: string, parentID: string): MessageV2.Assistant { + return { + id, + sessionID, + role: "assistant", + time: { created: 0 }, + parentID, + modelID: "model", + providerID: "provider", + mode: "", + agent: "agent", + path: { cwd: "/", root: "/" }, + cost: 0, + tokens: { + input: 0, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + } as unknown as MessageV2.Assistant +} + +function basePart(messageID: string, id: string) { + return { + id, + sessionID, + messageID, + } +} + +describe("issue-8862 regression test", () => { + test("successfully converts tool results with undefined metadata/attachments", () => { + const userID = "m-user" + const assistantID = "m-assistant" + + const input: MessageV2.WithParts[] = [ + { + info: assistantInfo(assistantID, userID), + parts: [ + { + ...basePart(assistantID, "a2"), + type: "tool", + callID: "call-1", + tool: "bash", + state: { + status: "completed", + input: { cmd: "ls" }, + output: "ok", + title: "Bash", + metadata: undefined as any, + time: { start: 0, end: 1 }, + attachments: undefined as any, + } as any, + metadata: undefined as any, + }, + ] as MessageV2.Part[], + }, + ] + + expect(MessageV2.toModelMessage(input)).toStrictEqual([ + { + role: "assistant", + content: [ + { + type: "tool-call", + toolCallId: "call-1", + toolName: "bash", + input: { cmd: "ls" }, + providerExecuted: undefined, + providerOptions: {}, + }, + ], + }, + { + role: "tool", + content: [ + { + type: "tool-result", + toolCallId: "call-1", + toolName: "bash", + output: { + type: "text", + value: "ok", + }, + providerOptions: {}, + }, + ], + }, + ]) + }) +})