fix(desktop): open a cloud workspace at its address instead of behind its wake
Opening a cloud workspace waited on the box twice: once for a wake that costs ~2 s even on a running box, and once for the box's host-service to serve a workspace row through the fan-out. Measured on 23 Sep against production:
| Call | Box | Latency |
|---|---|---|
cloudWorkspace.access, wake: false | running | 355 ms |
cloudWorkspace.access, wake: true | already running | 2,034–2,546 ms |
cloudWorkspace.access, wake: true | asleep → woken | 21,212 ms |
The change
A ready cloud workspace opens on its own row. The route's screen is decided by cloud_workspaces.status and nothing else: provisioning shows the wait, failed shows the failure, ready builds WorkspaceProvider from the cloud row and opens the box. The box's own row still arrives through the fan-out and takes over (the provider is keyed on the id, so that's a props update, not a remount). If the box doesn't answer, the existing HostConnectionStrip says so — it now names the box "Cloud workspace" and explains that it's waking, instead of "Unknown host" with tray-menu advice.
The wake runs beside the workspace, not in front of it. wake is out of the access query key; the open workspace's wake has its own query and writes its fresh ticket back into the one cached address. SandboxTarget.running and both gates on it are gone.
projectId was holding this up, and nothing needed it. Eight reads under the route: three were "is this a session workspace" in disguise and now read type; the rest already handled null (run config disabled, presets fall back to global, Set Run routes to terminal settings). The PR pane's hasProject reads type too. A cloud workspace carries projectId: null like a session does.
The provisioning screen is only for provisioning. The "Connecting" step, the dual-origin timer, and RECENTLY_CREATED_MS are gone. So is the branch line — since #7620 the cloud row's branch is the base, and the box lands on superset/….
Two smaller fixes. The $workspaceId route sets remountDeps, so switching workspaces no longer carries the previous one's clock over (TanStack Router reuses the component across param changes). useCloudWorkspaces keeps its 1 s provisioning poll alive in the background; it paused the moment the window lost focus, and with a missed nudge the loader stayed up for good.
Verified in the dev app, real sandboxes
- Create → open:
provisioningat 0.3 s → loader → rowreadyat 1.9 s → workspace at 6.0 s. No "not found" flash, no strip, none of the removed strings. - Running box, cold open: workspace at 215 ms, loader never rendered.
- Stopped box: workspace chrome at 0.3 s, strip "Connecting…" at 2.4 s, cleared at 12.2 s when the wake landed. Details popover reads "Cloud workspace / This cloud workspace is waking up…", no host-settings link.
- Failed row: its own state.
- Switching workspaces: each shows its own elapsed time (with
remountDeps); without it, B showed A's.
Typecheck, lint, i18n clean; 436/436 tests in the touched areas.
Left for a follow-up
- The layout has accumulated three ways to identify a workspace (host row, cloud row, access target) and gates them by timing. A
"cloud"workspace kind instead oftype: "local"on a cloud row, and a single resolver the layout switches over, is the honest shape. Separate PR. #7620derives the working branch from the workspace name, which auto-naming and rename change after the box is claimed. It should come from the id or be persisted.- Mobile still wakes on open (
wakeSandboxAccess).
https://claude.ai/code/session_01BVBuTCFBb1JkoX76VpLAQ8
Summary by CodeRabbit
- New Features
- Ready cloud workspaces can now open without waiting for a host connection. Workspaces that have been idle display a message explaining that waking may take up to 30 seconds.
- Bug Fixes
- Cloud workspace setup continues to refresh while the app is in the background.
- Pull request actions now reflect whether a workspace is a session workspace.
- UI Updates
- Simplified the cloud workspace setup screen by removing branch details and step-by-step progress indicators.