feat: add BoxLite as a sandbox provider#2964
Conversation
Wire boxlite (https://github.com/boxlite-ai/boxlite) into the extension sandbox registry as an optional provider. Adds BoxliteSandboxClient / Options / Session / State backed by boxlite.SimpleBox, with exec, read, write, persist_workspace, and hydrate_workspace implemented via the existing exec + tar + base64 pattern used by the Vercel backend.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2418bc3a34
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| context={"backend": "boxlite", "box_id": self.state.box_id}, | ||
| ), | ||
| ) | ||
| buf = await self.read(Path(archive_path)) |
There was a problem hiding this comment.
Read snapshot archive without workspace path checks
persist_workspace() writes the tarball to /tmp and then calls self.read(Path(archive_path)), but read() enforces _validate_remote_path_access and rejects absolute paths outside manifest.root unless an explicit extra path grant exists. With the default /workspace root and no /tmp grant, persistence fails deterministically; hydrate_workspace() has the same issue via self.write(Path(archive_path), ...).
Useful? React with 👍 / 👎.
| box.exec( | ||
| normalized[0], | ||
| *normalized[1:], | ||
| cwd=self.state.manifest.root, | ||
| ), |
There was a problem hiding this comment.
Propagate sandbox environment into command execution
BoxliteSandboxSession stores options.env in state, but _exec_internal() executes box.exec(...) with only argv and cwd and never merges either state.env or manifest.environment. This means user-configured environment variables are silently ignored in BoxLite sessions, so commands that depend on variables like API tokens or proxy settings will break.
Useful? React with 👍 / 👎.
| state.workspace_root_ready = False | ||
| inner = BoxliteSandboxSession.from_state(state) | ||
| await inner._ensure_box() | ||
| return self._wrap_session(inner, instrumentation=self._instrumentation) |
There was a problem hiding this comment.
Reattach to existing BoxLite session on resume
resume() always clears workspace_root_ready and immediately starts a new SimpleBox path without using state.box_id (or any persisted reuse flag), so it cannot target the previously running sandbox identity. In resume flows without a restorable snapshot, this drops prior workspace state and can leave the original box orphaned.
Useful? React with 👍 / 👎.
|
@seratch Could you please take a look? |
Summary
BoxliteSandboxClient/BoxliteSandboxClientOptions/BoxliteSandboxSession/BoxliteSandboxSessionStateundersrc/agents/extensions/sandbox/boxlite/, backed byboxlite.SimpleBox(local-first micro-VM sandbox with hardware isolation — https://github.com/boxlite-ai/boxlite).src/agents/extensions/sandbox/__init__.pywith the standard optional-import guard (_HAS_BOXLITE) and conditional__all__extension, matching the pattern used by the other cloud backends.boxlite = ["boxlite>=0.8.2"]inpyproject.tomlplus a mypyignore_missing_importsoverride.BaseSandboxSessionoverrides:_exec_internalviabox.exec;read/writevia base64-over-exec;persist_workspace/hydrate_workspacevia tar-over-exec;runningviabox.info().state.Test plan
make formatmake lintuv run mypy src/agents/extensions/sandbox/boxlite tests/extensions/test_sandbox_boxlite.py— cleanuv run pytest tests/extensions/test_sandbox_boxlite.py— 7/7 passing (options serialization, state round-trip via registry, create validation, exec translation, running probe, shutdown, base64 read)pip install boxliteand a realpython:slimbox