feat(desktop): cloud mode — connect the desktop to a remote control plane - #845
Open
AbirAbbas wants to merge 4 commits into
Open
feat(desktop): cloud mode — connect the desktop to a remote control plane#845AbirAbbas wants to merge 4 commits into
AbirAbbas wants to merge 4 commits into
Conversation
New connection-state module (base URL + API key, cycle-free) that
cpClient and every raw dashboard/tray fetch now draw auth from; a cloud
settings profile ({enabled, serverUrl, apiKey}) persisted through
normalizeSettings; testCloudConnection (health, auth, install-API,
version probes with per-step timeouts); URL normalization that refuses
plaintext http to public hosts; autostart gating so cloud mode never
probes ports, spawns a server, or auto-starts agents — one remote
health check instead. Fixes fetchUsageStats ignoring the active base
URL.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rol plane New Cloud nav view (agentfield://cloud, Cmd/Ctrl+5): connection status, server URL + API key form with live test verdict (reachable / auth / install API / version), save-and-switch, and switch-back-to-local that keeps the saved profile. Deploy-on-Railway section opens the control plane template through a dedicated IPC channel (no generic URL opener). Profile is applied at startup and immediately on settings change; the local server start IPC refuses politely while a cloud profile is active, and skills sync is skipped in cloud mode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… plane
A freshly deployed control plane returns {"packages":null,"total":0}
(Go marshals nil slices as null), which crashed the Agents view with
'Cannot read properties of null (reading filter)' the moment a cloud
profile pointed at an empty CP. Normalize every list-shaped response at
the cpClient boundary (packages, install jobs, job lines, running
agents, agent/global secrets) and guard the raw node/execution readers.
Regression tests use the exact wire payloads; verified live against an
empty key-enforcing CP.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five explicit states with color: in-flight test (spinner, locked controls), green success with server version, amber degraded verdict for outdated control planes (connected but too old for desktop agent management), red failure with per-check pass/fail marks, and a green confirmation after save/switch with a live status dot. Alignment pass: stacked full-width fields, overlaid show/hide toggle, single action row, fixed-column verdict list, flush Railway steps. Reduced-motion fallback for the spinner. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
The final piece of the one-management-path arc (#837 → #841 → #842 → #843 → #844): AgentField Desktop can now connect to a remote control plane with a saved
{server_url, api_key}profile, managing agents on that box exactly the way it manages a local one — same client, same flows, only the base URL changes.What's new
Cloud tab (
agentfield://cloud, ⌘/Ctrl+5): connection status, server URL + API key form, live Test connection verdict (reachable / auth / install API / server version), Save & switch, and Switch back to local (keeps the saved profile for one-click re-enable). A Deploy on Railway section opens the control-plane template with paste-back instructions, via a dedicated IPC channel — no generic URL-opener hole.Connection core: a new cycle-free connection-state module supplies base URL + API key to
cpClientand the five raw dashboard/tray fetches that previously bypassed auth entirely. URL normalization refuses plaintexthttp://to public hosts, so keys can't leak over cleartext. The cloud profile is applied at startup and immediately on settings change, and survives restarts (normalizeSettingsextended — it silently drops unknown keys otherwise).Guardrails in cloud mode: no local port probing, no
af serverspawn, no agent autostart (one remote health check instead), local-server-start IPC refuses politely, skills sync skipped. Switching back restores previous local behavior exactly.Also fixes a latent bug:
fetchUsageStatsignored the active base URL.Validation
AGENTFIELD_API_KEYenforcement: full management lifecycle (install → secrets → start → stop → uninstall) driven through the cloud profile; test-connection matrix verified live (valid key / rejected key / unreachable); autostart gating and local-mode restore confirmed. Notable: with a key configured, the CP properly 401s missing/wrong keys — fail-closed as required.typecheckclean,dist:dirbuilds.~/.agentfieldconfig material); moving it to ElectronsafeStorageis a noted follow-up.Follow-ups (not in this PR)
control-plane-cloudimage + volume + generated key default)safeStoragefor the API key at rest🤖 Generated with Claude Code