Help us shape the future of Go! Take the 2026 Go Developer Survey

runner

package
v0.4.5 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package runner is the single internal command runner every tool invocation routes through. Phase 1 executes commands directly via os/exec with no sandboxing, so a later sandbox can be added behind this seam without changing callers.

Index

Constants

View Source
const FixedPATH = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"

Variables

View Source
var ErrPipelineUnsupported = errors.New("runner: pipeline execution unsupported")

ErrPipelineUnsupported reports that a runner cannot execute a set of specs as one pipeline. Only PreflightPipeline may return it; a caller that sees it runs the stages sequentially through Exec.

Functions

func FixedEnvironment

func FixedEnvironment(home, cwd, tmpDir, lookupPath string, assignments []string) ([]string, error)

func ResolveOnPath

func ResolveOnPath(name, lookupPath string) (string, error)

Types

type BoundedExecRunner

type BoundedExecRunner interface {
	ExecBounded(ctx context.Context, spec RunSpec, maxCapture int) (RunResult, error)
}

type DirectExecRunner

type DirectExecRunner struct{}

DirectExecRunner is the phase-1 Runner: it runs commands directly via os/exec with no sandboxing and no shell interpretation.

func (DirectExecRunner) Exec

Exec runs spec.Argv directly (no shell) and reports the outcome. Normal completion — including a non-zero exit status — returns a RunResult with the captured streams, the process exit code, an empty LaunchErrCategory, and a nil error. A launch failure before the process starts returns ExitCode -1, empty streams, and a LaunchErrCategory classified from the OS error. A non-nil error is returned only for invalid input, in which case the RunResult is unusable.

func (DirectExecRunner) ExecBounded

func (DirectExecRunner) ExecBounded(ctx context.Context, spec RunSpec, maxCapture int) (RunResult, error)

func (DirectExecRunner) NewInvocationID

func (DirectExecRunner) NewInvocationID() string

NewInvocationID returns a freshly minted UUIDv7 via ids.NewV7.

func (DirectExecRunner) Pipeline

func (DirectExecRunner) Pipeline(ctx context.Context, specs []RunSpec, maxCapture int) ([]PipelineResult, error)

Pipeline launches every spec as a concurrent stage joined by OS pipes. Capture goes through parent copiers and collectors rather than an opaque writer so a bound can be applied while the stream keeps being consumed — a child must never block on a full pipe. A stage that fails to launch is handled as a stage that exited immediately: its pipe ends close, so the upstream stage takes SIGPIPE and the downstream stage sees EOF on stdin and still runs. Every started process is waited on and every goroutine joined before returning, on every path.

func (DirectExecRunner) PreflightPipeline

func (DirectExecRunner) PreflightPipeline(_ context.Context, specs []RunSpec) error

PreflightPipeline validates every spec before any process starts. DirectExecRunner supports every pipeline, so it never returns ErrPipelineUnsupported.

type EnvAssignmentError

type EnvAssignmentError struct {
	Name string
}

func (*EnvAssignmentError) Error

func (e *EnvAssignmentError) Error() string

type ExecutableNotFoundError

type ExecutableNotFoundError struct {
	Name string
}

func (*ExecutableNotFoundError) Error

func (e *ExecutableNotFoundError) Error() string

type PipelineResult

type PipelineResult struct {
	// InvocationID echoes the stage's RunSpec.InvocationID verbatim for every produced result.
	InvocationID string
	// Stdout and Stderr are the first maxCapture bytes the parent read from that stream.
	Stdout []byte
	Stderr []byte
	// ExitCode is the process exit status, or -1 when the stage failed to launch or never ran.
	ExitCode int
	// Duration is that stage's own wall-clock time from launch to exit; stages overlap, so summing
	// these across a pipeline overstates the elapsed time.
	Duration time.Duration
	// LaunchErrCategory is set only for a stage that failed to launch, matching Exec.
	LaunchErrCategory fserrors.Category
	// StdoutTotal and StderrTotal count every byte the parent read from that stream, including the
	// bytes past maxCapture that were counted but not retained. A pipeline stage can be ended before
	// it finishes producing — a downstream exit closes the upstream read end so the producer takes
	// SIGPIPE — so a total counts what was captured, not what the stage would have gone on to emit.
	StdoutTotal int64
	StderrTotal int64
	// PipelineErrCategory is set only for a stage affected by a post-launch copier, collector,
	// internal, or cancellation failure, which Pipeline also reports as its returned error.
	PipelineErrCategory PipelineStageFailure
}

PipelineResult is the outcome of one stage of a pipeline.

type PipelineRunner

type PipelineRunner interface {
	// PreflightPipeline validates every spec and decides capability support before any process
	// starts. It returns ErrPipelineUnsupported only when this runner cannot run a pipeline at all,
	// and any other non-nil error means nothing was started.
	PreflightPipeline(ctx context.Context, specs []RunSpec) error
	// Pipeline runs the ordered specs as one pipeline after a successful preflight, bounding each
	// captured stream to maxCapture bytes. It never returns ErrPipelineUnsupported. A non-nil error
	// is returned only once there is one PipelineResult per input spec and every started process,
	// copier, and collector has been joined.
	Pipeline(ctx context.Context, specs []RunSpec, maxCapture int) ([]PipelineResult, error)
}

PipelineRunner is the optional capability a Runner may also implement to run several specs as one concurrent pipeline over OS pipes. It is discovered by type assertion rather than added to Runner, so a runner that executes single commands needs no multi-process orchestration.

Only specs[0].Stdin is honored: every later stage takes stdin from the upstream stage's pipe and any Stdin set on it is ignored.

type PipelineStageFailure

type PipelineStageFailure string

PipelineStageFailure classifies a pipeline failure that happened after the stages were launched.

const (
	PipelineFailureCopy     PipelineStageFailure = "copy_failed"
	PipelineFailureCanceled PipelineStageFailure = "canceled"
	PipelineFailureInternal PipelineStageFailure = "internal"
)

type RunResult

type RunResult struct {
	// InvocationID echoes RunSpec.InvocationID verbatim for every produced result, so the paired
	// tool_exec_start/tool_exec_end events share one id.
	InvocationID string
	// Stdout and Stderr are empty on a launch failure because the process never ran.
	Stdout []byte
	Stderr []byte
	// ExitCode is the process exit status, or -1 when the process failed to launch.
	ExitCode int
	// Duration is the wall-clock time spent in cmd.Run.
	Duration time.Duration
	// LaunchErrCategory is set only when the process failed to launch before starting; it is empty
	// on normal completion, including a non-zero exit.
	LaunchErrCategory fserrors.Category
	StdoutTotal       int64
	StderrTotal       int64
}

RunResult is the outcome of a completed invocation, including launch failures. A non-nil Exec error is reserved for invalid input or internal failures where no reliable result exists; a non-zero process exit or a launch failure is reported here, not as an error.

type RunSpec

type RunSpec struct {
	// InvocationID is the UUIDv7 the caller minted via Runner.NewInvocationID at invocation
	// start — the single source of the paired tool_exec_start/tool_exec_end id.
	// Exec validates it and echoes it verbatim into RunResult.InvocationID.
	InvocationID string
	// Argv is the command and its arguments; Argv[0] is the binary, run directly with no shell
	// interpretation. It must be non-empty.
	Argv []string
	// Cwd, when non-empty, sets the process working directory (exec.Cmd.Dir). Callers own path
	// validation and resolution; the runner passes it through unchanged.
	Cwd string
	// Env is an optional complete environment block: nil inherits the parent process environment,
	// non-nil is passed to exec.Cmd.Env as-is.
	Env         []string
	Assignments []string
	// Stdin is fed to the process standard input; nil or empty means the process gets no input.
	Stdin                []byte
	ExceptionalAuthority string
}

RunSpec is the caller-supplied input for one command invocation.

type Runner

type Runner interface {
	// NewInvocationID mints a fresh UUIDv7 invocation id. The caller calls this at invocation
	// start, emits tool_exec_start with it, then passes it back in RunSpec.InvocationID.
	NewInvocationID() string
	// Exec runs spec directly with no shell interpretation and returns a RunResult. It returns a
	// non-nil error only for invalid input (empty or malformed InvocationID, empty Argv) or
	// internal failures; non-zero exits and launch failures are carried on RunResult.
	Exec(ctx context.Context, spec RunSpec) (RunResult, error)
}

Runner is the shared command-runner seam every tool invocation path depends on.

Jump to

Keyboard shortcuts

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