Repository navigation
feat(devkitd): migrate interactive agent start to the daemon - #406
Merged
Merged
Conversation
Add agent.start RPC so devkitd owns spawning and registration for tmux and herdr runtimes while daemon.db becomes the registry source of truth. The CLI routes through the daemon when reachable and falls back to the existing TS path on connect-failure or older devkitd. - proto: Response gains code/details; AgentStartParams/Result exported - store: agents table gains registry columns + unique-name partial index; registered-before-swept adoption, pid-reuse invalidation, named tombstones; legacy agents.db import + dual-write bridge - devkit-harness: StartProfile + MatchSpec port of the TS matchers - devkitd: TmuxRuntime (session mgmt + 5-stable-poll pid resolution), HerdrRuntime (busy retry, process-info poll), start_mutex-serialized agent_start handler, agent.started event, registry overlay in sweeps - daemon-client: DaemonRpcError, startAgent() with start-scoped timeout - cli: daemon-first start.command with identical error rendering
- runtime/testkit.rs: single shared FixtureDir + fake tmux/pgrep/ps/herdr scripts, replacing three near-identical copies (~170 lines) - Remove speculative AgentRuntime::provider() and unused Store::live_name - agent_start maps StartError via Display instead of duplicating message text; HerdrCall::detail() folds the availability error mapping - Fold agent_start::run wrapper into the dispatch arm
…namespace - devkit-core/store.rs -> store.rs + store/registry.rs: snapshot/events stay in the parent; registration lifecycle (register_start, lookup_name, unregister, prune_dead, registry_overlays) and the legacy agents.db bridge move to the child module - devkitd/agent_start.rs -> rpc/agent/start.rs; shared agent-op helpers (name validation/generation, pid_alive) live in rpc/agent/mod.rs and StartRpcError becomes RpcError in rpc/mod.rs for the next agent.* ops - Runtimes moves to runtime/mod.rs beside the impls it bundles - Per-test legacy db filenames fix a shared-fixture parallel-test race No wire, schema, API, or behavior changes.
…eading
- Availability {ok, reason?, detail?} allowed ok=true+reason=Some invalid
states; Ok/Missing(detail)/Unreachable(detail) removes them and keeps
the wire reason strings in one place
- import_legacy_agents -> read_legacy_rows + attach-or-tombstone loop:
the query is now a named step separate from the merge
- Daemon::parse_params<T> collapses the serde param-validation block each dispatch arm repeats; agent.start uses it, future agent.* ops get coded invalid_params for free (Err is Box<Response> per clippy) - devkitd gains serde workspace dep for the DeserializeOwned bound - implementation doc updated for the rpc/ + store/registry.rs layout
…IT_BIN - ensureDaemon/resolveDaemonBinary accept an onDebug callback; the CLI feeds it the ai-devkit:agent:start logger so --debug shows socket connect, autostart spawn, lock contention, timeouts, and which routing path was taken (daemon / fallback / coded error / transport failure) - NO_AI_DEVKIT_BIN forces "no binary found" so the fallback path is exercisable end-to-end without uninstalling devkitd; takes precedence over DEVKITD_BIN so the test knob can't be overridden accidentally - daemon-client stays zero-dependency: debug lines flow through the caller's logger rather than a direct debug dep
- runtime::spawn_output retries os error 26 (text file busy): exec of a just-written executable fails transiently on Linux/overlayfs (CI test fixture scripts) and when a binary is being atomically replaced - the 4 daemon-debug files were prettier-formatted; the repo checks with oxfmt — reformatted to match CI
This was referenced Oct 23, 2026
…ost-refactor paths
rpc/mod.rs -> rpc.rs, rpc/agent/mod.rs -> rpc/agent.rs, runtime/mod.rs -> runtime.rs — matches store.rs + store/registry.rs
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
Migrates interactive
agent startfrom the TypeScript agent-manager into the Rustdevkitddaemon over the Unix-socket RPC interface.daemon.db's existingagentstable becomes the registry source of truth (observed process state + registration metadata merged, no second registry table). Bothtmuxandherdrruntimes supported; durable mode unchanged.Rust
proto.rs—Response.code/details(backwards-compatible),AgentStartParams/AgentStartResult, ts-rs exportsstore.rs+store/registry.rs— registry columns onagents+ partial unique index on live names; three snapshot rules (register-before-sweep adoption, pid-reuse full delete,gone_attombstones); legacyagents.dbboot-import + dual-write bridge for unmigrated consumers (kill/send/rename/open)devkit-harness/start_profiles.rs—MatchSpecport of all 11HARNESS_RUNTIME_PROFILESmatchersdevkitd/runtime/—TmuxRuntime+HerdrRuntimewith sharedAvailabilityenum, arg order and runtimeRef shape identical to TS clientsdevkitd/rpc/—agent.startserialized understart_mutex, coded errors,agent.startedevent, registry overlay inagent.list, post-start sweep;parse_paramshelper for futureagent.*opsTS
DaemonClient.startAgent()+DaemonRpcError{code,details}; autostart handles spawn-lock/readiness/log-rotationstart.command.ts— daemon-first routing; falls back to the existing TS path only on unreachable daemon orunknown method(pre-agent.start devkitd)--debugnow traces routing decisions end-to-end (ai-devkit:agent:startnamespace);NO_AI_DEVKIT_BINenvvar forces the binary-missing fallback for testingTest plan
cargo test --workspace— 133 tests (30 devkit-core, 80 devkit-harness, 23 devkitd)cargo clippy --workspace --all-targets -- -D warningsclean;cargo fmt --checkcleancliagent tests — 106;daemon-client— 16 (incl. real-socket integration)claude— start → register →agent.listoverlay →agent.startedevent → kill → tombstone +disappearednpx ai-devkit lint --feature devkitd-agent-start— 12/12Known deltas (documented in implementation doc)
agent.started+agent.appearedboth fire — expected double-announceagents.dbbridge remains untilkill/send/rename/open/pinRPCs land