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
- Variables
- func FixedEnvironment(home, cwd, tmpDir, lookupPath string, assignments []string) ([]string, error)
- func ResolveOnPath(name, lookupPath string) (string, error)
- type BoundedExecRunner
- type DirectExecRunner
- func (DirectExecRunner) Exec(ctx context.Context, spec RunSpec) (RunResult, error)
- func (DirectExecRunner) ExecBounded(ctx context.Context, spec RunSpec, maxCapture int) (RunResult, error)
- func (DirectExecRunner) NewInvocationID() string
- func (DirectExecRunner) Pipeline(ctx context.Context, specs []RunSpec, maxCapture int) ([]PipelineResult, error)
- func (DirectExecRunner) PreflightPipeline(_ context.Context, specs []RunSpec) error
- type EnvAssignmentError
- type ExecutableNotFoundError
- type PipelineResult
- type PipelineRunner
- type PipelineStageFailure
- type RunResult
- type RunSpec
- type Runner
Constants ¶
const FixedPATH = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
Variables ¶
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 ResolveOnPath ¶
Types ¶
type BoundedExecRunner ¶
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) 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.