fix: restore messages after redo

Refetches session messages before applying redo
Aligns undo/redo navigation with OpenCode behavior
Keeps restored messages visible after unrevert
This commit is contained in:
Bohdan Triapitsyn
2026-05-08 14:53:48 +03:00
parent d659929685
commit c827d6b8df
7 changed files with 44 additions and 17 deletions
+1 -1
View File
@@ -39,7 +39,7 @@
"@fontsource/ibm-plex-sans": "^5.1.1",
"@ibm/plex": "^6.4.1",
"@lezer/highlight": "^1.2.3",
"@opencode-ai/sdk": "^1.4.39",
"@opencode-ai/sdk": "^1.4.41",
"@pierre/diffs": "1.1.0-beta.13",
"@base-ui/react": "^1.4.0",
"@remixicon/react": "^4.7.0",
+26
View File
@@ -13,6 +13,11 @@ import { useGlobalSessionsStore } from "@/stores/useGlobalSessionsStore"
import { useConfigStore } from "@/stores/useConfigStore"
import { registerSessionDirectory } from "./sync-refs"
import { isSyntheticPart } from "@/lib/messages/synthetic"
import { materializeSessionSnapshots } from "./materialization"
import { stripMessageDiffSnapshots } from "./sanitize"
const MESSAGE_REFETCH_LIMIT = 200
const MESSAGE_REFETCH_SKIP_PARTS = new Set(["patch", "step-start", "step-finish"])
// Reference set by SyncProvider — allows actions to access SDK and stores
let _sdk: OpencodeClient | null = null
@@ -647,6 +652,26 @@ export async function revertToMessage(sessionId: string, messageId: string): Pro
}
}
export async function refetchSessionMessages(sessionId: string): Promise<void> {
const store = dirStore()
const result = await sdk().session.messages({ sessionID: sessionId, directory: dir(), limit: MESSAGE_REFETCH_LIMIT })
const records = (result.data ?? []).filter((record: { info?: { id?: string } }) => !!record?.info?.id)
if (records.length === 0) return
store.setState((state) => {
const materialized = materializeSessionSnapshots(
state,
sessionId,
records.map((record: { info: Message; parts?: Part[] }) => ({
info: stripMessageDiffSnapshots(record.info),
parts: record.parts ?? [],
})),
{ skipPartTypes: MESSAGE_REFETCH_SKIP_PARTS },
)
return { message: materialized.message, part: materialized.part }
})
}
/**
* Unrevert — restore all previously reverted messages.
* Restore all previously reverted messages. Aborts if busy, merges result.
@@ -675,6 +700,7 @@ export async function unrevertSession(sessionId: string): Promise<void> {
store.setState({ session: sessions })
}
}
await refetchSessionMessages(sessionId)
}
/**
+5 -4
View File
@@ -46,6 +46,7 @@ import {
shareSession as shareSessionAction,
unshareSession as unshareSessionAction,
optimisticSend,
refetchSessionMessages,
} from "./session-actions"
import { useInputStore, type SyntheticContextPart } from "./input-store"
import { useSelectionStore } from "./selection-store"
@@ -967,8 +968,7 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
const revertToId = currentSession?.revert?.messageID
let targetMessage: typeof messages[number] | undefined
if (revertToId) {
const revertIndex = userMessages.findIndex((m) => m.id === revertToId)
targetMessage = userMessages[revertIndex + 1]
targetMessage = [...userMessages].reverse().find((m) => m.id < revertToId)
} else {
targetMessage = userMessages[userMessages.length - 1]
}
@@ -996,10 +996,11 @@ export const useSessionUIStore = create<SessionUIState>()((set, get) => ({
const revertToId = currentSession?.revert?.messageID
if (!revertToId) return
await refetchSessionMessages(sessionId)
const messages = getSyncMessages(sessionId)
const userMessages = messages.filter((m) => m.role === "user")
const revertIndex = userMessages.findIndex((m) => m.id === revertToId)
const targetMessage = userMessages[revertIndex - 1]
const targetMessage = userMessages.find((m) => m.id > revertToId)
if (targetMessage) {
const targetParts = getSyncParts(targetMessage.id)
+1 -1
View File
@@ -243,7 +243,7 @@
},
"dependencies": {
"@openchamber/ui": "workspace:*",
"@opencode-ai/sdk": "^1.4.39",
"@opencode-ai/sdk": "^1.4.41",
"adm-zip": "^0.5.16",
"jsonc-parser": "^3.3.1",
"react": "^19.1.1",
+1 -1
View File
@@ -25,7 +25,7 @@
"dependencies": {
"@clack/prompts": "^1.1.0",
"@octokit/rest": "^22.0.1",
"@opencode-ai/sdk": "^1.4.39",
"@opencode-ai/sdk": "^1.4.41",
"@simplewebauthn/server": "13.3.0",
"adm-zip": "^0.5.16",
"better-sqlite3": "^11.7.0",