From 2e3b9a2432a7ab71de1db2a65e76a8e5233bcf06 Mon Sep 17 00:00:00 2001 From: Aarav Date: Thu, 2 Apr 2026 04:21:43 -0600 Subject: [PATCH] fix: RevertBanner UI shows no changes after successful file revert (#8121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * core: fix revert diff showing incorrect changes after file restore When reverting a session, the diff was computed after files were already reverted to their pre-change state, producing an empty or wrong diff. By computing the diff before restoring files, the revert summary now correctly reflects what was actually undone for the user. * core: reduce revert diff size in DB to save storage Full file contents were being stored in the session summary diffs, causing unnecessary database bloat. The webview RevertBanner only needs file path, line counts, and status — not the full diff content. * chore(cli): add kilocode_change markers to revert diff changes --------- Co-authored-by: Marius --- packages/opencode/src/session/index.ts | 14 +++- packages/opencode/src/session/revert.ts | 17 ++++- packages/opencode/src/session/session.sql.ts | 6 +- packages/sdk/js/src/v2/gen/types.gen.ts | 14 +++- packages/sdk/openapi.json | 68 +++++++++++++++++++- 5 files changed, 111 insertions(+), 8 deletions(-) diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index a61cbe5c533..b2912e8223e 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -130,7 +130,18 @@ export namespace Session { additions: z.number(), deletions: z.number(), files: z.number(), - diffs: Snapshot.FileDiff.array().optional(), + // kilocode_change start - lightweight diff summary (no file contents) + diffs: z + .array( + z.object({ + file: z.string(), + additions: z.number(), + deletions: z.number(), + status: z.enum(["added", "deleted", "modified"]).optional(), + }), + ) + .optional(), + // kilocode_change end }) .optional(), share: z @@ -483,6 +494,7 @@ export namespace Session { summary_additions: input.summary?.additions, summary_deletions: input.summary?.deletions, summary_files: input.summary?.files, + summary_diffs: input.summary?.diffs ?? null, // kilocode_change time_updated: Date.now(), }) .where(eq(SessionTable.id, input.sessionID)) diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index ef9c7e2aace..46a52e49715 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -57,15 +57,27 @@ export namespace SessionRevert { if (revert) { const session = await Session.get(input.sessionID) revert.snapshot = session.revert?.snapshot ?? (await Snapshot.track()) - await Snapshot.revert(patches) - if (revert.snapshot) revert.diff = await Snapshot.diff(revert.snapshot) + + // kilocode_change start - compute diffs BEFORE reverting files so the diff + // reflects changes being undone (files on disk still have AI modifications) const rangeMessages = all.filter((msg) => msg.info.id >= revert!.messageID) const diffs = await SessionSummary.computeDiff({ messages: rangeMessages }) + await Snapshot.revert(patches) + if (revert.snapshot) revert.diff = await Snapshot.diff(revert.snapshot) + // kilocode_change end await Storage.write(["session_diff", input.sessionID], diffs) Bus.publish(Session.Event.Diff, { sessionID: input.sessionID, diff: diffs, }) + // kilocode_change start - strip full file contents before persisting to DB + const summaryDiffs = diffs.map((d) => ({ + file: d.file, + additions: d.additions, + deletions: d.deletions, + status: d.status, + })) + // kilocode_change end return Session.setRevert({ sessionID: input.sessionID, revert, @@ -73,6 +85,7 @@ export namespace SessionRevert { additions: diffs.reduce((sum, x) => sum + x.additions, 0), deletions: diffs.reduce((sum, x) => sum + x.deletions, 0), files: diffs.length, + diffs: summaryDiffs, // kilocode_change }, }) } diff --git a/packages/opencode/src/session/session.sql.ts b/packages/opencode/src/session/session.sql.ts index 0630760f3bc..ff4f05ef8ea 100644 --- a/packages/opencode/src/session/session.sql.ts +++ b/packages/opencode/src/session/session.sql.ts @@ -25,7 +25,11 @@ export const SessionTable = sqliteTable( summary_additions: integer(), summary_deletions: integer(), summary_files: integer(), - summary_diffs: text({ mode: "json" }).$type(), + // kilocode_change start - lightweight diff type (no file contents) + summary_diffs: text({ mode: "json" }).$type< + { file: string; additions: number; deletions: number; status?: "added" | "deleted" | "modified" }[] + >(), + // kilocode_change end revert: text({ mode: "json" }).$type<{ messageID: string; partID?: string; snapshot?: string; diff?: string }>(), permission: text({ mode: "json" }).$type(), ...Timestamps, diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index b22f7018043..0478e29df56 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -833,7 +833,12 @@ export type Session = { additions: number deletions: number files: number - diffs?: Array + diffs?: Array<{ + file: string + additions: number + deletions: number + status?: "added" | "deleted" | "modified" + }> } share?: { url: string @@ -1749,7 +1754,12 @@ export type GlobalSession = { additions: number deletions: number files: number - diffs?: Array + diffs?: Array<{ + file: string + additions: number + deletions: number + status?: "added" | "deleted" | "modified" + }> } share?: { url: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 7211c8fd359..c631974b276 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -5805,6 +5805,9 @@ }, "id": { "type": "string" + }, + "skipped": { + "type": "boolean" } }, "required": [ @@ -5927,6 +5930,9 @@ }, "id": { "type": "string" + }, + "skipped": { + "type": "boolean" } }, "required": [ @@ -6106,6 +6112,9 @@ }, "id": { "type": "string" + }, + "skipped": { + "type": "boolean" } }, "required": [ @@ -6368,6 +6377,9 @@ }, "id": { "type": "string" + }, + "skipped": { + "type": "boolean" } }, "required": [ @@ -12487,7 +12499,31 @@ "diffs": { "type": "array", "items": { - "$ref": "#/components/schemas/FileDiff" + "type": "object", + "properties": { + "file": { + "type": "string" + }, + "additions": { + "type": "number" + }, + "deletions": { + "type": "number" + }, + "status": { + "type": "string", + "enum": [ + "added", + "deleted", + "modified" + ] + } + }, + "required": [ + "file", + "additions", + "deletions" + ] } } }, @@ -13975,6 +14011,10 @@ "description": "@deprecated Use 'share' field instead. Share newly created sessions automatically", "type": "boolean" }, + "remote_control": { + "description": "Enable remote control of sessions via Kilo Cloud. Equivalent to running /remote on startup.", + "type": "boolean" + }, "autoupdate": { "description": "Automatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications", "anyOf": [ @@ -15061,7 +15101,31 @@ "diffs": { "type": "array", "items": { - "$ref": "#/components/schemas/FileDiff" + "type": "object", + "properties": { + "file": { + "type": "string" + }, + "additions": { + "type": "number" + }, + "deletions": { + "type": "number" + }, + "status": { + "type": "string", + "enum": [ + "added", + "deleted", + "modified" + ] + } + }, + "required": [ + "file", + "additions", + "deletions" + ] } } },