English | 中文
E2B implementation of the @deepseek-ai/dsh-subprocess seam. It has no config: load @deepseek-ai/dsh-e2b first, then this service in place of dsh-subprocess-local. Existing Bash, PTY, LSP, and subprocess Code Runtime consumers then execute in the shared remote sandbox without E2B-specific capability packages.
Sandbox.commands.run(..., { background: true }) starts remotely. pid is -1 until the wrapper publishes and the adapter validates its process-group id; stdin and ordinary observation wait for that publication, while cancellation can stop the provisional SDK handle first.cwd and private runtimeRoot come from the shared owner; executable lookup verifies absolute paths or resolves a bare name against the sandbox PATH plus explicit overrides.exec setsid --wait and records its actual process-group id plus private status files beneath ctx.e2b.runtimeRoot/processes. The handle waits for that file instead of treating the SDK command PID as its published identity. Termination signals the negative recorded id with SIGTERM, waits the caller's graceMs, then escalates to SIGKILL and the SDK kill fallback; TERM delivery or probe failures also force that escalation. A failed transaction is observable through waitForExit() and may be retried, while successful termination remains a permanent no-op. Before publication, cancellation uses the provisional SDK handle; if publication fails, rollback kills and verifies the provisional group before startup rejects. Service disposal rejects new starts, terminates and joins every retained process group, then awaits SDK settlement and private cleanup before the sandbox owner disposes.DSH_* and credential-shaped (*KEY*, *SECRET*, *TOKEN*) names, then restores every spec.env entry as an explicit caller opt-in. Host ambient variables never enter the sandbox implicitly. Private environment files are removed after consumption, and failed command or terminal setup removes its private state before rejecting.graceMs, the adapter disconnects an incomplete SDK stream, withholds its partial spill, and returns that status while retaining the remote group for waitForExit() and termination. Batch and streaming stdin use the SDK handle.spawnTerminal() uses E2B's byte PTY API, installs the exact argv and scrubbed environment through private mode-0600 files, reports the foreground process group, sends real signals, and tears down every group in the remote terminal session before settlement. A private random output boundary discards the E2B bootstrap shell's prompt and echoed runner command while preserving every requested-process byte, including its first prompt. Setup and teardown own the private state transaction, fence publication during service disposal, and include failure cleanup. Prompt detection, scrollback, readiness, and owner policy remain in dsh-pty-local.The base E2B image supplies the runtime and Bash/GNU utilities this adapter invokes: node, bash, setsid, ps, awk, tr, env, chmod, tee, head, rm, and kill. A custom template must retain compatible commands and E2B PTY support.
Indirectly, through consumer seams such as the Bash executor behind dsh-tool-bash, which render remote output, exit facts, background deltas, and spill paths.
No direct invalidation; the named consumers own any request-prefix changes.
CommandHandle.stdout and .stderr accumulate the base64 transport even when this adapter exposes bounded raw-byte tails, so the subprocess seam's normal host-memory bound is not achieved and transport retention is larger than the source stream.pid remains -1 during remote startup; consumers that require a positive PID immediately, including the ACP child backend, cannot use this provider unchanged.SubprocessHandle objects or output cursors from them..dsh-e2b; this POC supplies no retention sweep.SIGTERM or SIGKILL is reported as a signal; every unrequested SDK exit remains an exit code, including values shaped like 128 + signal.