Expand description
Daemon front-end (synaps daemon): UDS listener, per-connection pump,
registry file, lifecycle (PLAN-phase2 §2.11). Lives in agent-engine
(S289 D-1 amended) — agent-tui must never appear in this graph.
On by default: the first --attach/attach client auto-spawns the
daemon (ensure_running); SYNAPS_DAEMON=0 disables every daemon
feature (exit 3 with a one-line reason). Safety properties that are
NEVER stubbed: the flock liveness oracle, the ready-fd pipe, socket
perms 0700/0600, the spawn lock (one spawner per registry dir).
Modules§
- conn
- Per-connection pump: handshake → control loop → attach → pump.
- lifecycle
- Daemon shutdown: end every session concurrently inside ONE wall budget, then shut the shared extension host down.
- listener
- UDS listener: bind with 0600, accept until shutdown, one task per connection.
- registry
daemon.json/daemon.lock/daemon.pidunderregistry_dir()(PLAN-phase2 §2.11). The flock ondaemon.lockis THE liveness oracle (jcodesocket.rs:89-139): a daemon is alive iff someone holds the lock. A socket file with no lock holder is stale and gets unlinked. Nobody unlinks on ECONNREFUSED alone.- reload
synaps daemon reload(PLAN-phase3 §2.8, C3): version gate → drain →Checkpoint{Reload}every session → reload-state → announceReloading/Bye{Reloading}→execvself (same pid, adopted flock, CLOEXEC listener) → new image rehydrates sessions from reload-state BEFORE accepting.
Structs§
- Daemon
- A running daemon (bound socket, lock held, accept loop spawned).
- Daemon
Opts - Daemon
State - Shared by the accept loop and every connection.
Enums§
- Ensure
Error - Why
ensure_runningcould not hand back a live daemon. - Ensured
- Result of
ensure_running.
Constants§
- AUTOSPAWN_
IDLE_ EXIT - Default idle grace for auto-spawned daemons.
- DISABLED_
NOTICE - One-line reason used by every attach path when the flag is off.
- EXIT_
DAEMON_ LOST - The daemon was lost (SIGKILL / crash) and reconnection failed within the
budget (
SYNAPS_TUI_ATTACH_RECONNECT_SECS). - EXIT_
REFUSED - Exit code when the daemon refuses to start (flag off / legacy MCP).
- EXIT_
VERSION - Exit code for a protocol/version refusal on the client side.
- EXTENSION_
DISCOVERY_ WAIT - Upper bound
run_foregroundwaits for extension discovery before it starts accepting and signals ready (sidecars spawn once per daemon, and early sessions must see extension tools/hooks). - READY_
FD_ ENV - Env var carrying the write end of the ready pipe to a spawned daemon.
- SPAWN_
READY_ TIMEOUT - How long
spawn_detachedwaits for the child’s ready byte. Strictly greater than the daemon’s bounded pre-ready work: the extension wait plus a margin. MCP discovery never counts here — the daemon runs it in the background after it is accepting (crate::McpDiscovery::Background).
Functions§
- autospawn_
enabled SYNAPS_DAEMON_AUTOSPAWN: ON unless0/false/off/no. Off means an attach with no live daemon fails with the “no daemon running” message instead of starting one.- autospawn_
idle_ exit SYNAPS_DAEMON_IDLE_EXIT_SECSfor auto-spawned daemons: default 10 s — when the last client disconnects and no turn is running, the daemon is holding ~100 MB for one reason only: a re-launch inside the window skips extension boot. Ten seconds covers “oops, wrong window”;0/never→ never exit on idle.- daemon_
is_ idle - Idle = zero connections AND every live session between turns, held for
idlecontinuously. Clients count first so a probe is never sent while someone is attached. - enabled
SYNAPS_DAEMONfeature flag: ON unless set to0/false/off/no.SYNAPS_DAEMON=1is accepted (no-op, kept for older scripts).- ensure_
running - Attach-path entry: a live daemon or a freshly spawned one (jcode model —
first client spawns via
setsid+ ready-fd; the daemon holds the flock). The spawn lock (<stem>.spawn.locknext to the flock) serialises concurrent first-clients: the loser blocks on it, then re-probes the flock and finds the winner’s daemon. Enabled warm attaches also acquire this lock (extra open/flock overhead, and the lock must be writable). Never touches the socket on ECONNREFUSED alone —reap_stale+ the flock decide. Daemon startup must NOT acquire the spawn lock: its parent holds it until the child’s ready-fd acknowledgement. - host_
factory - The default factory for a booted host:
EngineHost::create_session(A1) — the realSessionActorowning oneRuntime+ConversationState. - run_
foreground synaps daemon --foregroundbody: gate → boot host (cached MCP descriptors only) → extension discovery once → start → background MCP discovery → wait for SIGTERM/SIGINT/Shutdown frame/idle.- session_
is_ idle - Whether
handle’s actor is between turns. AsksQuery{Status}under the reservedcrate::session::wire::IDLE_PROBE_QUERY_ID(transports swallow it) and readsstreaming. A no-answer inside [IDLE_PROBE_TIMEOUT] — the actor is insidecompact()/preflight, or its queue is full — counts as busy: the daemon never exits under a running turn (jcode mistake #1). - signal_
ready - Child side of the ready pipe: write
RtoSYNAPS_DAEMON_READY_FD(if set), close it, and scrub the env so tool subprocesses do not inherit it. - spawn_
detached - Parent side:
current_exe daemon --foreground …in its own session (setsid), stdout → null, stderr → pipe; waits ≤SPAWN_READY_TIMEOUT(15 s: the daemon’s ≤ 10 s extension wait plus margin) forRon the ready pipe. EOF beforeR= child died → error with its stderr tail.
Type Aliases§
- Session
Factory - Builds a session for
Attach::Create:host_factory(real actor) orecho_factory(tests).