fix(desktop): sandbox boot-retry, status, per-dashboard workspace#266
Merged
Conversation
…ngle-user UI - Auto-retry the local session-create for ~30s (12×3s) while the desktop VM boots, instead of failing the first terminal on a cold launch with "Network connection lost" (ensureDashboardSandboxCreate legacy/shared-SANDBOX_URL path). - Fix the sandbox status showing red "Sandbox asleep" while the local VM is healthy: the desktop sandbox has no Fly machine, so the status guard keyed on sandbox_machine_id short-circuited before the desktop "ready" branch. Now keys "no sandbox" on sandbox_session_id and returns ready for non-Fly deployments. - Per-dashboard workspace isolation on desktop: default each dashboard's terminals to /workspace/<dashboardId> (shared-sandbox deployments only; downloaded dashboards already set their own workingDir). The sandbox auto-creates the subdir on the desktop VM (ORCABOT_DEBUG_EXEC gate) so the first terminal lands there instead of falling back to the shared root; cloud is unchanged (each dashboard has its own VM). - Hide the multiplayer "N online" presence indicator on desktop (always one local user). Note: the sandbox auto-create (session.go) needs a VM-image rebuild to take effect for newly-created dashboards; downloaded dashboards isolate immediately (their subdir already exists). Control-plane + frontend changes take effect on a resources rebuild. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
Move per-dashboard workspace isolation from a per-PTY workingDir default to the SANDBOX session root, and add a real health check to the desktop status. - [P2] Isolate every dashboard-scoped execution path: manager.Create now roots each desktop session at /workspace/<dashboardID> (ORCABOT_DEBUG_EXEC gate, safe-component checked). Since the whole Session/Workspace is built from that root, UI terminals, chat run_command, schedules, and messaging all inherit it — no per-call plumbing. Reverted the control-plane per-PTY workingDir default (option a). Cloud is unchanged (one VM per dashboard; gate off). - [P2] Fixes the stale-session-retry losing isolation too — isolation no longer depends on the (retry-dropped) workingDir. - [P2] resolveWorkingDir no longer auto-creates arbitrary missing dirs — a typo errors (E79708) again; only the dashboard root is auto-created, in manager.Create. - [P2] Desktop status now probes the local sandbox /health instead of trusting the persisted dashboard_sandboxes row, so a stale row after restart/crash shows "starting" (not green) until the VM actually serves. - cloud-sync: download copies terminal content as-is (no subdir prepend) — the session root provides isolation; the download still writes files to <workspace>/<id> which equals that root. The session-root change is in the guest sandbox binary, so it needs a VM-image rebuild to take effect on desktop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
… root The session-root isolation (/workspace/<dashboardId>) broke two hardcoded-/workspace assumptions: - [P1] Dashboard chat run_command timed out: the wrapper wrote completion markers to absolute /workspace/.orc-run-* but read them via the session-scoped file API, which now resolves under /workspace/<dashboardId> — marker never found. Now the shell redirect uses the SAME relative names as the read (the run PTY cwds into the session root, and the file API resolves relative to it), so it works whether the root is /workspace (cloud) or /workspace/<dashboardId> (desktop). - [P2] Codex folder-trust pre-trusted the fixed /workspace, so desktop terminals starting in /workspace/<dashboardId> would re-show the "trust this directory?" prompt and block unattended startup. generateCodexHooks now trusts the actual session workspaceRoot it's already given (= s.workspace.Root()). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
… round 11)
- [P2] Codex completion events broke across dashboards: each dashboard's per-session
hook path was appended to the SHARED /etc/codex/config.toml notify array as a second
element, so Codex ran the first script with the second path as $1 instead of the
event JSON. Now the notify script is a single GLOBAL, workspace-independent file
(/etc/codex/orcabot-codex-stop.sh) — it already derives session/pty/secret from
per-PTY env vars at runtime — and notify is REPLACED (not appended) with exactly that
one path, idempotent across dashboards.
- [P2] The "~30s" boot retry could block 3+ minutes (12 × up-to-15s client timeout +
11 × 3s) and retried deterministic 4xx failures. Now bounded by an overall 30s
deadline and retries ONLY connection/transient failures ("fetch error:"), throwing
immediately on HTTP status errors (e.g. auth mismatch).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
…d 12) The incremental config assembly appended notify/check_for_updates AFTER the [projects."<root>"] trust tables, so TOML scoped `notify` under a project table instead of top-level — Codex (which reads notify as a top-level array<string>) never saw the global hook. Now rebuild the OrcaBot-managed system config deterministically: top-level keys (check_for_updates, notify) FIRST, then one [projects."<root>"] trust table per accumulated workspace root. Extracted the pure builder (buildCodexSystemConfig) and added a regression test asserting notify precedes any [table], trust accumulates across dashboards, and there's exactly one notify line. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
…view round 13) The config rebuild wrote only check_for_updates/notify/trust, wiping the [mcp_servers.*] sections that mcp.GenerateSettingsForAgent had just written to the same /etc/codex/config.toml — so every Codex launch lost Orcabot + user MCP tools (hook generation runs after MCP generation). buildCodexSystemConfig is now section-aware: it rewrites only the managed top-level keys (check_for_updates, notify — kept before every [table]) and the [projects."<root>"] trust tables, and PRESERVES all other sections verbatim (notably [mcp_servers.*]), stripping only stray managed keys a prior bug nested inside tables. Regression test extended to assert an [mcp_servers.*] section survives regeneration (and stays after notify). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014t8Ukp4NPWtqJ55X261wMZ
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.
Fix the local app sandbox boot status