(MOT-4388) feat(shell): sandbox target picker on the page - #767
Conversation
Every shell::fs::* and shell::exec* function already accepted
target: { kind: "sandbox", sandbox_id } — one wire shape for host and
guest — but the injected console page only ever spoke to the host. The
page now exposes the selector: a target picker beside the root
affordance lists live microVMs (one sandbox::list read on mount, pushed
{ kind: "fleet" } snapshots over a tab-scoped
sandbox-code-runner::event trigger, manual refresh for when the live
binding is absent; function-not-found on sandbox::list hides the picker
and the page stays pure host).
Host mode is byte-identical to before: coder::* calls, no target field
on the wire (omission is the serde default — an explicit null would be
a deserialize error). With a sandbox selected the same browser/editor
retargets: the tree roots at / and fills in lazily via shell::fs::ls
per expanded directory, search maps onto shell::fs::grep, and every
guest payload carries the target verbatim. Host-coupled chrome drops
out — git tab, workspace root picker, editor writes — and the header
shows the sandbox id (truncated, copyable, full in the title) with a
running/stopped dot. A selected sandbox that leaves the fleet degrades
to the "sandbox gone — reaped or stopped" empty state with a
back-to-host action rather than failing calls silently.
Guest read/write decision: coder::read-file is host-only and
shell::fs::read returns a stream-channel ref the console extension
client cannot consume (host.iii has no channel API), so guest reads
ride shell::exec cat stdout — the same way the git tab already consumes
file bodies via git show — with truncation caught by comparing byte
counts against shell::fs::stat and a NUL probe for binaries. Writes
have no guest path at all (shell::fs::write requires the streamed
ContentRef form on sandbox targets, which the page cannot produce), so
the editor is read-only for guests with a visible note instead of a
broken save.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 21 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
skill-check — worker0 verified, 57 skipped (no docs/).
Four for four. Nicely done. |
- guest reads ride head -c (1 MiB, the editor path's cap) instead of
bare cat, with truncation flagged whenever the capped bytes fall short
of the stat size (or fill the cap when stat reports none)
- fleet reads carry an ordering guard: stale sandbox::list responses are
dropped, and a pushed { kind: "fleet" } snapshot invalidates every
read still in flight
- switching target snapshots host tabs/expanded and restores them on the
return to host, so the persistence effect never saves cleared guest
state over stored host state
- copy-id handles clipboard rejection with a copied/failed flash; the
target refresh + copy buttons get :focus-visible outlines on
--color-rule-focus
All five CodeRabbit findings verified valid against the branch; none
skipped.
What
Every shell function already takes
target: { kind: "sandbox", sandbox_id }— host and sandbox share one wire shape onexec,exec_bg, and allfs::*. The page never exposed it. This adds a target picker to shell's injected page so the same file browser serves the host workspace and every live microVM.host(default — byte-identical behavior, still on thecoder::*twin surface) + one entry per live sandbox. Fleet source: onesandbox::listread on mount, plus{kind:'fleet'}snapshots over thesandbox-code-runner::eventtrigger when that worker is present (handleriii::shell-ui::fleet::<browserId>);sandbox::listfunction-not-found hides the picker entirely.shell::fs::*twins (lslazily per expand from/, search viafs::grepwith regex-escaped literals). Host-only affordances (git tab, workspace roots) hide; the header shows the sandbox id (truncated, copyable) and a running dot; a sandbox that leaves the fleet degrades to "sandbox gone — reaped or stopped" with a one-click return to host.shell::execcat— the page cannot consumeshell::fs::read's ContentRef channel (the console extension client has no channel API), and the README'sread_inlinewrapper does not exist in-repo. Truncation is detected by byte-count againstfs::stat; binaries by NUL probe; both flip the viewer read-only with the existing notes.contentis S210 on sandbox targets; the mandatory ContentRef form is unproducible from the page) — the editor is explicitly read-only for guests with a visible note, rather than a save that breaks.Verification
-D warningsclean, 1334 tests passed.Fixes MOT-4388