feat: github.com/flanksource/sandbox-runtime with --sandbox flag - #41
Conversation
Sandbox previously rewrote already-resolved models to CLI backends with a dedicated helper, duplicating registry behavior and making it appear that model identity changed.\n\nPass CLI mode into the existing resolver instead, apply it consistently to fallbacks and prompt overlays, and reject explicit API runtime contradictions.
Route --sandbox through the existing ModelFlags mode path while preserving mode during compact selector expansion and retaining WithMode as the shared model helper. Consolidate repetitive resolver cases and replace weak wrapper assertions with exact policy, provider wiring, and lifecycle cleanup coverage.
WalkthroughChangesThe pull request adds sandboxed execution for Claude, Codex, and Gemini CLI providers. It adds runtime-mode resolution, CLI-mode validation, sandbox configuration propagation, cleanup handling, and tests. The install task now uses metadata-aware Sandboxed CLI runtime
Installation task
Sequence Diagram(s)sequenceDiagram
participant AIProviderOptions
participant RuntimeRegistry
participant startCLIStream
participant sandbox-runtime
participant CLIProcess
AIProviderOptions->>RuntimeRegistry: resolve sandbox configuration as CLI mode
RuntimeRegistry->>startCLIStream: create CLI stream with sandbox enabled
startCLIStream->>sandbox-runtime: configure and wrap provider command
sandbox-runtime->>CLIProcess: start restricted Claude, Codex, or Gemini process
CLIProcess-->>startCLIStream: stream process output
startCLIStream-->>AIProviderOptions: return stream and sandbox cleanup
AIProviderOptions->>sandbox-runtime: close sandbox after stream completion or startup failure
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
✨ Simplify code
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
pkg/ai/provider/claude_cli.go (1)
17-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake
NewClaudeCLIsetsandboxat construction, likeNewCodexCLI.
NewClaudeCLI(model string)does not acceptai.Config, sosandboxstays at its zero value unless a caller setsprovider.sandbox = cfg.Sandboxafterward. pkg/ai/provider/init.go currently does this correctly for bothBackendClaudeCLIandBackendGeminiCLI, but the pattern relies on every future caller remembering the follow-up assignment.NewCodexCLI(cfg ai.Config)avoids this by accepting the full config and settingsandbox: cfg.Sandboxdirectly.Since
Config.Sandboxis documented so "the flag cannot be silently ignored," alignNewClaudeCLI(andNewGeminiCLI) withNewCodexCLI's single-step pattern to remove the two-step construction risk.♻️ Proposed refactor for NewClaudeCLI
-func NewClaudeCLI(model string) *ClaudeCLI { - if strings.TrimSpace(model) == "" { - model = "opus" - } - model = ai.NormalizeModelForBackend(ai.BackendClaudeCLI, model) - return &ClaudeCLI{model: model} -} +func NewClaudeCLI(cfg ai.Config) *ClaudeCLI { + model := cfg.Model.Name + if strings.TrimSpace(model) == "" { + model = "opus" + } + model = ai.NormalizeModelForBackend(ai.BackendClaudeCLI, model) + return &ClaudeCLI{model: model, sandbox: cfg.Sandbox} +}This requires updating
NewClaudeCLIcall sites (pkg/ai/provider/init.go, pkg/ai/provider/cli_test.go) to passai.Configinstead of a bare model string.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/ai/provider/claude_cli.go` around lines 17 - 28, Update NewClaudeCLI to accept ai.Config, derive and normalize the model from cfg, and initialize sandbox from cfg.Sandbox like NewCodexCLI. Update its call sites in init.go and cli_test.go to pass the full configuration, and apply the same constructor pattern to NewGeminiCLI so sandbox is set during construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/cli/ai_prompt_file.go`:
- Around line 106-111: Derive one effective sandbox value from both the request
option and saved configuration, then use it consistently in the mode-enforcement
block around requestedMode and when setting cfg.Sandbox. This must force
registry.ModeCLI whenever either sandbox source is enabled, while preserving the
existing validation for an explicitly incompatible --mode.
In `@pkg/cli/prompt_source.go`:
- Line 125: Update actionFlagsToOptions to assign the persisted f["mode"] flag
to o.Mode, alongside the existing Sandbox mapping, so prompt actions specifying
mode: cli reach overlayCLI unchanged.
---
Nitpick comments:
In `@pkg/ai/provider/claude_cli.go`:
- Around line 17-28: Update NewClaudeCLI to accept ai.Config, derive and
normalize the model from cfg, and initialize sandbox from cfg.Sandbox like
NewCodexCLI. Update its call sites in init.go and cli_test.go to pass the full
configuration, and apply the same constructor pattern to NewGeminiCLI so sandbox
is set during construction.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9ff846c8-e4be-4231-9a1c-4ed15b95801a
📒 Files selected for processing (21)
Taskfile.yamlpkg/ai/provider/claude_cli.gopkg/ai/provider/cli.gopkg/ai/provider/cli_test.gopkg/ai/provider/codex_cli.gopkg/ai/provider/gemini_cli.gopkg/ai/provider/init.gopkg/aiflags/flags.gopkg/api/registry/model.gopkg/api/registry/model_compact.gopkg/api/registry/parse.gopkg/api/runtime_config.gopkg/api/runtime_provider_ginkgo_test.gopkg/api/runtime_registry.gopkg/cli/ai.gopkg/cli/ai_prompt_file.gopkg/cli/ai_prompt_file_test.gopkg/cli/ai_test.gopkg/cli/prompt_source.gopkg/cli/prompt_source_test.gopkg/cli/provider_defaults.go
| if o.Sandbox { | ||
| if requestedMode != "" && requestedMode != registry.ModeCLI { | ||
| return base, baseCfg, fmt.Errorf("--sandbox requires CLI mode, but --mode is %q", requestedMode) | ||
| } | ||
| requestedMode = registry.ModeCLI | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Apply CLI mode when any sandbox source is enabled.
baseCfg.Sandbox enables cfg.Sandbox at Line 190, but it does not enter the CLI-mode enforcement block. A saved sandbox configuration can therefore resolve an API or agent backend. The provider validation layer will reject that configuration.
Use one effective sandbox value for both mode enforcement and cfg.Sandbox.
Proposed fix
- if o.Sandbox {
+ sandbox := o.Sandbox || baseCfg.Sandbox
+ if sandbox {
if requestedMode != "" && requestedMode != registry.ModeCLI {
return base, baseCfg, fmt.Errorf("--sandbox requires CLI mode, but --mode is %q", requestedMode)
}
requestedMode = registry.ModeCLI
}
@@
- cfg.Sandbox = o.Sandbox || baseCfg.Sandbox
+ cfg.Sandbox = sandboxAlso applies to: 190-190
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/cli/ai_prompt_file.go` around lines 106 - 111, Derive one effective
sandbox value from both the request option and saved configuration, then use it
consistently in the mode-enforcement block around requestedMode and when setting
cfg.Sandbox. This must force registry.ModeCLI whenever either sandbox source is
enabled, while preserving the existing validation for an explicitly incompatible
--mode.
| o.APIURL = f["api-url"] | ||
| o.NoCache = flagBool(f["no-cache"]) | ||
| o.Budget = f["budget"] | ||
| o.Sandbox = flagBool(f["sandbox"]) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Map the persisted mode action flag.
actionFlagsToOptions does not assign f["mode"] to o.Mode. As a result, a prompt action with mode: cli does not reach overlayCLI.
Proposed fix
o.Backend = f["backend"]
+ o.Mode = f["mode"]
o.APIKey = f["api-key"]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@pkg/cli/prompt_source.go` at line 125, Update actionFlagsToOptions to assign
the persisted f["mode"] flag to o.Mode, alongside the existing Sandbox mapping,
so prompt actions specifying mode: cli reach overlayCLI unchanged.
Summary by CodeRabbit
New Features
--sandboxoption and automatic CLI-mode enforcement.Bug Fixes
Chores