Skip to content

refactor(startup): share the daemon boot between the desktop app and codeg-server - #1100

Open
Tinghecui wants to merge 1 commit into
spacering-net:mainfrom
Tinghecui:refactor/shared-daemon-boot
Open

Tinghecui wants to merge 1 commit into
spacering-net:mainfrom
Tinghecui:refactor/shared-daemon-boot

Conversation

@Tinghecui

Copy link
Copy Markdown

What

The desktop app's Tauri setup hook (src-tauri/src/lib.rs) and src-tauri/src/bin/codeg_server.rs each start the same daemon with their own copy of the steps, kept in step by hand through mirrors lib.rs setup / mirrored in bin/codeg_server.rs comments. That is easy to get out of sync: a new background service has to be added in two places, in the right order relative to the delegation broker and the persisted settings, in two different styles (Tauri managed state vs. AppState fields).

This PR moves the shared steps into a new src-tauri/src/boot.rs and has both hosts call it. Pure refactor, no HTTP/WS API change.

boot API

Called in this order by both hosts (the module doc lists it too):

  1. spawn_startup_housekeeping(conn, data_dir, emitter): periodic scratch-dir sweep, bundled expert and science skills, orphaned chat-dir GC, worktree-folder alias backfill.
  2. DelegationStack::build(cm, conn, data_dir): the broker, token registry, socket path and the per-tool runtime configs as named fields (the 9-tuple from app_state::build_delegation_stack).
  3. apply_persisted_settings(conn, cm, &stack).await: terminal settings, the delegation / feedback / question / session-info / chat-authoring / browser-tools / computer-tools switches, the generative-UI skill.
  4. (host) its computer-use service, if any.
  5. start_delegation_service(&Daemon, browser, computer): the host passes its BrowserToolAccess / ComputerToolAccess (native tabs and the screen on desktop; NoBrowserTabs and the optional CODEG_COMPUTER_USE service on the server).
  6. start_chat_channels(&Daemon): install_chat_channel + start_background; returns a 'static future, which the desktop spawns and the server awaits before binding (as before).
  7. spawn_daemon_services(&Daemon) -> DaemonServices: LifecycleSubscriber, pet state mapper, ACP idle sweep, office-watch sweep, automation engine, work-task engine + forge auto-processing, config-sync uploader, Codex model list refresher. DaemonServices::stop() releases the office-watch previews at exit (what both hosts called directly before).

Daemon<'a> is a borrowed view of what both hosts own (DB connection, data dir, ConnectionManager, ChatChannelManager, broadcaster, event bus, EventEmitter, pet state, the delegation stack). Nothing in boot depends on Tauri.

What only one host has stays where it was:

  • desktop: the binary-cache startup sweep thread, tray, close behavior, pet panel aggregator, codeg-cli service with the desktop opener, embedded web server auto-start, deep links, window restore, mark_served;
  • server: token, proxy-JWT, CODEG_COMPUTER_USE, upload staging purge, listener, port bridge, codeg-cli service/access.

Order changes

All of these only move where a background task is spawned; none of the moved tasks waits on the others.

  • Desktop: the delegation and tool switches are now applied together with the terminal settings, before the chat-channel dispatcher starts (previously the dispatcher was spawned before the delegation stack was even built, so a chat-channel message arriving in the first moments could launch an agent with default switches). Chat channels, the pet state mapper, config sync, the Codex refresher and the worktree alias backfill are spawned after the delegation listener instead of before it. The idle/office sweeps and the automation / work-task engines are spawned before the codeg-cli service and the embedded web server auto-start instead of after.
  • Server: the orphaned chat-dir GC is spawned after AppState is built instead of before; the skill installs before the delegation listener instead of after; terminal settings are applied before the tool switches instead of after; cli_runs.spawn_background() runs after the work-task engine instead of between it and the automation engine.

Testing

  • Fork CI (the unchanged Test workflow, all 9 Rust cells on Linux / macOS / Windows plus the frontend job): https://github.com/Tinghecui/codeg/actions/runs/42279754798
  • The same extraction was first made on a downstream fork, where its desktop, server and cli test + clippy cells are green.
  • Not run by hand on a desktop yet beyond what the test suites cover.

🤖 Generated with Claude Code

…codeg-server

The desktop app's Tauri `setup` hook and `bin/codeg_server.rs` each carried
their own copy of the daemon's startup — the bundled skill installs, the
chat-dir GC, the delegation broker and its tool configs, the persisted
settings, the delegation listener, the chat channels, the LifecycleSubscriber,
the pet state mapper, the idle and office-watch sweeps, the automation and
work-task engines, config sync, the Codex model list refresher — kept in step
by "mirrors lib.rs setup" comments.

Move those steps into `src-tauri/src/boot.rs`, which both hosts call in the
same order. `boot` does not depend on Tauri: events go out through
`EventEmitter`, and the native pieces (browser tabs, computer use) are handed
in by the host. What only one host has stays where it was: the tray, windows,
deep links, close behavior, pet panel, embedded web server and binary-cache
startup sweep on the desktop; the listener, token, proxy-JWT, computer-use
opt-in and upload staging purge in the server.

No HTTP/WS API change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant