container

package
v0.7.0-rc.4 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2026 License: AGPL-3.0 Imports: 29 Imported by: 0

Documentation

Overview

Package container provides container lifecycle management for agents.

Index

Constants

View Source
const AgentStartupHealthTimeout = 2 * time.Minute

AgentStartupHealthTimeout bounds cold runtime initialization, including migrations and process-local startup hooks that complete before readiness.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentOpts

type AgentOpts struct {
	AgentID uuid.UUID
	Image   string            // Docker image to run (e.g., "my-agent:abc123")
	Token   string            // Versioned agent JWT issued from the live agent row
	Env     map[string]string // Additional environment variables
}

AgentOpts configures an agent container.

type AgentRuntimeSpec added in v0.4.0

type AgentRuntimeSpec struct {
	Image        string
	TokenVersion int64
	Status       string
}

PruneAgentResources removes Docker containers and images for agents that no longer exist in the database, and removes stale image tags for active agents (keeping only the current image_ref).

AgentRuntimeSpec is the persisted identity a reusable agent container must match.

type ConnectorBuildOpts added in v0.6.1

type ConnectorBuildOpts struct {
	SourceDir  string
	OutputDir  string
	Package    string
	Filename   string
	Platform   string
	GoProxyDir string
}

ConnectorBuildOpts describes one pure-Go connector compilation in the untrusted build sandbox. Platform is empty for the Linux-native manifest binary, which every connector package must compile regardless of its targets.

type Container

type Container struct {
	ID       string // Docker container ID
	Name     string // Human-readable name
	Endpoint string // HTTP endpoint (e.g., "http://172.17.0.2:8080")
	Token    string // Bearer token for authenticating requests to this container
	AgentID  uuid.UUID
	// Image is the tag the container was started with, copied from
	// Docker's Config.Image at inspect time. StartAgent compares this
	// against opts.Image to detect a stale running container after a
	// build/rollback swap — adopting one with the wrong image would
	// silently keep the agent on the old code.
	Image string
	// Network is the Docker network selected when the runtime was created.
	// Managed isolation uses it to reject containers left on a shared network.
	Network string
}

Container represents a running container.

type ContainerManager

type ContainerManager interface {
	// StartAgent ensures an agent container is running.
	// Returns the existing container if already running and healthy.
	StartAgent(ctx context.Context, opts AgentOpts) (*Container, error)

	// GetRunning returns the running container for an agent without starting
	// one if absent. Returns (nil, nil) when no container is up. Used by
	// out-of-band signals (e.g. /refresh push) where booting a container
	// just to notify it would defeat the purpose.
	GetRunning(ctx context.Context, agentID uuid.UUID) (*Container, error)

	// RunningAgents reports, per requested agent ID, whether a running
	// container currently exists for it. One Docker query regardless of
	// how many agents are asked about — for list/grid views that would
	// otherwise fan out into one inspect per agent.
	RunningAgents(ctx context.Context, agentIDs []uuid.UUID) (map[uuid.UUID]bool, error)

	// StopAgent stops a specific agent's container (resolved from the agent
	// ID via the instance-scoped name scheme).
	StopAgent(ctx context.Context, agentID uuid.UUID) error

	// MarkBusy / MarkIdle bracket an in-flight request to an agent
	// container. While the in-flight count is above zero the idle
	// reaper leaves the container alone, even past the idle timeout —
	// so a run that runs longer than the timeout is not killed
	// mid-execution. MarkIdle also refreshes the idle clock, so the
	// timeout is measured from the end of the last request. Pair every
	// MarkBusy with exactly one MarkIdle.
	MarkBusy(agentID uuid.UUID)
	MarkIdle(agentID uuid.UUID)

	// StartToolserver starts an ephemeral toolserver container for build operations.
	// Returns the container with a WebSocket endpoint for tool execution.
	StartToolserver(ctx context.Context, opts ToolserverOpts) (*Container, error)

	// StopToolserver stops and removes an ephemeral toolserver container.
	StopToolserver(ctx context.Context, name string) error

	// KillToolserver force-kills (SIGKILL) and removes an ephemeral
	// toolserver container without waiting for graceful shutdown. Used
	// on the build-cancel path so an in-flight tool stops emitting logs
	// the moment cancel hits, instead of after the 5s graceful timeout.
	KillToolserver(ctx context.Context, name string) error

	// CaptureToolserverDiagnostics snapshots abnormal runtime state/logs
	// before the ephemeral toolserver container is removed.
	CaptureToolserverDiagnostics(ctx context.Context, name, reason string) error

	// InspectManifest runs a candidate image in manifest mode and returns the
	// manifest written to stdout.
	InspectManifest(ctx context.Context, imageRef string) ([]byte, error)

	// BuildConnectorBinary compiles one connector with CGO disabled in a
	// read-only, capability-free build container.
	BuildConnectorBinary(ctx context.Context, opts ConnectorBuildOpts) error

	// InspectConnectorManifest runs a native connector binary in the same
	// no-network manifest envelope used for candidate agent manifests.
	InspectConnectorManifest(ctx context.Context, binaryPath string) ([]byte, error)

	// RemoveImage removes a Docker image by reference (e.g., "agentID:hash").
	RemoveImage(ctx context.Context, imageRef string) error

	// LockSwap serializes the agent's container-swap window. Held by the
	// builder around Phase F (StopAgent → StartAgent → UpdateAgentRefs)
	// and by EnsureRunning around its GetAgent → StartAgent critical
	// section, so a concurrent trigger can't start the old image while a
	// build is mid-swap (and vice versa). Returns a release function
	// callers must defer. Scope is just the swap — codegen, image build,
	// and migration validation all run outside the lock.
	LockSwap(agentID uuid.UUID) func()
}

ContainerManager manages the lifecycle of agent containers.

type DirectRuntimeNetworkPolicy added in v0.4.1

type DirectRuntimeNetworkPolicy struct{}

DirectRuntimeNetworkPolicy keeps managed per-agent networks internet-capable. Per-agent networks still separate runtimes from one another.

func (DirectRuntimeNetworkPolicy) Internal added in v0.4.1

type DockerManager

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

DockerManager implements ContainerManager using the Docker API.

func NewDockerManager

func NewDockerManager(cfg *config.Config, pool *pgxpool.Pool, networkPolicy RuntimeNetworkPolicy, logger *zap.Logger) *DockerManager

NewDockerManager creates a Docker-based ContainerManager.

func (*DockerManager) BuildConnectorBinary added in v0.6.1

func (m *DockerManager) BuildConnectorBinary(ctx context.Context, opts ConnectorBuildOpts) error

BuildConnectorBinary compiles untrusted connector source without exposing the Docker socket, runtime credentials, or a writable source tree.

func (*DockerManager) CaptureToolserverDiagnostics added in v0.4.0

func (m *DockerManager) CaptureToolserverDiagnostics(ctx context.Context, name, reason string) error

CaptureToolserverDiagnostics snapshots abnormal tool runtime state/logs.

func (*DockerManager) Close

func (m *DockerManager) Close()

Close stops the idle reaper and closes the Docker client.

func (*DockerManager) GetRunning

func (m *DockerManager) GetRunning(ctx context.Context, agentID uuid.UUID) (*Container, error)

GetRunning implements ContainerManager. Returns (nil, nil) when no container exists for the agent — caller is expected to treat that as "nothing to do" rather than an error. Repopulates the in-memory cache when it finds a running container Airlock didn't previously know about (typical after an Airlock restart).

func (*DockerManager) InspectConnectorManifest added in v0.6.1

func (m *DockerManager) InspectConnectorManifest(ctx context.Context, binaryPath string) ([]byte, error)

InspectConnectorManifest executes only the mounted native binary. The read-only root, absent network, and empty environment keep source-controlled code away from build and runtime credentials while it declares its contract.

func (*DockerManager) InspectManifest added in v0.5.0

func (m *DockerManager) InspectManifest(ctx context.Context, imageRef string) (manifest []byte, retErr error)

InspectManifest runs a candidate image without runtime credentials or network access and returns its bounded stdout. The image entrypoint selects the one-shot behavior from AIRLOCK_AGENT_MODE.

func (*DockerManager) KillToolserver added in v0.1.6

func (m *DockerManager) KillToolserver(ctx context.Context, name string) error

KillToolserver force-removes an ephemeral toolserver container without waiting for graceful shutdown. RemoveOptions{Force: true} sends SIGKILL and removes in one call, so any in-flight tool execution dies immediately. Used by the build-cancellation path: graceful shutdown is 5+ seconds of dead air during which the toolserver keeps running its in-flight tool (e.g. a long `bash go build`) and emitting log lines — which makes the cancel feel like it didn't take. Idempotent: returns nil/NotFound if the container is already gone.

func (*DockerManager) LockSwap added in v0.4.0

func (m *DockerManager) LockSwap(agentID uuid.UUID) func()

LockSwap acquires the per-agent container-swap mutex. See the ContainerManager interface comment for the design rationale.

func (*DockerManager) MarkBusy added in v0.4.0

func (m *DockerManager) MarkBusy(agentID uuid.UUID)

MarkBusy records the start of an in-flight request to an agent container. While the in-flight count is above zero the idle reaper skips the container, so a run that outlasts idleTimeout is not stopped mid-execution. Pair every MarkBusy with exactly one MarkIdle.

func (*DockerManager) MarkIdle added in v0.4.0

func (m *DockerManager) MarkIdle(agentID uuid.UUID)

MarkIdle records the end of an in-flight request. It also refreshes the idle clock so the timeout is measured from the end of the last request rather than its start.

func (*DockerManager) PruneAgentResources

func (m *DockerManager) PruneAgentResources(ctx context.Context, validAgents map[string]AgentRuntimeSpec) []uuid.UUID

validAgents maps agent UUID string to its current runtime identity. Any container or UUID-tagged image owned by this instance (run.airlock.instance label) not matching this set is removed. Other instances' resources carry a different label value and are never listed here.

func (*DockerManager) ReapJSExecutors

func (m *DockerManager) ReapJSExecutors(ctx context.Context) error

ReapJSExecutors only removes this instance's containers whose exact owner lease is no longer live. Another replica's live execution is never reclaimed.

func (*DockerManager) RemoveImage

func (m *DockerManager) RemoveImage(ctx context.Context, imageRef string) error

RemoveImage removes a Docker image by reference.

func (*DockerManager) RunningAgents added in v0.4.0

func (m *DockerManager) RunningAgents(ctx context.Context, agentIDs []uuid.UUID) (map[uuid.UUID]bool, error)

RunningAgents implements ContainerManager. One ContainerList call, scoped to this instance via the ownership label, then matched back to the requested IDs via agentName. Builder/toolserver containers ("<instance>-agent-builder-*") also carry the label but never equal an agentName(id), so they fall out of the lookup harmlessly.

func (*DockerManager) StartAgent

func (m *DockerManager) StartAgent(ctx context.Context, opts AgentOpts) (*Container, error)

StartAgent implements ContainerManager.

func (*DockerManager) StartJSExecutor

func (m *DockerManager) StartJSExecutor(ctx context.Context, runID, token uuid.UUID) (io.ReadWriteCloser, error)

func (*DockerManager) StartTestJSExecutor

func (m *DockerManager) StartTestJSExecutor(ctx context.Context, buildID uuid.UUID) (io.ReadWriteCloser, error)

func (*DockerManager) StartToolserver

func (m *DockerManager) StartToolserver(ctx context.Context, opts ToolserverOpts) (*Container, error)

StartToolserver starts an ephemeral toolserver container for build operations. The container runs the toolserver binary with the workspace mounted. Returns the container with a WebSocket endpoint for remote tool execution.

func (*DockerManager) StopAgent

func (m *DockerManager) StopAgent(ctx context.Context, agentID uuid.UUID) error

StopAgent implements ContainerManager. Idempotent: if Docker stopped or removed the container out-of-band (crash, OOM, daemon restart, the idle reaper), the desired post-condition — container not running — is already met, so a not-found error is success. Without this a dead-but-status='active' agent could never be stopped and so never restarted (the UI only offers Stop while active).

func (*DockerManager) StopToolserver

func (m *DockerManager) StopToolserver(ctx context.Context, name string) error

StopToolserver stops and removes an ephemeral toolserver container.

type JSExecutorManager

type JSExecutorManager interface {
	StartJSExecutor(context.Context, uuid.UUID, uuid.UUID) (io.ReadWriteCloser, error)
}

JSExecutorManager is intentionally separate from reusable app containers. The stream is non-TTY stdin/stdout; Close must unblock both directions and destroy the realm. No endpoint, credentials, workspace, or network is exposed.

type RuntimeNetworkPolicy added in v0.4.1

type RuntimeNetworkPolicy interface {
	Internal(agentID uuid.UUID) bool
}

RuntimeNetworkPolicy selects the Docker network boundary for an agent runtime. The OSS server supplies DirectRuntimeNetworkPolicy; distributions that require stricter containment can inject their own policy.

type TestJSExecutorManager

type TestJSExecutorManager interface {
	StartTestJSExecutor(context.Context, uuid.UUID) (io.ReadWriteCloser, error)
}

TestJSExecutorManager allocates only build-scoped test realms, using the same isolated image and resource recipe as chat execution.

type ToolserverOpts

type ToolserverOpts struct {
	Image       string        // toolserver image (e.g., "agent-builder:v1.0.0")
	Mounts      []mount.Mount // workspace bind mounts
	WorkDir     string        // -space-dir value inside the container
	Env         []string      // additional environment variables
	LogCallback func(line string)
}

ToolserverOpts configures an ephemeral toolserver container for build operations.

Jump to

Keyboard shortcuts

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