Skip to content

perf: finish the Tauri/React performance & architecture epic (#81)#92

Closed
Zeus-Deus wants to merge 1 commit into
mainfrom
feature/81-epic-tauri-react-performance-architecture-improvements
Closed

perf: finish the Tauri/React performance & architecture epic (#81)#92
Zeus-Deus wants to merge 1 commit into
mainfrom
feature/81-epic-tauri-react-performance-architecture-improvements

Conversation

@Zeus-Deus

Copy link
Copy Markdown
Owner

Implements the four remaining open items of epic #81. The other five (#72, #73, #74, #76, #77) were already merged.

Closes #75, closes #78, closes #79, closes #80. Closes the tracking epic #81.

#75[perf][agent-chat] Stream chat events over per-thread Tauri Channels

  • New AgentChatChannelRegistry in commands/agent_chat.rs + attach_agent_chat_output / detach_agent_chat_output commands, mirroring the PTY output pattern (SessionRuntime.output_channel).
  • forward_event now routes every thread-scoped event — including the high-frequency content_delta token stream — only to the channels attached to that thread. No more app.emit global broadcast of every token of every thread to every webview listener.
  • Only threadless global RuntimeWarnings keep the legacy agent_chat_event bus (they have no owning pane to route to).
  • Replay semantics unchanged: DB persistence of transcript events stays as-is; late-attaching/resumed panes hydrate from agent_chat_list_messages, the channel carries live deltas.
  • use-agent-chat-events.ts rewritten to attach a Channel per pane/thread (handler kept in a ref so identity changes never force re-attach); dev mock mirrors the Channel dispatcher contract ({index, message}, sequential per-channel index — verified against the installed @tauri-apps/api source).
  • Multiple panes per thread supported; dead channels (webview reload without detach) are pruned on send failure.

#79[perf] Move blocking files.rs commands off the GTK main thread

  • list_directory, search_in_files, search_file_names, reveal_in_file_manager, read_file, write_file, save_clipboard_image_bytes, paste_clipboard_image_to_file are now async fn + tokio::task::spawn_blocking — the same uniform fix commands/git.rs already uses, with the same rationale header.
  • No caller changes needed (invoke() already returns a Promise); no State/non-Send guard held across an .await.

#78[remote] Headless daemon worktree creation: desktop parity

  • scripts.rs gains a SetupEmitter enum: the desktop passes its AppHandle (setup-overlay events unchanged), the headless daemon uses SetupEmitter::Log which writes the same payloads to stderr (captured in serve.log).
  • remote/tools/mod.rs::worktree_create now runs the full provisioning pipeline in a background thread after registering the workspace: worktree includes (.env copy from the main checkout) + project setup scripts, with CODEMUX_ROOT_PATH / CODEMUX_WORKSPACE_PATH / CODEMUX_BRANCH / CODEMUX_PORT injected and the deterministic allocate_workspace_port port. File-based config only (.codemux/config.json); no config → clean no-op.
  • Tool response now carries setup: { configured, port }.
  • Fetch-before-branch was already shared onto the headless path by [git] Fetch origin before creating a new workspace branch so it starts from the latest remote #76 (remote/git.rs::fetch_origin_branch, with tests) — verified, no change needed.

#80[feature] Optional background rollback checkpoint at agent-run start

Design note: docs/plans/agent-run-checkpoints.md.

  • Opt-in: git.agent_checkpoint_enabled (Settings → Git, default off).
  • Zero first-token latency: agent_chat_start_session fires the snapshot on the blocking pool after the session is live — including the settings-cache read, nothing on the start path awaits it.
  • Non-destructive snapshot: scratch index (GIT_INDEX_FILE) seeded from HEAD + git add -A + write-tree/commit-tree — captures modified and untracked files (the common agent-output case git stash create misses) without ever touching the user's real index or worktree. Pinned under refs/codemux/checkpoints/<thread>; commit + HEAD hashes recorded on the agent_chat_sessions row (additive checkpoint_commit/checkpoint_head columns).
  • Restore: "Restore checkpoint" action in the chat pane header (hover-reveal, visible only when a checkpoint exists) with a destructive confirm dialog. Tree-only: a pre-restore safety snapshot is pinned under refs/codemux/pre-restore/<thread> first, then git read-tree --reset -u + git clean -fd — files created after the checkpoint are removed; ignored files, commits, and branch refs are untouched.

How it was tested

  • cargo check + cargo test: 1696 lib tests; agent_chat_commands integration suite (19) covering channel routing, cross-thread isolation, detach, 50-delta ordering, legacy-bus fallback, checkpoint DB round-trip, and a full checkpoint→mangle→restore loop against a real temp repo; codemux_remote_serve_mcp (11) including a new live-daemon test (http_worktree_create_runs_setup_scripts) that spawns a real codemux-remote serve, calls worktree_create over authed HTTP, and asserts the setup marker + injected env + .env copy on disk.
  • npm run check (tsc) + npm run test: 1826/1826 passing.
  • Browser e2e against the real UI under the dev mock runtime: 40-token live stream rendered in order through the per-thread Channel; a fake content_delta injected on the legacy global event bus does not render (bus is dead for thread events); restore-checkpoint dialog → confirm → success toast; Settings → Git toggle renders and flips.
  • Containerized clean-host e2e: new scripts/e2e/daemon-worktree-setup-e2e.sh runs the daemon in a Docker container (no dev environment), drives the authed HTTP tool surface, and asserts on the container filesystem that the worktree was provisioned (setup script ran with CODEMUX_BRANCH/CODEMUX_PORT, gitignored .env copied) — passing.

Known pre-existing, unrelated: commands::mcp::tests::project_codemux_entry_is_filtered_out fails on machines whose real ~/.claude.json contains a codemux MCP entry (passes with a clean $HOME).

Docs updated: docs/core/STATUS.md, docs/features/agent-chat.md (event bridge rewrite + checkpoints section), docs/features/setup-teardown.md (daemon parity), docs/INDEX.md, new docs/plans/agent-run-checkpoints.md.

Four remaining items from the epic, each implemented and tested e2e:

- perf(agent-chat): stream chat events over per-thread Tauri Channels
  instead of the global event bus (#75). forward_event routes
  thread-scoped events (incl. the content_delta token stream) to
  channels registered via attach/detach_agent_chat_output in a new
  AgentChatChannelRegistry, mirroring the PTY output path; only
  threadless RuntimeWarnings keep the legacy agent_chat_event bus.
  Frontend hook attaches a Channel per pane/thread; the dev mock
  mirrors the channel contract. Tests cover routing, cross-thread
  isolation, detach, delta ordering, and the legacy fallback.

- perf(files): move blocking files.rs commands off the GTK main
  thread (#79). list_directory, search_in_files, search_file_names,
  reveal_in_file_manager, read_file, write_file and both
  clipboard-image commands are now async + spawn_blocking, same fix
  class as commands/git.rs.

- remote(worktree): headless daemon worktree creation reaches desktop
  parity (#78). worktree_create on codemux-remote now runs worktree
  includes (.env copy) + project setup scripts in the background with
  the same CODEMUX_* env and deterministic per-workspace port the
  desktop injects. scripts.rs gains a SetupEmitter enum (desktop emits
  Tauri events; the daemon logs to stderr/serve.log). The tool
  response carries setup { configured, port }. Fetch-before-branch was
  already shared from #76. Covered by a live-daemon integration test
  plus a containerized clean-host e2e harness
  (scripts/e2e/daemon-worktree-setup-e2e.sh).

- feat(agent-chat): opt-in background rollback checkpoint at run
  start (#80). With git.agent_checkpoint_enabled on (Settings -> Git,
  default off), agent_chat_start_session fires a background
  scratch-index snapshot (captures modified AND untracked files,
  never touches the user's index/worktree, pinned under
  refs/codemux/checkpoints/<thread>, recorded on the
  agent_chat_sessions row) with zero latency added to the first
  token. The chat pane header gains a Restore checkpoint action:
  tree-only restore that never moves refs, preceded by a pinned
  pre-restore safety snapshot. Design note in
  docs/plans/agent-run-checkpoints.md.

Verified: cargo check, cargo test (lib + agent_chat_commands +
codemux_remote_serve_mcp), tsc, vitest (1826 passing), browser e2e of
channel streaming/isolation + restore flow + settings toggle against
the dev mock runtime, and the Docker clean-host daemon e2e.
@Zeus-Deus

Copy link
Copy Markdown
Owner Author

Superseded: parallel branches merged independent implementations of all four issues while this PR was in flight — #88 (#75 per-thread Channels), #89 (#79 async files.rs), #90 (#78 daemon provisioning parity), #91 (#80 run-start checkpoints) — with near-identical designs and equivalent test coverage, so this branch is now fully conflicting duplicate work. The one unique artifact here (the Docker clean-host e2e harness for daemon worktree provisioning) is being re-verified against main's daemon and resubmitted as a small standalone PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment