Let Hub continue agents through the standard daemon API - #4354
Conversation
Authorize ordinary agent and workspace recovery operations with hub.execute. Keep conversation routing in Hub and persist generic creation and message receipts so retries cannot silently duplicate work.
Allow Hub to advertise provider support independently of the app version. Document the companion continuation policy and migration. Preserve newly observed files in the native watcher inventory so coalesced deletions remain visible to reconciliation, addressing the Windows CI failure.
|
| Filename | Overview |
|---|---|
| packages/server/src/server/agent/requests/index.ts | Adds the durable request journal and now clears receipts after confirmed retry-safe local creation failures; completed receipts still have no bounded retention strategy. |
| packages/server/src/server/session.ts | Integrates keyed creation and message deduplication while moving agent loading before the message receipt becomes ambiguous. |
| packages/server/src/server/authorization/operation-permissions.ts | Extends hub.execute to the ordinary agent, observation, archival, and recovery operations required by the Hub continuation workflow. |
| packages/server/src/server/file-observer/internal/native-recursive.ts | Records newly announced files immediately so subsequent reconciliation can observe coalesced deletions. |
| packages/server/src/server/file-observer/native-recursive.test.ts | Replaces banned module mocks with real filesystem behavior, but still bypasses the public module interface by importing a private internal backend. |
| packages/client/src/daemon-client.ts | Adds keyed creation support and rejects it when the connected daemon does not advertise durable receipt support. |
| docs/hub.md | Documents daemon-wide Hub agent authority, durable operation identities, unknown outcomes, and workspace recovery. |
Sequence Diagram
sequenceDiagram
participant Hub
participant Session
participant Receipts as AgentRequests
participant Agent as AgentManager/Provider
participant Disk as Receipt Storage
Hub->>Session: create_agent_request(idempotencyKey)
Session->>Receipts: create(key, fingerprint)
Receipts->>Disk: persist pending receipt + agentId
Receipts->>Agent: create assigned agentId
Agent-->>Receipts: creation completed
Receipts->>Disk: mark completed
Receipts-->>Session: durable agentId
Session-->>Hub: agent_created
Hub->>Session: send_agent_message_request(messageId)
Session->>Receipts: send(agentId, messageId, fingerprint)
Receipts->>Agent: ensure agent loaded
Receipts->>Disk: persist pending receipt
Receipts->>Agent: submit prompt
Agent-->>Receipts: accepted
Receipts->>Disk: mark completed
Receipts-->>Session: deduplicated success
Session-->>Hub: accepted
Reviews (2): Last reviewed commit: "fix(hub): allow retries after confirmed ..." | Re-trigger Greptile
Prepare message loading before recording dispatch intent. Remove failed creation receipts only when creation cleanup completed and no live or stored agent exists. Keep ambiguous provider deliveries fail-closed. Exercise native file observation with real filesystem dependencies.
Linked issue
Refs #2673, #3994 and getpaseo/hub#86.
Type of change
Reasoning
Hub needs to send follow-ups to an existing agent and recover its archived workspace. The daemon already provides these operations to ordinary clients. This change makes them available under
hub.execute, with durable request receipts so a lost acknowledgement does not create another agent or submit the same prompt again.Conversation identity and trigger policy stay in Hub. The daemon receives ordinary agent/workspace IDs and opaque operation keys; no new Hub-specific RPC names or trigger-provider branches are introduced.
Goals
hub.execute.Non-goals
hub.execution.*protocol.Supersedes
send_agent_message_requestnow serves this workflow, alongside explicit workspace recovery, without adding an execution-specific prompt RPC. Close the older PR when this replacement merges.QA
Tested on Linux with isolated daemons and real temporary repositories/worktrees. The main development daemon was not restarted. The combined Hub source-built end-to-end suite passed (7 tests), and a real Codex agent finished two arrivals through session MCP with workspace archival/restoration between them. Hub browser coverage passed (79 tests). macOS and Windows were not exercised locally.
The integration journey creates an agent concurrently with one key and gets one ID, subscribes to agent/timeline updates, retries one message and observes one provider prompt, restarts the daemon and repeats both requests without duplication, archives the actual worktree, restores it through the ordinary recovery RPC, and sends a follow-up to the original agent. Authorization tests cover denied administration and permission revocation.
npm run build:client,npm run build:server,npm run typecheck,npm run lint,npm run format: passed.Authority is intentionally daemon-wide:
hub.executecan operate existing agents and workspaces, not just those created by Hub. Daemon administration, terminals, and permission management retain their separate permissions. Public security documentation now states this explicitly.A pending receipt with no recoverable result returns
agent_request_outcome_unknown. The provider may have accepted the message before the daemon recorded success; the caller must reconcile that outcome before choosing a new message ID. Receipts persist request hashes and agent identity, not prompts or credentials.The Hub client advertises
all_providersin the existing hello capabilities so native RPCs can expose custom providers without pretending to be a versioned Paseo app. Existing app version compatibility remains intact. Companion Hub implementation: getpaseo/hub#118. Trigger behavior and migration are documented in the public docs.The first Windows CI run exposed a native file-watcher inventory bug: files announced before the first reconciliation were not remembered, so coalesced deletions could disappear. The small inventory fix has a deterministic regression that fails without it. The affected session, wire, and watcher tests pass (167 tests); full typecheck, lint, formatting, and server build pass.
Confirmed local failures now remain retryable: message loading precedes the pending receipt, and failed creation receipts are removed only after cleanup confirms no live or stored agent exists. Uncertain provider sends still fail closed. The affected request, prompt, session, and watcher files pass (182 tests), and the combined continuation/restoration E2E passed again. Receipt retention remains outside this PR scope.
Checklist
npm run typecheckpassesnpm run lintpassesnpm run formatpasses