feat(desktop): sessions REST + transcript hydration + clawcodex desktop launcher (stage 3) - #804
Merged
Merged
Conversation
…op launcher (stage 3)
The sidebar lists real sessions, reopening a chat restores it, and the app
has a first-class launcher — verified live end-to-end: the packaged shell
booted this backend, created a session, and round-tripped a real model reply
rendered in the chat (sidebar row, branch chip, error paths all live).
Server:
- src/server/desktop_sessions.py: pure readers over the saved transcripts
(<config>/sessions/*.json — transport-independent, TUI + desktop share one
list): newest-first rows with pagination/min_messages, corrupt files
skipped, strict id charset (no traversal); transcript hydration with
<system-reminder> user rows marked hidden.
- Routes (token-gated): /api/sessions (+is_active for live gateway
sessions), /api/sessions/{id}/messages, /api/model/info,
/api/profiles (+/active — single default profile),
/api/profiles/sessions (source/exclude_sources filters),
/api/profiles/sessions/sidebar (batched slices; cron/messaging empty),
/api/config/defaults (redacted). A logging catch-all 404 names every
route the shell asks for that isn't built yet — found the exact five the
boot needed (an uncaught rejection on /api/profiles/sessions was breaking
the session list).
- session.resume hydrates messages from the stored transcript
(omit_messages/lazy honored); sessions.changed pushed after every turn;
gateway.ready advertises change_events so the renderer demotes polling.
- GUI<->backend contract ladder restarts at v1: serve reports
desktop_contract=1 in session info; the renderer's
REQUIRED_BACKEND_CONTRACT drops 5 -> 1 (reference v2-v5 capabilities
re-bump as they land) — removes the false backend-out-of-date banner.
CLI:
- clawcodex desktop (src/entrypoints/desktop_cli.py + sieve entry): dev
launcher — resolves the checkout, npm ci when deps are missing
(--install to force), npm run dev (--no-dev for build+start), and pins
the app's backend to this checkout via env.
Verification: 33 desktop server tests (listing/pagination/filtering,
hydration + reminder hiding, traversal refusal, profiles/defaults shapes,
resume-through-gateway, launcher plan logic); server+entrypoints suites 547
passed; ui-desktop typecheck green + electron vitest 78 files green; live
app drive with a real streamed reply.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agentforce314
enabled auto-merge (squash)
August 8, 2026 07:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stage 3 of the Desktop port — and the stage where the app went live end-to-end: the shell booted this backend, created a session, and round-tripped a real model reply rendered in the chat (sidebar row, branch/diff chip, and error paths all working).
Server
src/server/desktop_sessions.py— pure readers over the saved transcripts (<config>/sessions/*.json; transport-independent, TUI + desktop share one list): newest-first rows with pagination/min_messages, corrupt-file skip, strict id charset (no traversal); transcript hydration with<system-reminder>rows marked hidden./api/sessions(+is_activefor live gateway sessions),/api/sessions/{id}/messages,/api/model/info,/api/profiles(+/active),/api/profiles/sessions(source filters),/api/profiles/sessions/sidebar(batched slices),/api/config/defaults(redacted). A logging catch-all 404 names every route the shell asks for that isn't built yet — it found the exact five the boot needed (an uncaught rejection on/api/profiles/sessions404 was breaking the session list).session.resumehydrates messages from the stored transcript (omit_messages/lazyhonored);sessions.changedpushed after every turn;gateway.readyadvertiseschange_events.desktop_contract: 1; rendererREQUIRED_BACKEND_CONTRACT5 → 1 (reference v2–v5 capabilities re-bump as they land) — removes the false backend-out-of-date banner.CLI
clawcodex desktop— dev launcher: resolves the checkout,npm ciwhen deps missing (--installto force),npm run dev(--no-devfor build+start), backend pinned to the checkout.Verification
🤖 Generated with Claude Code