Documentation
¶
Overview ¶
Package process provides the seam between agentboot and the OS process that implements an agent (e.g. the `claude` CLI binary).
Production code uses OSExecFactory, which wraps os/exec. Tests use FakeFactory to substitute the binary with a scripted in-memory process, keeping the rest of the agent stack (driver, decoder, runner) on the real code path.
Index ¶
- Variables
- type Factory
- type FakeFactory
- type FakeHandle
- func (h *FakeHandle) Done() <-chan struct{}
- func (h *FakeHandle) FinishOutput()
- func (h *FakeHandle) Kill() error
- func (h *FakeHandle) SignalExit(err error)
- func (h *FakeHandle) Spec() LaunchSpec
- func (h *FakeHandle) Stdin() io.WriteCloser
- func (h *FakeHandle) Stdout() io.ReadCloser
- func (h *FakeHandle) Wait() error
- func (h *FakeHandle) WriteOutput(p []byte) (int, error)
- type Handle
- type LaunchSpec
- type OSExecFactory
Constants ¶
This section is empty.
Variables ¶
var ErrKilled = errors.New("process killed")
ErrKilled is the synthetic Wait error reported after Kill.
Functions ¶
This section is empty.
Types ¶
type Factory ¶
type Factory interface {
Start(ctx context.Context, spec LaunchSpec) (Handle, error)
}
Factory starts agent processes.
type FakeFactory ¶
type FakeFactory struct {
// OnStart, if non-nil, is invoked synchronously inside Start with the
// freshly-constructed FakeHandle. Use it to install scripted I/O.
OnStart func(context.Context, LaunchSpec, *FakeHandle)
// contains filtered or unexported fields
}
FakeFactory is the test Factory. It never spawns a real process; instead each call to Start produces a FakeHandle whose stdin/stdout are wired to in-memory pipes. Tests script the handle's behavior either via [OnStart] or by calling helpers on the returned FakeHandle directly.
func NewFakeFactory ¶
func NewFakeFactory() *FakeFactory
NewFakeFactory returns an empty FakeFactory. Configure OnStart before passing it to a runner.
func (*FakeFactory) Handles ¶
func (f *FakeFactory) Handles() []*FakeHandle
Handles returns every FakeHandle produced by this factory, in order.
func (*FakeFactory) Start ¶
func (f *FakeFactory) Start(ctx context.Context, spec LaunchSpec) (Handle, error)
func (*FakeFactory) Starts ¶
func (f *FakeFactory) Starts() []LaunchSpec
Starts returns the LaunchSpec from every Start call, in order.
type FakeHandle ¶
type FakeHandle struct {
// StdinR exposes the read end of the stdin pipe so tests can observe
// what the system under test wrote to the child.
StdinR *io.PipeReader
// contains filtered or unexported fields
}
FakeHandle is the Handle returned by FakeFactory.
Its Stdin and Stdout are connected to in-memory pipes:
- Bytes the system under test writes to Stdin can be read from StdinR.
- Bytes pushed via WriteOutput appear on Stdout.
A FakeHandle starts in the running state. Call SignalExit (with optional error) or Kill to transition it to exited.
func (*FakeHandle) Done ¶
func (h *FakeHandle) Done() <-chan struct{}
func (*FakeHandle) FinishOutput ¶
func (h *FakeHandle) FinishOutput()
FinishOutput closes the Stdout pipe, signaling EOF to the reader. Idempotent.
func (*FakeHandle) Kill ¶
func (h *FakeHandle) Kill() error
Kill closes both pipes and signals exit with a synthetic "killed" error. Idempotent.
func (*FakeHandle) SignalExit ¶
func (h *FakeHandle) SignalExit(err error)
SignalExit transitions the handle to the exited state with the given error. Subsequent Wait calls return err. Idempotent: only the first call's error is recorded.
func (*FakeHandle) Spec ¶
func (h *FakeHandle) Spec() LaunchSpec
Spec returns the LaunchSpec used to construct this handle.
func (*FakeHandle) Stdin ¶
func (h *FakeHandle) Stdin() io.WriteCloser
func (*FakeHandle) Stdout ¶
func (h *FakeHandle) Stdout() io.ReadCloser
func (*FakeHandle) Wait ¶
func (h *FakeHandle) Wait() error
func (*FakeHandle) WriteOutput ¶
func (h *FakeHandle) WriteOutput(p []byte) (int, error)
WriteOutput pushes bytes to the handle's Stdout. Tests use this to emit scripted events. Safe to call concurrently with reads from Stdout.
type Handle ¶
type Handle interface {
Stdin() io.WriteCloser
Stdout() io.ReadCloser
Wait() error
Kill() error
Done() <-chan struct{}
}
Handle is a running process with attached stdin/stdout pipes.
Lifecycle invariants:
- Stdin and Stdout are valid until Wait returns.
- Done is closed after the process has exited; Wait then returns immediately with the exit error.
- Kill is idempotent and safe to call concurrently with Wait.
type LaunchSpec ¶
LaunchSpec describes how to start an agent process.
It intentionally mirrors the subset of os/exec.Cmd that an agent driver needs to populate, so that drivers can be unit-tested against any Factory.
type OSExecFactory ¶
type OSExecFactory struct {
// Stderr, if non-nil, receives the child process's stderr stream.
// Defaults to os.Stderr.
Stderr io.Writer
}
OSExecFactory is the production Factory backed by os/exec.
func NewOSExecFactory ¶
func NewOSExecFactory() *OSExecFactory
NewOSExecFactory returns a Factory wired to os.Stderr.
func (*OSExecFactory) Start ¶
func (f *OSExecFactory) Start(ctx context.Context, spec LaunchSpec) (Handle, error)