diff --git a/packages/server/src/server/agent/providers/opencode/tool-call-detail-parser.ts b/packages/server/src/server/agent/providers/opencode/tool-call-detail-parser.ts index 39a7deb8c9..8214ebb1d0 100644 --- a/packages/server/src/server/agent/providers/opencode/tool-call-detail-parser.ts +++ b/packages/server/src/server/agent/providers/opencode/tool-call-detail-parser.ts @@ -312,6 +312,10 @@ const OpencodeKnownToolDetailSchema = z.union([ z.unknown(), (input) => toEditToolDetail(input, null), ), + // OpenCode v2 reports apply_patch as `patch`. + toolDetailBranchByToolName("patch", OpencodeApplyPatchTextInputSchema, z.unknown(), (input) => + toEditToolDetail(input, null), + ), toolDetailBranchByToolName( "apply_diff", OpencodeEditInputSchema, diff --git a/packages/server/src/server/agent/providers/opencode/tool-call-mapper.test.ts b/packages/server/src/server/agent/providers/opencode/tool-call-mapper.test.ts index 54f3faa514..1c9ba212e1 100644 --- a/packages/server/src/server/agent/providers/opencode/tool-call-mapper.test.ts +++ b/packages/server/src/server/agent/providers/opencode/tool-call-mapper.test.ts @@ -387,6 +387,34 @@ describe("opencode tool-call mapper", () => { }); }); + it("maps OpenCode v2 patch payloads from GPT models into edit detail", () => { + const item = expectMapped( + mapOpencodeToolCall({ + toolName: "patch", + callId: "opencode-v2-patch-1", + status: "completed", + input: { + patchText: + "*** Begin Patch\n*** Update File: patch.txt\n@@\n-north south\n+NORTH south\n*** End Patch", + }, + output: "Success. Updated the following files:\nM patch.txt", + }), + ); + + expect(item.detail).toEqual({ + type: "edit", + filePath: "patch.txt", + unifiedDiff: [ + "diff --git a/patch.txt b/patch.txt", + "--- a/patch.txt", + "+++ b/patch.txt", + "@@", + "-north south", + "+NORTH south", + ].join("\n"), + }); + }); + it("maps unknown tools to unknown detail with raw payloads", () => { const item = expectMapped( mapOpencodeToolCall({