feat(app): restore and browse archived sessions#32337
Conversation
Widen the unarchive path so a null/cleared archived timestamp reactivates a session end to end: UpdatePayload accepts time.archived = null, setArchived converts null to undefined before patch/publish, the core projector coerces time_archived to null on update, and the app event-reducer increments sessionTotal exactly once per stable root id on unarchive (and decrements idempotently on archive), tracked via a new optional State.archivedRoots map. Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Add an unarchive action across the app and TUI: the layout exposes a shared unarchiveSession helper that clears the archived timestamp and navigates to the restored session, wired into the file picker and session list. Includes i18n strings for all locales and the supporting layout helpers. Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Add a global discovery dialog that lists archived sessions across all projects and restores one on selection. The cross-project list is fetched once on open and cached, with a distinct loading state, an explicit in-dialog error surface, and a single error toast per failure. Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
listByProject (the instance-scoped Session.list used by the sidebar) had no time_archived filter, so archived sessions consumed LIMIT-window slots and pushed active sessions out of the sidebar (anomalyco#24850). Add an archived?: boolean to ListInput and filter out archived sessions unless explicitly requested, mirroring the existing guard in listGlobal. Closes anomalyco#24850 Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Based on the search results, I found potential duplicate/related PRs: Related PRs:
These PRs are related to the core functionality in PR #32337 (archiving/unarchiving sessions and viewing archived sessions). The current PR appears to be a comprehensive solution that builds upon or supersedes the earlier attempts by combining UI, core session logic, and the browse/discovery functionality into one integrated feature. |
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Issue for this PR
Closes #24153, #26078, #13463, #29517. Fixes #24850.
Type of change
What does this PR do?
Archiving a session was one-way: it vanished from the sidebar with no restore path, and there was no way to find archived sessions again. This adds unarchive support and a discovery dialog, and fixes two count/visibility bugs along the way.
The restore mechanism clears the
time_archivedtimestamp.setArchivedacceptsnullto clear it; the projector writesSET time_archived = NULL(Drizzle omitsundefined, so the value is coerced tonull); and the PATCH payload schema acceptsNullOrso the clear signal survives decoding. On the client, the event reducer tracks archived root ids in a smallarchivedRootsmap sosessionTotalincrements/decrements exactly once per stable id — without it, a restored session showed an inconsistent count and disappeared from the sidebar until restart (#29517).The UI exposes a toggleable Archive/Restore action in the file picker, message timeline, and TUI session list, plus a new global dialog that lists archived sessions across all projects and restores one on selection.
Separately,
listByProject(the sidebar query) had no archived filter, so archived rows consumedLIMITslots and pushed active sessions out of view (#24850). It now excludes archived sessions by default, matching the existing guard inlistGlobal.I'm aware #15250 and #27510 touched parts of this area earlier; this PR implements the full round-trip (server clear + schema + reducer + UI + sidebar fix) as one coherent change.
How did you verify your code works?
Unit tests added/exercised:
packages/opencode:session-list-archived.test.ts(the Session.list() includes archived sessions in LIMIT window, causing unarchived sessions to disappear from sidebar #24850 regression — archived rows no longer consume the LIMIT window),httpapi-session.test.ts,global-session-list.test.tspackages/app:event-reducer.test.ts(sessionTotal idempotency),browse-archived.test.ts,layout/helpers.test.tspackages/tui:util/session.test.tsbun typecheckvia the pre-push hook.Screenshots / recordings
To be added — the discovery dialog and the restore action are the user-facing surfaces.
Checklist