fix: persist session renames through state.db sync#865
Conversation
Renames previously updated the local sessions.json cache first and swallowed state.db errors, so the UI looked successful until the next syncSessionCache restored the old Hermes title. Write the durable DB row first (honoring unique titles and the 100-char cap), only then mirror into the cache, and toast/rollback when the write fails. Co-authored-by: Cursor <cursoragent@cursor.com>
Pull title policy into src/shared/session-title and the optimistic rename UX into confirmSessionRename so the sidebar and Sessions modal stop duplicating toast/rollback/refocus logic. Keeps both screens under the 1k-line ceiling and prevents UI/DB whitespace drift on rename. Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile SummaryThis PR makes session renames durable and shares the rename flow across both session lists. The main changes are:
Confidence Score: 4/5Cache-write failures and overlapping modal renames can leave the displayed title out of sync with durable state.
src/main/session-cache.ts and src/renderer/src/screens/Sessions/Sessions.tsx Important Files Changed
|
| if (idx >= 0) { | ||
| cache.sessions[idx].title = title; | ||
| cache.sessions[idx].title = normalized; | ||
| writeCache(cache); |
There was a problem hiding this comment.
Cache Mirror Failure Is Hidden
The database has already committed when writeCache runs, but that function suppresses every write error. If disk access fails, this call still reports success while sessions.json keeps the old title; later incremental syncs do not repair established sessions because they select by unchanged started_at and refresh only message counts in the stale-entry pass.
| const oldSessionTitle = | ||
| sessions.find((s) => s.id === sessionId)?.title ?? ""; | ||
| const oldSearchResultTitle = | ||
| searchResults.find((r) => r.sessionId === sessionId)?.title ?? ""; |
There was a problem hiding this comment.
Older Rollback Overwrites Newer Rename
Two submissions for the same session can overlap while persistence is pending. If rename B succeeds before rename A fails, A's snapshot rollback runs last and restores the original title over B's optimistic title, leaving the modal inconsistent with the title persisted by B until another refresh.
Summary
state.dbbefore updating the localsessions.jsoncache, sosyncSessionCachecannot resurrect the old titleTest plan
npm test -- tests/session-cache-sync.test.ts src/shared/session-title.test.tsnpm run typecheckMade with Cursor