Skip to content

Let Hub continue agents through the standard daemon API - #4354

Merged
boudra merged 3 commits into
mainfrom
hub-agent-continuation
Sep 6, 2026
Merged

Let Hub continue agents through the standard daemon API#4354
boudra merged 3 commits into
mainfrom
hub-agent-continuation

Conversation

@boudra

@boudra boudra commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Linked issue

Refs #2673, #3994 and getpaseo/hub#86.

Type of change

  • New feature
  • Docs

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

  • Permit agent creation, messaging, cancellation, archival, observation, configuration, and workspace recovery through existing RPCs under hub.execute.
  • Add optional creation idempotency keys and deduplicate sends by their existing message IDs, including concurrent requests and daemon restart.
  • Reuse native steering, provider-session loading, and workspace restoration.
  • Advertise support explicitly and make the client reject keyed creation on unsupported hosts.

Non-goals

  • Hub trigger defaults, key expressions, execution/output lifecycle, or editor changes. This is the daemon protocol prerequisite.
  • Workspace retention timers or changes to the existing hub.execution.* protocol.
  • Automatically replaying a provider call whose outcome is unknown.

Supersedes

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.

  • Eight affected client, authorization, receipt, Hub socket, workspace, and snapshot test files: 276 passed, 4 skipped.
  • Native session and wire compatibility files: 153 passed.
  • Agent creation and authorization regression checks: 20 passed.
  • npm run build:client, npm run build:server, npm run typecheck, npm run lint, npm run format: passed.

Authority is intentionally daemon-wide: hub.execute can 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_providers in 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

  • One focused change
  • npm run typecheck passes
  • npm run lint passes
  • npm run format passes
  • QA evidence
  • Tests added or updated where it made sense

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.
@boudra
boudra marked this pull request as ready for review September 5, 2026 14:10
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR exposes standard daemon agent and workspace operations to authenticated Hub sessions and adds durable idempotency receipts for keyed creation and message delivery.

  • Adds protocol capabilities and client compatibility gating for retry-safe creation.
  • Adds persistent creation/message receipts with concurrent and restart-safe deduplication.
  • Expands hub.execute authorization to the required ordinary agent, observation, archival, and workspace-recovery RPCs.
  • Adds workspace restoration and continuation coverage.
  • Fixes the native recursive watcher’s initial file inventory behavior and replaces mocked watcher coverage with a real filesystem test.
  • Updates Hub and security documentation for daemon-wide authority and retry semantics.

Confidence Score: 4/5

The behavior changes appear sound, but the explicit repository testing requirement must be satisfied before merging.

The prior pending-receipt failure is fixed: local message preparation now occurs before receipt persistence, and failed keyed creation removes its pending receipt when no agent was stored. The previous unbounded receipt-retention concern remains because completed creation and message receipts are still retained indefinitely. The previous test-discipline finding also remains outstanding: packages/server/src/server/file-observer/native-recursive.test.ts removed the banned mocks but now imports ./internal/native-recursive.js directly, so it still tests through a private implementation rather than the caller-facing file-observer interface.

Files Needing Attention: packages/server/src/server/agent/requests/index.ts; packages/server/src/server/file-observer/native-recursive.test.ts

Important Files Changed

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
Loading

Reviews (2): Last reviewed commit: "fix(hub): allow retries after confirmed ..." | Re-trigger Greptile

Comment thread packages/server/src/server/agent/requests/index.ts
Comment thread packages/server/src/server/agent/requests/index.ts
Comment thread packages/server/src/server/file-observer/native-recursive.test.ts Outdated
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.
@boudra
boudra merged commit ab7d66d into main Sep 6, 2026
24 checks passed
@boudra
boudra deleted the hub-agent-continuation branch September 6, 2026 08:19
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