feat(probe): resolve the workspace the agent-relay CLI selects (phase 2)
Merged
KH
6d ago+2314+2314+0123456789012345678901234567890123456789-348-348-012345678901234567890123456789
Phase 2 of moving the probe core into relay (stacked on #2012). The probe now finds its Relaycast workspace the way the agent-relay CLI does, so relay init's local server and self-hosted servers work with no Cloud sign-in.
What changed
relay::workspace::cli: a read-only CLI source. It never writes the CLI's files. It follows the CLI's ladder (resolveWorkspaceSelection+resolveWorkspaceTransport):RELAY_WORKSPACE_KEY>AGENT_RELAY_WORKSPACE_KEY>RELAY_API_KEY- the project pin
<project>/.agentworkforce/relay/workspace-key.jsonwhenAGENT_RELAY_PROJECTnames the project. A malformed pin falls through. Persisted routes and their route credential (relaycastApiKeyRef→relaycast-credentials.json) get the CLI's checks. - the active entry of
$AGENT_RELAY_HOME/workspaces.json. If the file exists but can't be read, resolution fails.
relay::workspace::origin_binding: readsrelaycast-origins.jsonusing the CLI's PBKDF2-HMAC-SHA256 fingerprint (via theringalready linked; no new dependency). It is tested againstpackages/contracts/fixtures/relaycast-origin-binding.json, so TS, the broker and the probe all agree. The origin is chosen in this order: persisted route (Agent Relay gateways only; a key bound to another server is refused) →RELAY_BASE_URL→ the binding →https://cast.agentrelay.com.http://127.0.0.1:8787-style origins and self-hosted ports and path prefixes are accepted. If the bindings file orRELAY_BASE_URLis malformed, resolution fails closed.- How the sources combine: the CLI source wins whenever it names a workspace. The Cloud sign-in is used only when the CLI names nothing. If the CLI's selection can't be used, the daemon has no workspace and logs a warning; it does not fall back to the account. Neither source's key is ever sent to the other's origin (
RELAYCAST_URLre-origins only the account's key).Workspace.sourcerecords which source the key came from. - Refresh/verify/recovery: a key rotated in
workspaces.jsonis picked up by the next 30 s rediscovery and verified. Cloud recovery runs only forCloud-sourced keys. - One workspace per daemon (documented). About 40 call sites treat
Core.workspaceas the workspace, so per-project workspaces that differ from the machine's active one are a follow-up. - Prettier fix: the auto-format bot on #2012 reformatted assets that the core embeds verbatim (the OpenCode and Pi plugins, the Claude hook, the sign-in page, fixtures), which broke 2 OpenCode tests. This PR restores them and adds
crates/probe/{src,resources,tests/fixtures}to.prettierignore. - Docs:
docs/probe-move.md(phase 2 done) andcrates/probe/docs/relay-core.md(Workspace discovery).
Behaviour change to note
A desktop that is signed in to Cloud and has an active CLI workspace now uses the CLI's workspace for messaging. Uploads still go to the account. This reaches desktop users only in phase 4.
Verification
HOME=<empty> cargo test --locked --no-fail-fastincrates/probe: everything passes except the two known ones:cloud::tests::cloud_bearer_reuses_only_a_matching_unexpired_official_cli_session(env-dependent) andlive::selected_remote::tests::selected_claude_worker_refreshes_shallow_catalog_and_selected_evidence(flake). 41 new or updated workspace tests cover precedence, origin binding with the shared fixture, malformed files, localhost, persisted routes, the combination rule, rotation, and recovery gating.- Live run, fully isolated (scratch
HOME,AGENT_RELAY_HOME, app-data dir and socket,env -i; no Cloud sign-in):npx -y agent-relay@next init --yes --tools none --port 8799, thenagent-relay-probe relay serve --headless.relay call status.getshowsbase_url http://127.0.0.1:8799,verification: verified,workspace_name: local. With a corruptedrelaycast-origins.jsonthe probe reportsstate: missingand does not fall back.
🤖 Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Agent Relay sessions