sandbox

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package sandbox holds the podman-backed Sandbox implementation (internal/agent.Sandbox) — a session- or worker-scoped rootless container that RunBashTool dispatches commands into via `podman exec` instead of running them directly on the host. See roadmap/sandbox-podman.md for the design.

This package mirrors internal/lsp's role: a sibling package holding an external-process lifecycle, imported only by the two session entry points (internal/tui, internal/oneshot) and internal/agent's dispatch worker wiring — never by internal/agent itself, which only needs the Sandbox interface.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PodmanSandbox

type PodmanSandbox struct {
	// contains filtered or unexported fields
}

PodmanSandbox runs commands inside a single long-lived rootless podman container (`podman run -d ... sleep infinity`), dispatching each RunBashTool call via `podman exec`. One container per session or per dispatch write-worker — never per command (see roadmap/sandbox-podman.md for why a fresh container per command is rejected).

func NewPodmanSandbox

func NewPodmanSandbox(ctx context.Context, cfg config.SandboxConfig, id, mountRoot string) (*PodmanSandbox, error)

NewPodmanSandbox starts a session-scoped container per cfg, bind-mounting mountRoot at the SAME absolute path inside the container (so paths the model uses are valid on both sides). id becomes part of the container name (e.g. a session ID or "<session>-<taskID>" for a dispatch worker).

Synchronous: blocks until the container is confirmed started. On any failure (podman missing, image pull failure, rootless setup issues) it returns a wrapped, actionable error and leaves no container running — callers must treat this as fatal to session/worker startup and must NEVER fall back to HostSandbox on error, which would silently defeat the isolation the caller asked for.

func (*PodmanSandbox) Close

func (s *PodmanSandbox) Close() error

Close removes the container. See removeContainer — Close just adds the caller-facing error wrap; callers at the two documented call sites (session teardown, dispatch worker cleanup) treat it as non-fatal and swallow it, consistent with this codebase's existing best-effort cleanup convention (dispatch_cleanup.go).

func (*PodmanSandbox) Command

func (s *PodmanSandbox) Command(ctx context.Context, command, cwd string) *exec.Cmd

Command returns a `podman exec` into this sandbox's container. Mirrors HostSandbox.Command's contract exactly: command is a single /bin/sh -c argument, so there is no new shell-injection surface beyond what already exists for the host path today.

The command is tagged with a unique marker and cmd.Cancel is set to best-effort kill the marked process (and its direct children) inside the container when ctx is canceled or times out. Without this, the default Cancel behavior (kill the local `podman exec` client) does NOT kill the process it started inside the long-lived container — verified empirically: a canceled `sleep 30` kept running, reparented to the container's PID 1, after the local client was killed. A plain process-group kill doesn't reach it either — this container setup gives no per-exec process group (children inherit the container's own group rather than a fresh one), also verified by direct test.

Known residual limitation: only the marked process and its DIRECT children are targeted, covering the wrapper shell + whatever it directly forks — the overwhelming majority of real run_bash shapes. A grandchild the command itself spawns can still survive as an orphan inside the container until Close() removes it. Full recursive-tree cleanup would need per-exec process-group isolation this container doesn't have.

func (*PodmanSandbox) Label

func (s *PodmanSandbox) Label() string

Unambiguously "-sandbox", not just "[podman]" — a bare "[podman]" tag on a run_bash card reads like a statement about the command itself (e.g. "this ran podman"), not "this ran inside a podman sandbox container".

type Status

type Status struct {
	Installed    bool
	ImagePresent bool // only meaningful when Installed
}

Status reports whether podman is usable and whether the configured base image is already present locally. Surfaced by the TUI /sandbox picker so a missing podman or unpulled image shows up as a warning there, instead of only failing later when NewPodmanSandbox runs at session start.

func DetectStatus

func DetectStatus(ctx context.Context, image string) Status

DetectStatus checks podman availability and whether image is already pulled locally. Never triggers a pull or touches the network — `podman image exists` is a local metadata lookup.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL