From 7ea837000ce93eff62c6c6e6ab2023c3fca27eb0 Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Fri, 13 Feb 2026 16:00:41 +0100 Subject: [PATCH 1/4] fix(opencode): improve message filtering for summary update during revert and unrevert --- packages/opencode/src/session/revert.ts | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index 7afe44e2ce37..08a52718bd19 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -58,8 +58,13 @@ export namespace SessionRevert { revert.snapshot = session.revert?.snapshot ?? (await Snapshot.track()) await Snapshot.revert(patches) if (revert.snapshot) revert.diff = await Snapshot.diff(revert.snapshot) - const rangeMessages = all.filter((msg) => msg.info.id >= revert!.messageID) - const diffs = await SessionSummary.computeDiff({ messages: rangeMessages }) + const remainingMessages = all.filter((msg) => + revert?.partID ? msg.info.id <= revert.messageID : msg.info.id < revert!.messageID, + ) + // Make sure new summary is made up of remainingMessgaes, messages with id less (<) then the reverted one + // If reverting a part, we add in the message itself + + const diffs = await SessionSummary.computeDiff({ messages: remainingMessages }) await Storage.write(["session_diff", input.sessionID], diffs) Bus.publish(Session.Event.Diff, { sessionID: input.sessionID, @@ -86,6 +91,20 @@ export namespace SessionRevert { const next = await Session.update(input.sessionID, (draft) => { draft.revert = undefined }) + const messages = await Session.messages({ sessionID: input.sessionID }) + const diffs = await SessionSummary.computeDiff({ messages }) + await Storage.write(["session_diff", input.sessionID], diffs) + Bus.publish(Session.Event.Diff, { + sessionID: input.sessionID, + diff: diffs, + }) + await Session.update(input.sessionID, (draft) => { + draft.summary = { + additions: diffs.reduce((sum, x) => sum + x.additions, 0), + deletions: diffs.reduce((sum, x) => sum + x.deletions, 0), + files: diffs.length, + } + }) return next } From 1a6db6411c59fabb8777d54222271782b32e82d9 Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Sat, 14 Feb 2026 19:22:14 +0100 Subject: [PATCH 2/4] refactor: update session summary handling in revert function with new session update method --- packages/opencode/src/session/revert.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index 10e851ab5b7a..999e598257d8 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -97,12 +97,15 @@ export namespace SessionRevert { sessionID: input.sessionID, diff: diffs, }) - await Session.update(input.sessionID, (draft) => { - draft.summary = { + + await Session.setSummary({ + sessionID: input.sessionID, + summary: { + ...session.summary, additions: diffs.reduce((sum, x) => sum + x.additions, 0), deletions: diffs.reduce((sum, x) => sum + x.deletions, 0), files: diffs.length, - } + }, }) return Session.clearRevert(input.sessionID) } From 5e0bee03baa3599301a497f7c574022f84a16e54 Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Tue, 17 Feb 2026 13:32:14 +0100 Subject: [PATCH 3/4] fix(opencode): restore baseline snapshot before stacking reverts --- packages/opencode/src/session/revert.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index 999e598257d8..ada4f82bfd57 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -56,7 +56,12 @@ export namespace SessionRevert { if (revert) { const session = await Session.get(input.sessionID) - revert.snapshot = session.revert?.snapshot ?? (await Snapshot.track()) + const snapshot = session.revert?.snapshot ?? (await Snapshot.track()) + // When stacking reverts, ensure we restore the original snapshot baseline so the + // next diff only reflects the newly reverted content, not prior revert state. + if (session.revert?.snapshot) await Snapshot.restore(session.revert.snapshot) + // Preserve the baseline snapshot for future redo/unrevert operations. + revert.snapshot = snapshot await Snapshot.revert(patches) if (revert.snapshot) revert.diff = await Snapshot.diff(revert.snapshot) const remainingMessages = all.filter((msg) => From bfcfe7f1d9f3dcb02a66ac44fdccd4d474e77549 Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Sat, 11 Apr 2026 12:58:59 +0100 Subject: [PATCH 4/4] fix(sessions): fix session summary updates for revert and unrevert --- packages/opencode/src/session/revert.ts | 18 ++++++++++++++++-- .../test/session/revert-compact.test.ts | 10 ++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/session/revert.ts b/packages/opencode/src/session/revert.ts index 416b8555de87..56482e51b678 100644 --- a/packages/opencode/src/session/revert.ts +++ b/packages/opencode/src/session/revert.ts @@ -77,8 +77,10 @@ export namespace SessionRevert { if (session.revert?.snapshot) yield* snap.restore(session.revert.snapshot) yield* snap.revert(patches) if (rev.snapshot) rev.diff = yield* snap.diff(rev.snapshot as string) - const range = all.filter((msg) => msg.info.id >= rev!.messageID) - const diffs = yield* summary.computeDiff({ messages: range }) + const remainingMsgs = all.filter((msg) => + rev?.partID ? msg.info.id <= rev.messageID : msg.info.id < rev!.messageID, + ) + const diffs = yield* summary.computeDiff({ messages: remainingMsgs }) yield* storage.write(["session_diff", input.sessionID], diffs).pipe(Effect.ignore) yield* bus.publish(Session.Event.Diff, { sessionID: input.sessionID, diff: diffs }) yield* sessions.setRevert({ @@ -99,6 +101,18 @@ export namespace SessionRevert { const session = yield* sessions.get(input.sessionID) if (!session.revert) return session if (session.revert.snapshot) yield* snap.restore(session.revert!.snapshot!) + const messages = yield* sessions.messages({ sessionID: input.sessionID }) + const diffs = yield* summary.computeDiff({ messages }) + yield* storage.write(["session_diff", input.sessionID], diffs).pipe(Effect.ignore) + yield* bus.publish(Session.Event.Diff, { sessionID: input.sessionID, diff: diffs }) + yield* sessions.setSummary({ + sessionID: input.sessionID, + summary: { + additions: diffs.reduce((sum, x) => sum + x.additions, 0), + deletions: diffs.reduce((sum, x) => sum + x.deletions, 0), + files: diffs.length, + }, + }) yield* sessions.clearRevert(input.sessionID) return yield* sessions.get(input.sessionID) }) diff --git a/packages/opencode/test/session/revert-compact.test.ts b/packages/opencode/test/session/revert-compact.test.ts index 95d90325ad36..285bfa593b7f 100644 --- a/packages/opencode/test/session/revert-compact.test.ts +++ b/packages/opencode/test/session/revert-compact.test.ts @@ -6,6 +6,7 @@ import { ModelID, ProviderID } from "../../src/provider/schema" import { SessionRevert } from "../../src/session/revert" import { SessionCompaction } from "../../src/session/compaction" import { MessageV2 } from "../../src/session/message-v2" +import { SessionSummary } from "../../src/session/summary" import { Snapshot } from "../../src/snapshot" import { Log } from "../../src/util/log" import { Instance } from "../../src/project/instance" @@ -497,12 +498,15 @@ describe("revert + compact workflow", () => { const first = await turn("a.txt", "a1") const second = await turn("b.txt", "b2") const third = await turn("c.txt", "c3") + const files = async () => (await SessionSummary.diff({ sessionID: sid })).map((item) => item.file).sort() await SessionRevert.revert({ sessionID: sid, messageID: first, }) expect((await Session.get(sid)).revert?.messageID).toBe(first) + expect((await Session.get(sid)).summary?.files).toBe(0) + expect(await files()).toEqual([]) expect(await fs.readFile(path.join(tmp.path, "a.txt"), "utf-8")).toBe("a0") expect(await fs.readFile(path.join(tmp.path, "b.txt"), "utf-8")).toBe("b0") expect(await fs.readFile(path.join(tmp.path, "c.txt"), "utf-8")).toBe("c0") @@ -512,6 +516,8 @@ describe("revert + compact workflow", () => { messageID: second, }) expect((await Session.get(sid)).revert?.messageID).toBe(second) + expect((await Session.get(sid)).summary?.files).toBe(1) + expect(await files()).toEqual(["a.txt"]) expect(await fs.readFile(path.join(tmp.path, "a.txt"), "utf-8")).toBe("a1") expect(await fs.readFile(path.join(tmp.path, "b.txt"), "utf-8")).toBe("b0") expect(await fs.readFile(path.join(tmp.path, "c.txt"), "utf-8")).toBe("c0") @@ -521,6 +527,8 @@ describe("revert + compact workflow", () => { messageID: third, }) expect((await Session.get(sid)).revert?.messageID).toBe(third) + expect((await Session.get(sid)).summary?.files).toBe(2) + expect(await files()).toEqual(["a.txt", "b.txt"]) expect(await fs.readFile(path.join(tmp.path, "a.txt"), "utf-8")).toBe("a1") expect(await fs.readFile(path.join(tmp.path, "b.txt"), "utf-8")).toBe("b2") expect(await fs.readFile(path.join(tmp.path, "c.txt"), "utf-8")).toBe("c0") @@ -529,6 +537,8 @@ describe("revert + compact workflow", () => { sessionID: sid, }) expect((await Session.get(sid)).revert).toBeUndefined() + expect((await Session.get(sid)).summary?.files).toBe(3) + expect(await files()).toEqual(["a.txt", "b.txt", "c.txt"]) expect(await fs.readFile(path.join(tmp.path, "a.txt"), "utf-8")).toBe("a1") expect(await fs.readFile(path.join(tmp.path, "b.txt"), "utf-8")).toBe("b2") expect(await fs.readFile(path.join(tmp.path, "c.txt"), "utf-8")).toBe("c3")