You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Add remote instances, so one devStudio can run work on another (#54)
Introduces IExecutionHost: the machine a session's work happens on. Everything
on it is filesystem- or process-bound — the CLI registry, workspace service,
account service, workspace files and terminal — which is exactly the set of
things that stops being true when the work moves elsewhere.
LocalExecutionHost returns the services that were already registered, so the
local path is unchanged and remoting is the special case. RemoteExecutionHost
returns proxies that turn each call into a SignalR invocation, and the hub on
the far side hands them to its own ordinary services — the same ones its UI
uses, so there is no separate "remote mode" to drift.
The session, its transcript, the agent, the project and the queue that
dispatched it all stay local, so there is still one place you look for your
conversations. What travels is the CLI process, the login it runs as, the
checkout and the workspace.
Transport is SignalR at /hubs/remote. A turn is a stream — the events a CLI
produces arrive over a minute or several — so a hub method returning
IAsyncEnumerable<AgentEvent> maps straight onto IProviderCli.RunTurnAsync and a
remote transcript fills in as the work happens rather than arriving all at once.
Pairing is asked for on one side and granted on the other: a request lodges as
pending with a six-digit code and a notification, somebody approves it, and a
five-year JWT is issued. Long on purpose — this pairs two machines the same
person owns, and what ends it is revocation rather than the calendar. The grant
is checked on every call, so revoking takes effect on the far side's next
request despite the expiry.
Choosing an instance reloads every dependent dropdown, because a repository id,
a login, a skill and an MCP server all name something on one particular machine.
One GetConfig call answers for both local and remote, so the two share a path.
Also carries a WorkspacePlan seam through IWorkspaceService: the project's
contribution — repository, base branch and uploaded files, contents and all — is
resolved locally and carried across, because over there the project does not
exist. Local and remote then run the same build.
Two faults found while driving this between two live instances:
UseStatusCodePagesWithReExecute turned the empty 401s from the remote endpoints
into sign-in redirects, which the far side follows instead of noticing its
access was withdrawn; and StreamTerminal read IsRunning twice, so a process
exiting between the send and the check ended the stream after a frame claiming
it was still going, leaving the caller with no exit code.
Claude-Session: https://claude.ai/code/session_01JwMfdZjqLyrBMgVab8P8b6
Co-authored-by: Matt Ratcliffe <m.ratcliffe@htrak.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>