commands

package
v1.0.0-rc2 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: AGPL-3.0 Imports: 40 Imported by: 0

Documentation

Index

Constants

View Source
const (

	// DefaultAuditMaxEntries bounds one snapshot walk. A work dir larger than
	// this is not diffed at all — see TakeSnapshot.
	DefaultAuditMaxEntries = 20000
)

Variables

View Source
var DefaultAuditIgnore = []string{".git", "node_modules", ".cairn", "__pycache__", ".venv"}

DefaultAuditIgnore are the path segments a snapshot never walks: the directories where a build or a checkout produces thousands of changes that say nothing about what the agent was doing.

Functions

func AuditDigest

func AuditDigest(content []byte) string

AuditDigest is the content hash carried by a write observation. It is what lets a consumer tell a rewrite that changed nothing from one that changed everything, without storing either version.

func BuildPlan added in v0.4.0

func BuildPlan(plan capability.Plan, deps *Deps, reg *CommandRegistry)

BuildPlan is the only factory assembly path. Factory membership is keyed by capability identity; groups are selection metadata owned by descriptors.

func JoinCommandLine added in v0.4.0

func JoinCommandLine(name string, args []string) string

JoinCommandLine builds a command line that SplitCommandLine can losslessly parse. It is intended for trusted internal callers that already have args.

func Provide added in v0.4.0

func Provide[T any](d *Deps, key deps.Key[T], value T)

Provide stores a typed dependency, allocating the bag on first use so a literal-constructed Deps cannot drop it silently.

func RegisterFactory

func RegisterFactory(f Factory)

func SplitCommandLine

func SplitCommandLine(input string) ([]string, error)

Types

type AuditChange

type AuditChange struct {
	Path string
	Op   filepb.AccessOp
	Size int64
}

AuditChange is one difference between two snapshots.

func DiffSnapshots

func DiffSnapshots(before, after AuditSnapshot) []AuditChange

DiffSnapshots reports what happened to the work dir between two snapshots, sorted by path so the same pair always produces the same sequence.

A file present in both is reported only when its size or modification time moved. That misses a rewrite that restored the previous bytes within the filesystem's timestamp resolution — the price of not hashing every file in the tree twice per command.

type AuditOptions

type AuditOptions struct {
	Enabled    bool
	Ignore     []string
	MaxEntries int
}

AuditOptions is the snapshot and reporting policy. A peer sets it at runtime through the file namespace's Configure.

type AuditSnapshot

type AuditSnapshot map[string]auditEntry

AuditSnapshot is a work dir's regular files at one moment, keyed by absolute path.

func TakeSnapshot

func TakeSnapshot(root string, options AuditOptions) (AuditSnapshot, error)

TakeSnapshot walks root and records every regular file it is willing to look at.

It returns an error rather than a partial listing when the tree exceeds MaxEntries: a diff against a truncated snapshot invents a deletion for every file that fell off the end, and a wrong audit trail is worse than an absent one. The caller reports the refusal instead.

type BashArgs

type BashArgs struct {
	Command string `` /* 176-byte string literal not displayed */
	Wait    int    `` /* 217-byte string literal not displayed */
	Timeout int    `` /* 245-byte string literal not displayed */
	// contains filtered or unexported fields
}

func (BashArgs) TimeoutSpecified

func (a BashArgs) TimeoutSpecified() bool

func (*BashArgs) UnmarshalJSON

func (a *BashArgs) UnmarshalJSON(data []byte) error

UnmarshalJSON preserves the distinction between an omitted timeout (use the tool default) and an explicit timeout of zero (no command deadline).

func (BashArgs) Validate

func (a BashArgs) Validate() error

type BashExecOptions added in v0.4.0

type BashExecOptions struct {
	Name       string
	WorkDir    string
	Env        map[string]string
	Timeout    time.Duration
	TimeoutSet bool
	OnOutput   func([]byte)
	Stdin      io.Reader
	Stdout     io.Writer
	Stderr     io.Writer
}

BashExecOptions controls one foreground execution without mutating the BashTool defaults. Runner/WebAgent transports use this entry point while the agent-facing Execute method applies the explicit wait/background contract.

type BashTool

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

func NewBashTool

func NewBashTool(workDir string, timeout int) *BashTool

func (*BashTool) Close

func (t *BashTool) Close()

func (*BashTool) Definition

func (t *BashTool) Definition() *coretool.Definition

func (*BashTool) Description

func (t *BashTool) Description() string

func (*BashTool) Execute

func (t *BashTool) Execute(ctx context.Context, arguments string) (*coretool.Result, error)

func (*BashTool) Manager

func (t *BashTool) Manager() *tmux.Manager

func (*BashTool) Name

func (t *BashTool) Name() string

func (*BashTool) RunForeground added in v0.4.0

func (t *BashTool) RunForeground(ctx context.Context, command string, options BashExecOptions) (*Execution, error)

RunForeground executes command through the same tmux/registered-command router used by the bash agent tool, streams raw output, and waits for the final session state. Non-zero exits are represented by Info.ExitCode rather than returned as transport errors.

func (*BashTool) RunForegroundTool added in v0.4.0

func (t *BashTool) RunForegroundTool(ctx context.Context, command string, options BashExecOptions) (*coretool.Result, error)

RunForegroundTool executes a command in the foreground and returns the collected ToolResult (bounded text and media), streaming raw output through options.OnOutput. Transports that must remain foreground (AOP tool.call) use this instead of Execute.

func (*BashTool) SetCommandNames

func (t *BashTool) SetCommandNames(fn func() []string)

func (*BashTool) SetCommandResolver added in v0.4.0

func (t *BashTool) SetCommandResolver(fn func(string) (Command, bool))

func (*BashTool) SetEgressResolver

func (t *BashTool) SetEgressResolver(fn func(callID string) (string, string))

func (*BashTool) SetScannerProxy

func (t *BashTool) SetScannerProxy(proxy string)

func (*BashTool) SetScannerProxyCA

func (t *BashTool) SetScannerProxyCA(caPath string)

func (*BashTool) Start added in v0.4.0

func (t *BashTool) Start(ctx context.Context, command string, options BashExecOptions) (*Execution, error)

Start resolves command through the built-in registry or the system shell and always returns an Execution backed by one PTY session.

func (*BashTool) WithAudit

func (t *BashTool) WithAudit(audit *FileAudit) *BashTool

WithAudit attaches the file-access audit trail. Shell commands are the one place the runtime cannot observe a file access directly, so what this buys is the work dir diff taken around every execution.

func (*BashTool) WithEgressResolver

func (t *BashTool) WithEgressResolver(fn func(callID string) (string, string)) *BashTool

func (*BashTool) WithScannerProxy

func (t *BashTool) WithScannerProxy(proxy string) *BashTool

func (*BashTool) WithScannerProxyCA

func (t *BashTool) WithScannerProxyCA(caPath string) *BashTool

type Command

type Command struct {
	Name           string
	Usage          string
	QuickReference string
	// DescriptionPath points at the OKF markdown concept whose frontmatter
	// description is advertised to management and composer surfaces.
	DescriptionPath string
	Run             func(context.Context, *Execution) (any, error)
	SetProxy        func(string)
	GetProxy        func() string
	SetDefaultSpace func(string)
	Close           func()
}

Command describes one built-in command accepted by the Bash tool. Runtime state belongs to Execution; command-specific dependencies are captured by Run at construction time.

func NewTmuxCommand

func NewTmuxCommand(bash *BashTool) Command

type CommandRegistry

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

func NewRegistry

func NewRegistry() *CommandRegistry

func (*CommandRegistry) All

func (r *CommandRegistry) All() []Command

func (*CommandRegistry) ExecuteBashForeground

func (r *CommandRegistry) ExecuteBashForeground(ctx context.Context, command string, options BashExecOptions) (*tool.Result, error)

ExecuteBashForeground runs the transport-facing Bash path through the same panic boundary as ordinary tool execution.

func (*CommandRegistry) ExecuteTool

func (r *CommandRegistry) ExecuteTool(ctx context.Context, name, arguments string) (*tool.Result, error)

func (*CommandRegistry) Get

func (r *CommandRegistry) Get(name string) (Command, bool)

func (*CommandRegistry) GetTool

func (r *CommandRegistry) GetTool(name string) (tool.Tool, bool)

func (*CommandRegistry) GroupNames

func (r *CommandRegistry) GroupNames(group string) []string

func (*CommandRegistry) Has

func (r *CommandRegistry) Has(name string) bool

func (*CommandRegistry) Names

func (r *CommandRegistry) Names() []string

func (*CommandRegistry) Register

func (r *CommandRegistry) Register(cmd Command, group string)

func (*CommandRegistry) RegisterTool

func (r *CommandRegistry) RegisterTool(t tool.Tool)

func (*CommandRegistry) Run added in v0.4.0

func (r *CommandRegistry) Run(ctx context.Context, tokens []string, parent *Execution) (details any, err error)

Run executes a nested built-in command inside an existing Execution. The child shares the outer PTY session and file descriptors; it does not create a second lifecycle or an ID-less execution.

func (*CommandRegistry) SetLogger added in v0.3.0

func (r *CommandRegistry) SetLogger(logger telemetry.Logger)

func (*CommandRegistry) ToolDefinitions

func (r *CommandRegistry) ToolDefinitions() []*tool.Definition

func (*CommandRegistry) Tools

func (r *CommandRegistry) Tools() []tool.Tool

func (*CommandRegistry) UsageDocs

func (r *CommandRegistry) UsageDocs() string

type Deps

type Deps struct {
	*deps.Bag

	WorkDir     string
	BashTimeout int
	SkillStore  SkillSource
	RunnerMode  bool

	Provider       provider.Provider
	ScannerProxy   string
	ScannerProxyCA string // CA PEM path for the MITM hub; injected so children trust intercepted HTTPS
	// EgressResolver, when set, supersedes ScannerProxy/ScannerProxyCA per
	// execution: given the current tool-call id it returns the proxy URL (with
	// the id as the proxy username, so captured flows attribute to it) and the
	// CA path from live hub state (empty while the hub is not intercepting).
	EgressResolver    func(callID string) (proxyURL, caPath string)
	Logger            telemetry.Logger
	NodeName          string
	NodeMeta          map[string]any
	TavilyKeys        string // comma-separated Tavily API keys
	PlaywrightSession string
	Events            aop.EventEmitter
	Hooks             *hooks.Registry
	// FileAudit collects what the file tools and shell executions did to the
	// filesystem. Nil leaves them unobserved.
	FileAudit *FileAudit
}

Deps carries everything a Factory may need. Values whose type pkg/commands must not import (scanner engines, resources, IOA client, scan options) travel in the Bag under keys owned by their own package.

func (*Deps) GetLogger added in v0.2.7

func (d *Deps) GetLogger() telemetry.Logger

func (*Deps) Skip added in v0.4.0

func (d *Deps) Skip(id, dep string)

Skip reports that a factory bailed out because a dependency is missing. It exists because these sites used to return silently, leaving the tool absent from the registry with nothing in the log to explain it.

type EditPatch

type EditPatch struct {
	OldText    string `` /* 141-byte string literal not displayed */
	NewText    string `json:"new_text"                jsonschema:"description=Replacement text for this edit."`
	ReplaceAll bool   `json:"replace_all,omitempty"   jsonschema:"description=Replace all occurrences of old_text instead of requiring uniqueness."`
}

type Execution added in v0.4.0

type Execution struct {
	ID      string
	Command string
	Args    []string
	Dir     string
	Env     []string

	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer

	State     tmux.State
	ExitCode  int
	StartedAt time.Time
	EndedAt   time.Time
	KillCause string
	Details   any
	// contains filtered or unexported fields
}

Execution is one shell or built-in command invocation. Its ID is always the ID of the underlying PTY session, so existing tmux attach/read/write/kill operations continue to address the same runtime object.

func (*Execution) Duration added in v0.4.0

func (e *Execution) Duration() time.Duration

func (*Execution) Kill added in v0.4.0

func (e *Execution) Kill() error

func (*Execution) Wait added in v0.4.0

func (e *Execution) Wait(ctx context.Context) error

Wait waits for the PTY session. Canceling the wait also kills the session, matching the previous foreground Bash execution behavior.

type Factory

type Factory struct {
	Capability capability.ID
	Build      func(deps *Deps, reg *CommandRegistry)
}

type FileAudit

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

FileAudit is the runtime's file-access audit trail: what the agent read, what it wrote, and what its shell commands left behind.

An agent that operates on a machine is answerable for what it touched there, and a tool call alone does not say it. This type is where the tools in this package report that, and it publishes each observation as an aop.file.Access so the file namespace answers both "operate on this file" and "who touched it" — one mechanism rather than two.

Recording is off the critical path by construction: it is non-blocking and lossy under pressure. A file access must never be slower because someone is watching, so a full queue drops the observation and counts it.

Coverage is honest rather than complete. Tool-level records are exact. Shell executions are covered by diffing the work dir around them (Around), which sees every write but no read at all — an unmodified read leaves nothing behind to find. That difference is on the wire as AccessSource.

A nil *FileAudit is a working no-op, so a runtime that never wired one up costs nothing and no call site needs a nil check.

func NewFileAudit

func NewFileAudit() *FileAudit

NewFileAudit starts an audit trail. Nothing is published until something subscribes, and subscribers see every observation recorded after they attach.

func (*FileAudit) Around

func (a *FileAudit) Around(ctx context.Context, workDir string, fn func() error) error

Around brackets fn with two snapshots of workDir and records the difference as SNAPSHOT observations attributed to the invocation in ctx.

What it cannot do is separate the command's own writes from anything else that changed the work dir while it ran — a detached session, a background build — which is exactly what AccessSource SNAPSHOT tells a consumer.

func (*FileAudit) Close

func (a *FileAudit) Close()

Close stops the publisher and waits for queued observations to drain.

func (*FileAudit) Configure

func (a *FileAudit) Configure(config *filepb.WatchConfig)

Configure applies a peer's watch policy. A nil config restores the defaults, which is what a peer that asked to observe with no opinion should get.

func (*FileAudit) Enabled

func (a *FileAudit) Enabled() bool

Enabled reports whether observations are currently collected.

func (*FileAudit) Options

func (a *FileAudit) Options() AuditOptions

Options returns the active policy. Callers about to do expensive work — a snapshot walk above all — check Enabled first.

func (*FileAudit) Record

func (a *FileAudit) Record(ctx context.Context, access *filepb.Access)

Record publishes one observation. The caller supplies what it knows; identity, timing and the invocation context are filled in here so no call site has to remember them. It never blocks.

func (*FileAudit) RecordFile

func (a *FileAudit) RecordFile(ctx context.Context, op filepb.AccessOp, path string, access *filepb.Access)

RecordFile reports one exact, tool-level access. The size is read from the file unless the caller already knows it.

func (*FileAudit) State

func (a *FileAudit) State() *filepb.WatchState

State is the reply a peer gets to Configure. Dropped rides along so a consumer can say the trail has a hole in it rather than presenting a short history as a complete one.

func (*FileAudit) Subscribe

func (a *FileAudit) Subscribe(handler func(*filepb.Access)) func()

Subscribe delivers every subsequent observation to handler, returning the detach function. Handlers run on the audit's own goroutine, never on the one that performed the file access.

type GlobArgs

type GlobArgs struct {
	Pattern string `` /* 143-byte string literal not displayed */
	Path    string `json:"path,omitempty" jsonschema:"description=Base directory for the search (default: working directory)"`
}

type GlobTool

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

func NewGlobTool

func NewGlobTool(workDir string, globbers ...VirtualGlobber) *GlobTool

func (*GlobTool) Definition

func (t *GlobTool) Definition() *coretool.Definition

func (*GlobTool) Description

func (t *GlobTool) Description() string

func (*GlobTool) Execute

func (t *GlobTool) Execute(ctx context.Context, arguments string) (*coretool.Result, error)

func (*GlobTool) Name

func (t *GlobTool) Name() string

type ListArgs added in v0.4.0

type ListArgs struct {
	Path string `json:"path,omitempty" jsonschema:"description=Directory path to list (absolute or relative to working directory; default: .)"`
}

type ListEntry added in v0.4.0

type ListEntry struct {
	Name        string `json:"name"`
	IsDirectory bool   `json:"isDirectory"`
	Size        int64  `json:"size"`
}

type ListResult added in v0.4.0

type ListResult struct {
	Path      string      `json:"path"`
	Entries   []ListEntry `json:"entries"`
	Truncated bool        `json:"truncated,omitempty"`
}

type ListTool added in v0.4.0

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

ListTool lists directory entries through the host filesystem API.

func NewListTool added in v0.4.0

func NewListTool(workDir string) *ListTool

func (*ListTool) Definition added in v0.4.0

func (t *ListTool) Definition() *coretool.Definition

func (*ListTool) Description added in v0.4.0

func (t *ListTool) Description() string

func (*ListTool) Execute added in v0.4.0

func (t *ListTool) Execute(ctx context.Context, arguments string) (*coretool.Result, error)

func (*ListTool) Name added in v0.4.0

func (t *ListTool) Name() string

type LoggerAware added in v0.3.0

type LoggerAware interface {
	InitLogger(telemetry.Logger)
}

type ReadArgs

type ReadArgs struct {
	Path   string `json:"path"            jsonschema:"description=File path to read (absolute or relative to working directory)"`
	Offset int    `json:"offset,omitempty" jsonschema:"description=1-indexed line number to start reading from (default: 1)"`
	Limit  int    `json:"limit,omitempty"  jsonschema:"description=Maximum number of lines to read (default: 2000)"`
}

type ReadTool

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

func NewReadTool

func NewReadTool(workDir string, readers ...VirtualFileReader) *ReadTool

func (*ReadTool) Definition

func (t *ReadTool) Definition() *coretool.Definition

func (*ReadTool) Description

func (t *ReadTool) Description() string

func (*ReadTool) Execute

func (t *ReadTool) Execute(ctx context.Context, arguments string) (*coretool.Result, error)

func (*ReadTool) Name

func (t *ReadTool) Name() string

func (*ReadTool) WithAudit

func (t *ReadTool) WithAudit(recorder *FileAudit) *ReadTool

WithAudit attaches the file-access audit trail. A nil recorder leaves the tool unobserved, which is what a runtime that never wired one up gets.

type SkillSource added in v0.4.0

type SkillSource interface {
	VirtualFileReader
	VirtualGlobber
}

SkillSource is the slice of skills.Store the built-in tools need; declaring it here keeps pkg/commands from importing the skill store itself.

type VirtualFileReader

type VirtualFileReader interface {
	ReadVirtual(path string) (content string, handled bool, err error)
}

type VirtualGlobber

type VirtualGlobber interface {
	GlobVirtual(pattern string) ([]string, bool)
}

type WriteArgs

type WriteArgs struct {
	Path    string      `json:"path"             jsonschema:"description=File path to write or edit (absolute or relative to working directory)"`
	Content string      `json:"content,omitempty" jsonschema:"description=Full file content for write mode. Ignored when edits is provided."`
	Edits   []EditPatch `` /* 166-byte string literal not displayed */
}

type WriteTool

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

func NewWriteTool

func NewWriteTool(workDir string) *WriteTool

func (*WriteTool) Definition

func (t *WriteTool) Definition() *coretool.Definition

func (*WriteTool) Description

func (t *WriteTool) Description() string

func (*WriteTool) Execute

func (t *WriteTool) Execute(ctx context.Context, arguments string) (*coretool.Result, error)

func (*WriteTool) Name

func (t *WriteTool) Name() string

func (*WriteTool) WithAudit

func (t *WriteTool) WithAudit(recorder *FileAudit) *WriteTool

WithAudit attaches the file-access audit trail. A nil recorder leaves the tool unobserved.

Jump to

Keyboard shortcuts

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