Skip to content

feat(sandbox): pluggable SandboxBackend + Alibaba OpenSandbox adapter (#516)#645

Closed
merchloubna70-dot wants to merge 5 commits into
Hmbown:mainfrom
merchloubna70-dot:feat/sandbox-backend-516
Closed

feat(sandbox): pluggable SandboxBackend + Alibaba OpenSandbox adapter (#516)#645
merchloubna70-dot wants to merge 5 commits into
Hmbown:mainfrom
merchloubna70-dot:feat/sandbox-backend-516

Conversation

@merchloubna70-dot

Copy link
Copy Markdown

What this does

Adds a pluggable sandbox backend layer to exec_shell, making #516 (Firecracker microVM) an implementation detail rather than a hard dependency.

# ~/.deepseek/config.toml
sandbox_backend = "opensandbox"          # opt-in, default = "none"
sandbox_url     = "http://localhost:8080" # local OpenSandbox instance
sandbox_api_key = ""                      # optional

Architecture

exec_shell ──► SandboxBackend trait ──► OpenSandboxBackend (HTTP REST)
                                    └──► LocalBackend (default, unchanged)

The SandboxBackend trait is minimal — any future backend (Firecracker, Tencent Cube, E2B, Docker) just implements async fn exec(cmd, env) -> Result<SandboxOutput>.

Why OpenSandbox first?

Instead of building Firecracker from scratch, this PR integrates Alibaba OpenSandbox (10.4k stars, Apache-2.0, Docker Compose deploy, active development). It's the most mature open-source sandbox in the Chinese AI ecosystem and works on Linux + macOS via Docker — no KVM required.

Upgrade path: once Tencent CubeSandbox (microVM, E2B-compatible) stabilises past v0.1, adding it is a 50-line trait impl.

Backend Stars Deploy Notes
Alibaba OpenSandbox 10.4k Docker Compose This PR — multi-backend, most mature
Tencent Cube 5.0k k8s/bare-metal microVM, future impl
E2B SaaS Western users, future impl

No sandbox overhead for users who don't opt in — sandbox_backend defaults to "none".

Implemented using deepseek exec --model deepseek-v4-pro. 🐋

macworkers and others added 3 commits May 4, 2026 12:39
All system prompts were English-only, causing DeepSeek V4 to reason
and respond in English even when users wrote in Chinese or other
languages.

Add a Language Mirror section to base.md and base.txt that instructs
the model to detect the user's primary language and use it for both
reasoning (thinking tokens) and the final reply.
base.txt is not referenced via include_str! in prompts.rs.
Only base.md is loaded (BASE_PROMPT). Remove the redundant change
to base.txt as noted by Gemini Code Assist review.
…dapter (Hmbown#516)

Adds a pluggable sandbox layer to exec_shell, with Alibaba OpenSandbox
as the first opt-in backend. No sandbox by default — existing behavior
unchanged.

New files:
  crates/tui/src/sandbox/mod.rs       — SandboxBackend trait + factory
  crates/tui/src/sandbox/backend.rs   — SandboxOutput, SandboxKind
  crates/tui/src/sandbox/opensandbox.rs — HTTP adapter for OpenSandbox REST API

Config additions (~/.deepseek/config.toml):
  sandbox_backend = "opensandbox"   # or "none" (default)
  sandbox_url = "http://localhost:8080"
  sandbox_api_key = "..."           # optional

Implemented using `deepseek exec --model deepseek-v4-pro`. 🐋
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@merchloubna70-dot

Copy link
Copy Markdown
Author

One more suggestion: consider enabling GitHub Discussions for this repo (Settings → Features → Discussions).

DeepSeek-TUI has a large Chinese user base (most of the issues filed today are in Chinese), and Discussions is where that community naturally organizes — Q&A, show-and-tell, feature ideas that aren't quite ready to be issues. It also keeps issues cleaner by giving users a place to ask "how do I..." without opening a bug report.

Takes 10 seconds to enable and costs nothing. wangfengcsu@qq.com 🐋

@Hmbown

Hmbown commented May 5, 2026

Copy link
Copy Markdown
Owner

Review notes from v0.8.12 integration

Reviewed the sandbox backend infrastructure as part of merging into v0.8.12. Two findings:

create_backend() is never called

The trait abstraction (SandboxBackend), the OpenSandboxBackend HTTP client, the create_backend() factory, and the sandbox_backend field on ToolContext all compile and look well-structured. But create_backend() is called from nowhere in the codebase — not in Engine::new, not in build_tool_context, not in main.rs. The field on ToolContext is always None, and the shell.rs integration path is unreachable.

This means the entire feature is dead code in its current form — users who configure sandbox_backend = "opensandbox" in config.toml will see no effect.

expect() panic risk

In OpenSandboxBackend::new():

let client = reqwest::Client::builder()
    .timeout(Duration::from_secs(timeout_secs))
    .build()
    .expect("reqwest::Client::builder should not fail with default settings");

While the default builder almost never fails, a stripped system without a TLS backend would panic the entire TUI process here — not just this feature, every running session. Should return a Result and propagate the error.

Recommendation

  1. Fix the expect() to return Result — one-line change
  2. Wire create_backend() into Engine::build_tool_context so the feature actually activates — about 4 lines in the engine

The infrastructure itself is clean. It just needs the last mile of wiring.

@Hmbown

Hmbown commented May 5, 2026

Copy link
Copy Markdown
Owner

v0.8.12 fix applied

Two issues from the review have been resolved on the feat/v0.8.12 branch:

  1. expect() panicOpenSandboxBackend::new() now returns Result and the error propagates via create_backend(). If TLS init fails, the engine continues with local execution as fallback.

  2. create_backend() never called — The engine now creates the sandbox backend in Engine::new() (from api_config) and wires it into ToolContext via build_tool_context(). exec_shell checks context.sandbox_backend and routes accordingly.

Commits:

  • ca9fccc0d — replace expect() with Result
  • b51fa6bc9 — wire create_backend() into the engine

The SandboxBackend trait, OpenSandboxBackend, and create_backend()
factory were all dead code — no production code path called
create_backend(). Wire it into Engine::new so the configured backend
is initialized at startup, and expose it to shell tools via
build_tool_context → with_sandbox_backend().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@merchloubna70-dot

Copy link
Copy Markdown
Author

Fixed — added sandbox_backend: Option<Arc<dyn SandboxBackend>> field to Engine, initialized via create_backend(api_config) in Engine::new, and wired into build_tool_context via with_sandbox_backend.

Hmbown added a commit that referenced this pull request May 5, 2026
47 fmt drifts had accumulated from the squash-merged community PRs on
this branch (#653, #654, #655, #645, #658, #668, #659, #661, #660,
#667, #656). Pure formatting — no behavioural changes — applied via
`cargo fmt --all` to satisfy CI's `cargo fmt --all -- --check` gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…own#516)

timeout_secs was stored as a struct field but only needed during
construction to configure the reqwest client. Remove the field.
SandboxKind::as_str() is a utility method with no callers yet;
annotate with #[allow(dead_code)] rather than deleting it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kibuniverse pushed a commit to kibuniverse/DeepSeek-TUI that referenced this pull request May 5, 2026
kibuniverse pushed a commit to kibuniverse/DeepSeek-TUI that referenced this pull request May 5, 2026
…g docstring

Hmbown#651: fix test assertion — section_bg now Color::Reset (was DEEPSEEK_INK)
Hmbown#645: replace expect() with Result in OpenSandboxBackend::new()
Hmbown#653: correct resolve_prefixes docstring to describe deny-always-wins
kibuniverse pushed a commit to kibuniverse/DeepSeek-TUI that referenced this pull request May 5, 2026
…mbown#645)

The sandbox backend infrastructure was complete but the engine never
called create_backend(), leaving the feature dead. Now:
- Engine::new() creates the backend from api_config (non-fatal on error)
- build_tool_context() attaches it to the ToolContext
- exec_shell checks context.sandbox_backend and routes accordingly
MMMarcinho pushed a commit to MMMarcinho/DeepSeek-TUI that referenced this pull request May 6, 2026
MMMarcinho pushed a commit to MMMarcinho/DeepSeek-TUI that referenced this pull request May 6, 2026
…g docstring

Hmbown#651: fix test assertion — section_bg now Color::Reset (was DEEPSEEK_INK)
Hmbown#645: replace expect() with Result in OpenSandboxBackend::new()
Hmbown#653: correct resolve_prefixes docstring to describe deny-always-wins
MMMarcinho pushed a commit to MMMarcinho/DeepSeek-TUI that referenced this pull request May 6, 2026
…mbown#645)

The sandbox backend infrastructure was complete but the engine never
called create_backend(), leaving the feature dead. Now:
- Engine::new() creates the backend from api_config (non-fatal on error)
- build_tool_context() attaches it to the ToolContext
- exec_shell checks context.sandbox_backend and routes accordingly
MMMarcinho pushed a commit to MMMarcinho/DeepSeek-TUI that referenced this pull request May 6, 2026
47 fmt drifts had accumulated from the squash-merged community PRs on
this branch (Hmbown#653, Hmbown#654, Hmbown#655, Hmbown#645, Hmbown#658, Hmbown#668, Hmbown#659, Hmbown#661, Hmbown#660,
Hmbown#667, Hmbown#656). Pure formatting — no behavioural changes — applied via
`cargo fmt --all` to satisfy CI's `cargo fmt --all -- --check` gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Hmbown

Hmbown commented May 23, 2026

Copy link
Copy Markdown
Owner

This PR was opened before the v0.8.41 rebrand and is now stale. Feel free to rebase onto current main and reopen. 鲸鱼兄弟们等你 🐋

@Hmbown Hmbown closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants