From fa510665abc5b5f8da2e5543cfb2ae38c759edbe Mon Sep 17 00:00:00 2001 From: reesilva Date: Wed, 10 Jun 2026 23:10:44 +0200 Subject: [PATCH 1/3] feat(emit-diff-content): add content to edit/write permissions --- packages/opencode/src/acp/permission.ts | 12 +++++++++++- packages/opencode/src/tool/edit.ts | 4 ++++ packages/opencode/src/tool/write.ts | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/acp/permission.ts b/packages/opencode/src/acp/permission.ts index 357754e093e9..5f0aa356027a 100644 --- a/packages/opencode/src/acp/permission.ts +++ b/packages/opencode/src/acp/permission.ts @@ -1,4 +1,4 @@ -import type { AgentSideConnection, PermissionOption, RequestPermissionResponse } from "@agentclientprotocol/sdk" +import type { AgentSideConnection, PermissionOption, RequestPermissionResponse, ToolCallContent } from "@agentclientprotocol/sdk" import type { Event, OpencodeClient } from "@opencode-ai/sdk/v2" import { applyPatch } from "diff" import { exists, readText } from "@/util/filesystem" @@ -61,6 +61,7 @@ export class Handler { rawInput: permission.metadata, kind: toToolKind(permission.permission), locations: toLocations(permission.permission, permission.metadata), + content: editDiffContent(permission.permission, permission.metadata), }, options: permissionOptions, }) @@ -111,6 +112,15 @@ export class Handler { } } +function editDiffContent(permission: string, metadata: ToolInput): ToolCallContent[] | undefined { + if (permission !== "edit") return undefined + const path = stringValue(metadata.filepath) + const oldText = stringValue(metadata.oldString) + const newText = stringValue(metadata.newString) + if (!path || oldText === undefined || newText === undefined) return undefined + return [{ type: "diff", path, oldText, newText }] +} + function selectedReply(result: RequestPermissionResponse): Reply { if (result.outcome.outcome !== "selected") return "reject" if (result.outcome.optionId === "once" || result.outcome.optionId === "always") return result.outcome.optionId diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index a92e4720c0fc..140ea210ec0a 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -106,6 +106,8 @@ export const EditTool = Tool.define( metadata: { filepath: filePath, diff, + oldString: contentOld, + newString: contentNew, }, }) yield* afs.writeWithDirs(filePath, Bom.join(contentNew, desiredBom)) @@ -149,6 +151,8 @@ export const EditTool = Tool.define( metadata: { filepath: filePath, diff, + oldString: contentOld, + newString: contentNew, }, }) diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index 37be6d8c47bc..51d08e69e06e 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -58,6 +58,8 @@ export const WriteTool = Tool.define( metadata: { filepath, diff, + oldString: contentOld, + newString: contentNew, }, }) From 0c993471d40a8ee8ec97bceb06750ae5232bf348 Mon Sep 17 00:00:00 2001 From: reesilva Date: Fri, 12 Jun 2026 00:38:21 +0200 Subject: [PATCH 2/3] feat(emit-diff): fix for verbose_output case --- packages/opencode/src/acp/tool.ts | 11 ++++++++--- packages/opencode/src/tool/write.ts | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/acp/tool.ts b/packages/opencode/src/acp/tool.ts index 4c39c0eff1fd..cb58611a8dd4 100644 --- a/packages/opencode/src/acp/tool.ts +++ b/packages/opencode/src/acp/tool.ts @@ -111,7 +111,11 @@ export function completedToolContent(toolName: string, state: CompletedToolState ] if (toToolKind(toolName) === "edit") { - content.push(...diffContent(state.input)) + const inputForDiff = + toolName.toLowerCase() === "write" && state.metadata && typeof state.metadata === "object" + ? { ...state.input, ...(state.metadata as Record) } + : state.input + content.push(...diffContent(inputForDiff)) } content.push(...imageContents(state.attachments ?? [])) @@ -280,9 +284,10 @@ function locationFrom(...values: unknown[]): ToolCallLocation[] { } function diffContent(input: ToolInput): ToolCallContent[] { - const oldText = stringValue(input.oldString) const newText = stringValue(input.newString) ?? stringValue(input.content) - if (oldText === undefined || newText === undefined) return [] + if (newText === undefined) return [] + + const oldText = stringValue(input.oldString) ?? null return [ { diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index 51d08e69e06e..32f929c1d7b7 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -97,6 +97,8 @@ export const WriteTool = Tool.define( diagnostics, filepath, exists: exists, + oldString: contentOld, + newString: contentNew, }, output, } From 0072f0ec31c0566cc825ed4d524ab9c44d0285ef Mon Sep 17 00:00:00 2001 From: reesilva Date: Fri, 12 Jun 2026 00:53:35 +0200 Subject: [PATCH 3/3] feat(emit-diff): remove conditional, write now emits oldContent --- packages/opencode/src/acp/tool.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/acp/tool.ts b/packages/opencode/src/acp/tool.ts index cb58611a8dd4..7c387ec65185 100644 --- a/packages/opencode/src/acp/tool.ts +++ b/packages/opencode/src/acp/tool.ts @@ -284,10 +284,9 @@ function locationFrom(...values: unknown[]): ToolCallLocation[] { } function diffContent(input: ToolInput): ToolCallContent[] { + const oldText = stringValue(input.oldString) const newText = stringValue(input.newString) ?? stringValue(input.content) - if (newText === undefined) return [] - - const oldText = stringValue(input.oldString) ?? null + if (oldText === undefined || newText === undefined) return [] return [ {