Repository navigation
Share Maple Agent desktop and ACP through one local host - #1161
Conversation
6efde87 to
108e6ec
Compare
Review at e580912 against the code-docs #88 planOverall. The shape is right and it is the base Phase 2 should build on: one host per profile behind an OS file lock and a handshake, the desktop reduced to an IPC client, ACP as a projection that never owns the runtime (pipe EOF detaches, How it was checked. Read the #88 package and the whole diff; built this head and ran the ACP harness plus a new reproduction test; ran lifecycle probes of the debug binary on an isolated profile with no sign-in (startup election, profile mismatch, explicit stop, idle exit, shutdown window). CI is green on all three platforms. Not run: signed-in flows (the lag chain, permission attribution) and native Windows/Linux. Paths are under Fix before merge
Before Phase 2
Smaller items
Plan and docs (code-docs #88)
Review by Claude Code, folding in a second reviewer's pass; posted from Anthony's account. 🤖 Generated with Claude Code |
Desktop and
maple-agent acpnow attach to one on-demand local host. Starting ACP first creates the same owner that desktop later joins, so both interfaces can resume a task, observe its stream, answer questions and cancel its run without competing runtimes or store writers. The existing backend moves tobackend/local.rs; the desktop facade becomes an IPC client. Pi is unchanged.The host owns account state, task persistence, tools and children. OS-private sockets/named pipes, startup locks and a profile/version handshake define its boundary. Closing one client detaches it; the last intentional desktop Quit or ACP detach triggers graceful shutdown. An unexpected desktop connection loss allows 30 seconds for recovery; desktop reconnects for up to 15 seconds and reloads history, running tasks, queues and questions before accepting another send. Account validation can run alongside local operations; actual account switches remain exclusive. Sign-out revokes ACP connections and old account handles. Snapshot revisions reconcile live partials, and durable send receipts let desktop resolve a lost admission reply without replaying inference.
ACP remains a standards-based projection. It supports the shared Codex/Claude
_session/steeringextension, reasoning controls and negotiated form questions. Client MCP bindings are transient and disabled on detach. CUA, external agents and host filesystem tools use the shared execution owner. Optional ACPsession/closeis omitted because its cancellation semantics differ from pipe EOF/detach.This is local Phase 1 only: no remote transport, pairing, background-service installation or Pi changes.
Validation
macOS ARM64, fresh managed Local environment with local OpenSecret and billing, Pro fixture and live Continuum inference. Hosted Dev flags fallback was present; this does not prove local flags entitlement behavior.
nix develop --no-update-lock-file -c just ci: passed. Includes 267 Maple runtime tests (2 ignored), 458 desktop tests, 67 headless app tests, the remaining workspace tests and all four lint configurations.Native simultaneous ACP startup elected one host; incompatible profile/build rejected; last-client exit and explicit host stop exited cleanly.
Live desktop/ACP task sharing in both directions, mid-turn join, text/tool streaming, reasoning selection, steering, form questions, cancellation and originating-client detach passed.
Lost-reply send admission reconciled without a second run. Sign-out closed a retained native ACP process; old-account requests and silent account replacement were rejected; Free/Pro task isolation passed.
Native CUA window enumeration passed from an ACP-created task under the workspace's ad-hoc debug bundle. Desktop sent a Flash turn with
bash, rendered its generated tool summary and the task reloaded over ACP.Exercised the generic ACP provider source (
b2ca7dcf, 2026-10-15): create, model selection, streamed tool use, close and resume/history passed. Also tested installed Paseo 0.11.1 with the native Maple desktop: a long first reply, a desktop continuation delivered live to Paseo, and another prompt on the same Paseo connection all passed. Manual testing confirmed simultaneous streaming and repeated continuation from both interfaces.Regression coverage streams beyond the runtime broadcast capacity while titles change, then continues from desktop and ACP. Metadata updates drain independently of the whole-turn history gate.
Root
nix flake check --no-update-lock-filepassed. A native disposable-DMG check reproduced the old cleanup failure and verified bounded detach retries, including preserving the mounted fixture when it remained busy.Added regressions for standalone external-agent updates during an ACP turn, incompatible-host stop/startup handling, shutdown ownership waiting, signed-out ACP diagnostics, nonblocking credential restoration, connection loss/overflow, queued commands crossing a disconnect, lost send receipts, account changes, snapshot/event reconciliation, explicit stop and multi-client shutdown. Frontend runtime teardown is safe when its last reference is released by an async callback.
Live Local Pro recovery smoke: an active Bash tool survived loss of its only client and a three-second gap; the same host recovered the active run and completed response, with exactly one user message. Explicit stop drained the isolated host.
Native macOS GUI opened/rendered successfully with the new cleanup path. The package probe now explicitly stops its own isolated host before unmounting; all 11 probe regressions passed.
Review boundaries
Windows named pipes and Linux IPC are implemented but were not executed natively here. External agents have automated fixture coverage; authenticated Codex/Claude runs were not repeated. This is a local debug build, not production packaging validation.
Paseo's generic provider does not yet call
_session/steeringand rejects a second active turn itself. Desktop-originated user and assistant messages stream to an already attached idle Paseo client. Stable ACP v1 does not provide a separate running/idle lifecycle for turns started elsewhere, so transcript delivery does not establish full desktop status parity. A disconnected/slow desktop automatically reconnects within the bounded recovery window; failed recovery asks the user to reopen. Recovery does not spawn a replacement host or replay commands. Remote keepalive remains outside this phase. Host crashes recover stored history without automatic inference replay or a promise that tools survive. Details are inapps/maple-agent/docs/local-host.md.Need help on this PR? Tag
@codesmith-botwith what you need.