shell

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package shell exposes a single LLM-callable shell tool plus a small Executor SPI. The package itself does not pick where commands run — local, sandboxed, or remote backends each implement Executor and plug in via NewTool.

The local executor (NewLocalExecutor) is the reference impl and covers the common case (run on the same host as the agent).

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrEmptyCommand  = errors.New("shell: command must not be empty")
	ErrInvalidConfig = errors.New("shell: executor configuration is invalid")
	ErrInvalidInput  = errors.New("shell: input is invalid")
	ErrNilExecutor   = errors.New("shell: executor must not be nil")
)

Functions

This section is empty.

Types

type Config added in v0.20.0

type Config struct {
	Executor Executor
	// Description replaces the neutral default with the host's actual shell
	// semantics and tool-use policy. Empty selects the neutral description.
	Description string
}

Config binds execution authority and the model-visible description.

type Executor

type Executor interface {
	// Run executes exactly one command within the executor's frozen authority.
	// It honors ctx and Input.Timeout, returns non-zero exit status as Output
	// rather than error, and reserves error for spawn, I/O, or collection failure.
	// On error, Output retains all available execution facts. Neither an error
	// nor missing output proves that the command had no side effects.
	Run(ctx context.Context, in Input) (Output, error)
}

Executor is the authority boundary behind the model-facing shell tool. The concrete implementation owns process creation, working-directory policy, environment exposure, output capture, termination, and platform semantics.

type Input

type Input struct {
	// Cmd is the shell command line. Required.
	Cmd string

	// Timeout bounds the run. 0 = no timeout; ctx cancellation still
	// applies.
	Timeout time.Duration
}

Input captures everything an executor needs to launch a single command. Only Cmd is required.

type LocalConfig added in v0.13.0

type LocalConfig struct {
	Directory string
	Shell     string
	// MaxBytesPerStream caps captured stdout and stderr independently.
	// Zero selects 30 KiB per stream; truncation markers are additional bytes.
	MaxBytesPerStream int
}

LocalConfig makes the local process authority visible at construction. The directory controls relative-path resolution but is not a filesystem jail; callers that need confinement must supply an OS sandbox or container.

type LocalExecutor

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

LocalExecutor runs commands on the local host through one immutable construction-time configuration. Each call owns a Unix process group and kills that group on cancellation or return, including background children. A command that deliberately creates another session requires a host sandbox to keep its lifetime confined; this executor is not a process sandbox.

func NewLocalExecutor

func NewLocalExecutor(config LocalConfig) (*LocalExecutor, error)

NewLocalExecutor resolves the working directory to an absolute path and freezes it, so a command cannot relocate the executor by changing process state. The output cap is set here because a command that writes without bound would otherwise be truncated only after the memory was already spent.

func (*LocalExecutor) Run

func (l *LocalExecutor) Run(ctx context.Context, in Input) (Output, error)

type Output

type Output struct {
	Stdout   []byte
	Stderr   []byte
	ExitCode int
	Duration time.Duration

	// CancellationObserved reports that cancellation or timeout was observed
	// before returning; it does not establish why the process exited.
	CancellationObserved bool
}

Output is what every executor returns. A non-zero ExitCode is not an error — only spawn/I/O failures populate the error return.

type Request

type Request struct {
	Command   string `` /* 128-byte string literal not displayed */
	TimeoutMS int    `` /* 169-byte string literal not displayed */
}

Request is the LLM-facing argument shape. It is a strict subset of Input — environment, working directory, and streaming are executor-side concerns, not LLM knobs.

type Response

type Response struct {
	Stdout               string `json:"stdout"`
	Stderr               string `json:"stderr"`
	ExitCode             int    `json:"exit_code"`
	CancellationObserved bool   `json:"cancellation_observed,omitempty"`
	Duration             string `json:"duration"`
}

Response is the LLM-facing return shape. Stdout/stderr are strings (not []byte) because every consumer is a chat model.

type Tool

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

Tool exposes shell execution to a model. It holds an Executor rather than running commands itself so the dangerous half — where a command runs, under what shell, with what limits — is chosen by the host at construction and cannot be influenced by the model's arguments.

func NewTool

func NewTool(config Config) (*Tool, error)

NewTool requires an executor because there is no safe default for running arbitrary commands; a package-level fallback would let a caller obtain shell access without ever stating where it should run.

func (*Tool) Call

func (t *Tool) Call(ctx context.Context, invocation toolcontract.Invocation) (chat.ToolOutput, error)

func (*Tool) Definition

func (t *Tool) Definition() chat.ToolDefinition

func (*Tool) Unwrap added in v0.19.0

func (t *Tool) Unwrap() toolcontract.Tool

Unwrap exposes the typed input contract through tool decorators.

Jump to

Keyboard shortcuts

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