Documentation
¶
Overview ¶
Package agentwire drives vendor coding-agent CLIs as child processes over their structured protocols: Claude stream-json, Codex app-server, OpenCode serve, ACP (Copilot, Cursor, Gemini, omp, grok) and pi RPC.
One event model covers every harness. The library knows vendors; it does not know consumers. Vendor flags, env vars, config formats, protocol quirks and version floors live here. Product homes, hooks, memory, secret env, job semantics and UI text belong to the caller.
There is no global state: every cache, pool and ledger hangs off one Runtime, and two runtimes in one process share nothing.
The wire is Go-native. Official vendor SDKs are the reference implementation and the fixture oracle at build and test time only; they are never a runtime dependency.
Index ¶
- Constants
- Variables
- func ClaudeMCPConfig(servers []MCPServer) map[string]any
- func CodexMCPArgs(servers []MCPServer) []string
- func CodexMCPEnv(servers []MCPServer) (map[string]string, error)
- func CredentialFiles(h Harness) []string
- func DefaultEffort(h Harness) string
- func DefaultHome(h Harness) string
- func DropKeys(format string, data []byte, keys []string) ([]byte, error)
- func Efforts(h Harness, model string) []string
- func HomeMCPFile(h Harness) string
- func HomeTrustFile(h Harness) string
- func LoginCommand(h Harness) []string
- func LoginCommandFor(h Harness, o LoginOptions) ([]string, error)
- func LoginDir(h Harness) string
- func LoginEnv(h Harness, home string) map[string]string
- func LoginTokenEnv(h Harness) string
- func LogoutCommand(h Harness) []string
- func MergeKeys(format string, own, user []byte, keys, skip []string) ([]byte, error)
- func ModelArgs(h Harness, model, effort string) []string
- func OpenCodeConfigContent(servers []MCPServer) (string, error)
- func SessionFiles(h Harness, home, id string) []string
- func SetHomeMCP(h Harness, data []byte, servers []MCPServer) ([]byte, error)
- func SetHomeTrust(h Harness, data []byte, dirs []string) ([]byte, error)
- func SetKeys(path string, data []byte, keys []HomeKey) ([]byte, error)
- func SharedLoginEnv(h Harness) map[string]string
- func SharesUserHome(h Harness) bool
- func SplitArgs(command string) []string
- func TokenEnvKeys(h Harness) []string
- func WindowKey(minutes int) string
- type Attachment
- type AuthState
- type Classification
- type Credentials
- type Decision
- type Delivery
- type Detection
- type Detector
- type Driver
- type Event
- type EventType
- type FailureClass
- type FakeDriver
- type Features
- type FileSystem
- type Harness
- type HomeFile
- type HomeFileKind
- type HomeKey
- type InstallMethod
- type InstallRecipe
- type LedgerEntry
- type LimitWindow
- type Limits
- type LimitsReader
- type LoginOptions
- type MCPCapability
- type MCPServer
- type ModelInfo
- type ModelLister
- type ModelQuery
- type ModelSetter
- type Options
- type Permission
- type PermissionMode
- type PermissionPolicy
- type Prompt
- type Registry
- func (r *Registry) Add(key string, s Session)
- func (r *Registry) CloseAll(ctx context.Context)
- func (r *Registry) Get(key string) (Session, bool)
- func (r *Registry) Keys() []string
- func (r *Registry) List() []LedgerEntry
- func (r *Registry) Path() string
- func (r *Registry) Reconcile() (killed []string, stale []string)
- func (r *Registry) Remove(key string)
- func (r *Registry) Track(key, harness string, pid, pgid int, argv []string)
- type Result
- type Runtime
- func (rt *Runtime) Close(ctx context.Context) error
- func (rt *Runtime) Detect(ctx context.Context, h Harness) (Detection, error)
- func (rt *Runtime) Driver(h Harness) (Driver, bool)
- func (rt *Runtime) HelpText(ctx context.Context, bin string) string
- func (rt *Runtime) InvalidateDetect(h Harness)
- func (rt *Runtime) InvalidateModels(h Harness)
- func (rt *Runtime) LatestVersion(ctx context.Context, h Harness) (string, error)
- func (rt *Runtime) Limits(ctx context.Context, h Harness, q ModelQuery) (Limits, error)
- func (rt *Runtime) Logger() *slog.Logger
- func (rt *Runtime) MaxFrameBytes() int
- func (rt *Runtime) Models(ctx context.Context, h Harness, q ModelQuery) ([]ModelInfo, error)
- func (rt *Runtime) OpenCodeMessages(ctx context.Context, sessionID string) ([]byte, bool)
- func (rt *Runtime) Reconcile() error
- func (rt *Runtime) Resume(ctx context.Context, req StartRequest) (Session, error)
- func (rt *Runtime) SetDriver(h Harness, d Driver)
- func (rt *Runtime) Start(ctx context.Context, req StartRequest) (Session, error)
- func (rt *Runtime) Version(ctx context.Context, bin string) string
- type Sender
- type Session
- type SessionModels
- type SessionStatus
- type Skill
- type SkillSupport
- type Snapshot
- type StartRequest
- type Steerer
- type ToolEvent
- type ToolKind
- type Tracker
- func (t *Tracker) InflightCount() int
- func (t *Tracker) Observe(e Event) Snapshot
- func (t *Tracker) OldestApprovalID() string
- func (t *Tracker) PermissionAdded(id string) Snapshot
- func (t *Tracker) PermissionDecided(id string) Snapshot
- func (t *Tracker) PromptWritten()
- func (t *Tracker) Snapshot() Snapshot
- type Usage
Constants ¶
const ( EventInit = wire.EventInit EventAssistant = wire.EventAssistant EventThought = wire.EventThought EventUser = wire.EventUser EventTool = wire.EventTool EventPermission = wire.EventPermission EventResult = wire.EventResult EventError = wire.EventError EventUsage = wire.EventUsage EventStatus = wire.EventStatus EventExit = wire.EventExit EventLimits = wire.EventLimits )
Event types.
const ( WindowFiveHour = wire.WindowFiveHour WindowDaily = wire.WindowDaily WindowWeekly = wire.WindowWeekly WindowMonthly = wire.WindowMonthly WindowCustom = wire.WindowCustom )
Window keys.
const ( StatusUnknown = wire.StatusUnknown StatusRunning = wire.StatusRunning StatusWaiting = wire.StatusWaiting StatusIdle = wire.StatusIdle )
Session statuses.
const ( ToolRead = wire.ToolRead ToolEdit = wire.ToolEdit ToolExec = wire.ToolExec ToolMCP = wire.ToolMCP ToolSearch = wire.ToolSearch ToolOther = wire.ToolOther )
Tool kinds.
const ( // DeliverySteered means the prompt joined the running turn. DeliverySteered = wire.DeliverySteered // DeliveryPrompted means a new turn starts now, or the vendor queues it. DeliveryPrompted = wire.DeliveryPrompted // DeliveryHeld means the prompt starts a new turn when the running turn // ends. DeliveryHeld = wire.DeliveryHeld )
const CodeHeldPromptDropped = wire.CodeHeldPromptDropped
CodeHeldPromptDropped is the EventError code of held prompts that never reached the vendor, because the session ended first. Text holds them.
const DefaultFakeScript = `` /* 126-byte string literal not displayed */
DefaultFakeScript emits a tiny assistant turn and a success result.
The session writes one NDJSON line to the script's stdin per call: {"type":"user","text":…} for Prompt, {"type":"steer","text":…} for Steer while a turn runs, and {"type":"set_model","model":…} for SetModel. This script echoes a steer line that arrives during its turn:
read -r line
echo '{"type":"assistant","text":"working"}'
if read -r next; then echo '{"type":"user","text":"got: '"$next"'"}'; fi
echo '{"type":"result","subtype":"success"}'
const FakeModelsEnv = "AGENTWIRE_FAKE_MODELS"
FakeModelsEnv holds the fake model list as a JSON array of ModelInfo, used when FakeDriver.ModelList is empty.
const FakeScriptEnv = "AGENTWIRE_FAKE_SCRIPT"
FakeScriptEnv overrides the fake driver script from the environment.
const StallThreshold = 5 * time.Minute
StallThreshold is the "running but no events and no in-flight tools" window that raises a stall. It is observability only; the consumer's max duration is the killer.
Variables ¶
var ErrNoActiveTurn = wire.ErrNoActiveTurn
ErrNoActiveTurn reports a Steer with no running turn.
var ErrResumeUnsupported = errors.New("agentwire: session resume not supported")
ErrResumeUnsupported reports a driver that cannot resume a session (the vendor no longer knows it, or the protocol has no resume).
var ErrTurnActive = wire.ErrTurnActive
ErrTurnActive reports a Prompt while a turn runs on a harness that cannot take a second prompt then. The caller waits for the result, or steers.
var ErrUnsupported = wire.ErrUnsupported
ErrUnsupported reports a capability the harness does not have.
Functions ¶
func ClaudeMCPConfig ¶ added in v0.3.1
ClaudeMCPConfig renders the Claude/pi JSON shape for injected servers: the value of the top-level "mcpServers" key.
func CodexMCPArgs ¶ added in v0.3.1
CodexMCPArgs renders the `-c mcp_servers.<name>...` overrides for injected servers. It never renders a secret value: a stdio server lists its env keys in env_vars, and a url server maps each header to an env var in env_http_headers. The process must carry CodexMCPEnv.
func CodexMCPEnv ¶ added in v0.3.2
CodexMCPEnv returns the env that the codex process must carry for the servers of CodexMCPArgs. Codex has one process env, so two servers that set one key to different values return an error.
func CredentialFiles ¶ added in v0.8.0
CredentialFiles are the vendor credential files, relative to the login home. DefaultHome gives the home of the user's own login.
func DefaultEffort ¶ added in v0.8.0
DefaultEffort returns the effort that harness h uses when no effort is set, or "" when the vendor does not document one. A user config can change it.
func DefaultHome ¶ added in v0.8.0
DefaultHome is the login home of the user's own login, such as ~/.claude. It is "" for a harness with no login facts.
func Efforts ¶ added in v0.8.0
Efforts returns the effort levels of model on harness h, from low to high. The levels are the same for each model of a harness, except OpenCode: there the levels are the variants of each model, and Efforts returns nil (use the live model list). An empty, non-nil result means that the harness has no effort setting.
func HomeMCPFile ¶ added in v0.9.0
HomeMCPFile is the home file that holds the MCP servers of a harness, or "" when the harness reads them from elsewhere.
func HomeTrustFile ¶ added in v0.12.0
HomeTrustFile is the home file that holds the trusted folders of a harness, or "" when the harness keeps no folder trust in its home.
func LoginCommand ¶ added in v0.8.0
LoginCommand is the command line that starts an interactive vendor login, with the binary first. Nil means that the user logs in inside the TUI with /login. Run it with LoginEnv.
func LoginCommandFor ¶ added in v0.9.0
func LoginCommandFor(h Harness, o LoginOptions) ([]string, error)
LoginCommandFor is LoginCommand for one login choice. A separate Claude login makes a long-lived token, because the keychain entry belongs to the user's own login. OpenCode needs a provider with a browser login.
func LoginDir ¶ added in v0.9.0
LoginDir is the login home inside a harness home, relative to it. Pass it to LoginEnv, AuthStatus, and the credential files. OpenCode keeps its login in an XDG data folder, apart from its config folder.
func LoginEnv ¶ added in v0.8.0
LoginEnv is the env for LoginCommand and LogoutCommand. A home that is not "" points the vendor at that login home. For OpenCode the home is the XDG data folder, which is not the StartRequest.Home config folder.
func LoginTokenEnv ¶ added in v0.9.0
LoginTokenEnv is the env key that holds a token login of h, such as the token that a separate Claude login prints. It is "" when h has none.
func LogoutCommand ¶ added in v0.8.0
LogoutCommand is the vendor logout command line, with the binary first. Nil means that the vendor has no logout command.
func MergeKeys ¶ added in v0.9.0
MergeKeys copies keys of user into own and gives the new own content. A nil keys copies each key not in skip. A key that user does not hold leaves own as it is. format is json or toml.
func ModelArgs ¶ added in v0.7.2
ModelArgs returns the flags that set the model and the reasoning effort on the interactive CLI of a harness, for example to start it in a terminal. An empty model or effort adds no flag. A harness without the flag gets none: OpenCode 2 has no model flag, and only some CLIs take an effort.
func OpenCodeConfigContent ¶ added in v0.3.1
OpenCodeConfigContent renders the OpenCode config fragment that carries the injected servers: the value of OPENCODE_CONFIG_CONTENT.
func SessionFiles ¶ added in v0.11.0
SessionFiles lists the files and folders that harness h keeps in home for the vendor session id. Remove them to forget the session. The list is empty when the harness keeps no such files or id is not a plain name.
func SetHomeMCP ¶ added in v0.9.0
SetHomeMCP writes servers into the MCP file of a harness home and gives the new content. It replaces a server of the same name.
func SetHomeTrust ¶ added in v0.12.0
SetHomeTrust marks dirs as trusted in the trust file of a harness home and gives the new content. The vendor CLI then shows no folder trust dialog for them. It keeps the other fields of each folder entry.
func SetKeys ¶ added in v0.9.0
SetKeys writes values into a home file and gives the new content. The format comes from the file extension.
func SharedLoginEnv ¶ added in v0.9.0
SharedLoginEnv is the env that makes a harness home use the user's own login. On macOS, Claude keeps the login in the keychain; an empty CLAUDE_SECURESTORAGE_CONFIG_DIR keeps the default keychain entry while CLAUDE_CONFIG_DIR points at the home. OpenCode reads the user data folder.
func SharesUserHome ¶ added in v0.9.0
SharesUserHome reports that a harness runs in the user's own home when it shares the user login. Codex cold-starts its plugin sync in a new home, omp keeps its login in a database, and OpenCode 2 reads only the user config folders.
func SplitArgs ¶
SplitArgs splits a prepared command line into arguments.
The rules are the POSIX shell's word splitting, minus expansion: unquoted whitespace separates words, single quotes are literal, double quotes keep whitespace and honor a backslash before " \ $ ` and newline, and a backslash outside quotes escapes the next character. A consumer that pins a path with spaces or a literal backslash therefore gets the argument it wrote.
func TokenEnvKeys ¶ added in v0.8.0
TokenEnvKeys are the env keys whose value is a usable login for h, such as an API key.
Types ¶
type Attachment ¶
type Attachment = wire.Attachment
Attachment is one out-of-band prompt payload (images first).
type AuthState ¶
type AuthState string
AuthState is the best-effort login view of a harness.
func AuthStatus ¶ added in v0.8.0
AuthStatus tells the login state of h in a login home. A home of "" means the user's own login, where a token env key also counts. It asks the vendor first, then reads the credential files. A login on file that the vendor rejects is AuthExpired.
type Classification ¶
type Classification struct {
Class FailureClass
Code string
Message string
}
Classification is the family plus a stable machine code.
func ClassifyError ¶
func ClassifyError(text string, status int) Classification
ClassifyError inspects error-shaped text and returns the family and code.
text MUST be error-shaped: a result error field, a stderr tail, an HTTP status field. Free-form assistant prose or tool output yields false positives, because vendors quote ordinary words such as "capacity" and "credentials" in normal text. status is an optional HTTP status from the wire (0 = unknown).
func ClassifyFor ¶
func ClassifyFor(h Harness, text string, status int) Classification
ClassifyFor is ClassifyError with the harness recorded in the code, so a consumer maps "claude.limit.rate_limited" and "codex.limit.rate_limited" to different text.
func ClassifyResult ¶
func ClassifyResult(r *Result) Classification
ClassifyResult classifies an error result frame.
func ClassifyResultFor ¶
func ClassifyResultFor(h Harness, r *Result) Classification
ClassifyResultFor is ClassifyResult with the harness recorded in the code.
func (Classification) EndReason ¶
func (c Classification) EndReason() string
EndReason maps a class to the run end-reason vocabulary (auth|limit|failed|launch).
type Credentials ¶ added in v0.3.0
type Credentials struct {
// Format names the provider wire: "anthropic" or "openai".
Format string
// BaseURL overrides the provider endpoint. Empty uses the provider
// default; an http(s) URL turns the SDK into a gateway client.
BaseURL string
// APIKey is the bearer credential.
APIKey string
// Headers are extra HTTP headers for every provider call.
Headers map[string]string
}
Credentials are the provider credentials a native session runs with.
type Detection ¶
type Detection struct {
Harness Harness
// Path is the resolved binary, empty when the harness is not installed.
Path string
// Version is the first line of `<bin> --version`, empty when unknown.
Version string
// Supported reports that the binary exists and meets the version floor.
Supported bool
// Ready reports Supported && Auth == AuthOK. Runtime.Detect sets it for
// every harness, so a picker reads one field.
Ready bool
// Auth is the best-effort login state.
Auth AuthState
// AuthDetail is a short note from the auth probe, such as an account
// email. It never contains a token.
AuthDetail string
// Features is the static capability table for the harness.
Features Features
// Detail explains an unsupported verdict.
Detail string
}
Detection is the result of probing one harness on this machine.
type Detector ¶ added in v0.3.0
Detector lets a driver answer Detect without a binary lookup. The native driver implements it: it is in-process and has no binary to find.
type Driver ¶
type Driver interface {
Name() string
Start(ctx context.Context, req StartRequest) (Session, error)
Resume(ctx context.Context, req StartRequest) (Session, error)
}
Driver starts sessions for one vendor protocol. The built-in drivers are unexported and reached through Runtime.Driver.
type FailureClass ¶
type FailureClass string
FailureClass is the entitlement/quota classification family. No pricing logic lives here, and no operator-facing text: a consumer maps the class and the code to its own wording.
const ( FailNone FailureClass = "" FailAuth FailureClass = "auth" FailLimit FailureClass = "limit" FailEntitlement FailureClass = "entitlement" FailOverloaded FailureClass = "overloaded" FailProtocol FailureClass = "protocol" FailUnknown FailureClass = "unknown" )
type FakeDriver ¶
type FakeDriver struct {
// Script is a shell program. Empty uses FakeScriptEnv, then
// DefaultFakeScript.
Script string
// Dir overrides the working directory.
Dir string
// ModelList is the list Runtime.Models returns. Empty reads
// FakeModelsEnv.
ModelList []ModelInfo
// NoSteer makes every steer fail with ErrUnsupported, so Send holds a
// prompt during a turn and sends it after the result.
NoSteer bool
}
FakeDriver is the scripted driver for tests: it spawns a shell that emits the same NDJSON vocabulary the vendors do, so a consumer's event pump is exercised without a vendor binary.
It implements Driver on its own, so a consumer injects it with Runtime.SetDriver.
func (FakeDriver) Models ¶ added in v0.4.0
func (f FakeDriver) Models(context.Context, ModelQuery) ([]ModelInfo, error)
Models implements ModelLister: ModelList, else the list in FakeModelsEnv.
func (FakeDriver) Resume ¶
func (f FakeDriver) Resume(ctx context.Context, req StartRequest) (Session, error)
Resume implements Driver.
func (FakeDriver) Start ¶
func (f FakeDriver) Start(ctx context.Context, req StartRequest) (Session, error)
Start implements Driver.
type Features ¶
type Features struct {
// MCPInject says how MCPServers reach the harness.
MCPInject MCPCapability
// SkillsInject says how Skills reach the harness.
SkillsInject SkillSupport
// Instructions reports per-session instruction support.
Instructions bool
// Attachments reports prompt image support.
Attachments bool
// Resume reports session resume support.
Resume bool
// Permissions reports that the harness asks before a tool runs and the
// library can answer.
Permissions bool
// FS reports that the harness can route file reads and writes to
// StartRequest.FS.
FS bool
// Models reports that Runtime.Models can list the harness models.
Models bool
// SetModel reports that a live session implements ModelSetter.
SetModel bool
// Steer reports that a live session implements Steerer and the vendor
// takes input during a running turn.
Steer bool
}
Features reports what a harness can take per session. It is static per harness: a feature that needs StartRequest.Home degrades at run time rather than appearing and disappearing here.
type FileSystem ¶
type FileSystem interface {
ReadTextFile(ctx context.Context, path string) (string, error)
WriteTextFile(ctx context.Context, path, content string) error
}
FileSystem is the optional file access an ACP agent may request. When it is set, the library advertises fs.readTextFile and fs.writeTextFile and routes those calls here, so a consumer can observe or approve every file write.
type Harness ¶
type Harness string
Harness identifies one vendor coding agent.
const ( Claude Harness = "claude" Codex Harness = "codex" OpenCode Harness = "opencode" OpenCode2 Harness = "opencode2" Pi Harness = "pi" Copilot Harness = "copilot" Cursor Harness = "cursor" Gemini Harness = "gemini" OMP Harness = "omp" Grok Harness = "grok" Fake Harness = "fake" // Native is the in-process harness the native module serves. It is not // in New's built-in driver table: a consumer registers it with // SetDriver(Native, nativedriver) or leaves it out entirely. Native Harness = "native" )
type HomeFile ¶ added in v0.9.0
type HomeFile struct {
Key string `json:"key"`
Kind HomeFileKind `json:"kind"`
// User is the path relative to the user's home folder.
User string `json:"user"`
// Home is the path relative to the harness home.
Home string `json:"home"`
// Format is json, toml, or markdown for a file, and empty for a folder.
Format string `json:"format,omitempty"`
// Keys are the keys that a HomeKeys entry copies. A TOML key can be
// "table.key". Nil copies each key that no other entry of the same
// home file names.
Keys []string `json:"keys,omitempty"`
Share bool `json:"share"`
// Login marks a login file. The auth mode decides its share.
Login bool `json:"login,omitempty"`
// Hooks marks a file or a key that holds user hooks.
Hooks bool `json:"hooks,omitempty"`
// OwnEnv is the env key that points the vendor at the own copy.
OwnEnv string `json:"own_env,omitempty"`
}
HomeFile is one vendor file or folder that a harness home can share with the user's own setup, or keep as an own copy.
type HomeFileKind ¶ added in v0.9.0
type HomeFileKind string
HomeFileKind tells how a user file reaches a harness home.
const ( // HomeLink links the home path to the user file or folder. HomeLink HomeFileKind = "link" // HomeEach links each entry of the user folder into the home folder. HomeEach HomeFileKind = "each" // HomeKeys copies top-level keys of the user file into the home file. HomeKeys HomeFileKind = "keys" // HomeRead marks a user file that the vendor reads itself. An own copy // lives at Home, and OwnEnv points the vendor at it. HomeRead HomeFileKind = "read" )
type HomeKey ¶ added in v0.9.0
type HomeKey struct {
// File is the path relative to the harness home.
File string `json:"file"`
// Key is a top-level JSON key, or a TOML key with its table:
// "table.key".
Key string `json:"key"`
Value any `json:"value"`
// Keep keeps a value that the file holds already.
Keep bool `json:"keep,omitempty"`
}
HomeKey is one value that a home file must hold.
func HomeDefaults ¶ added in v0.9.0
HomeDefaults are the values that a harness home needs to start with no first-run dialog and no self-update.
type InstallMethod ¶ added in v0.8.0
type InstallMethod string
InstallMethod is how a harness binary gets on the machine.
const ( // InstallNPM installs a global npm package. InstallNPM InstallMethod = "npm" // InstallBrew installs a Homebrew formula. InstallBrew InstallMethod = "brew" // InstallScript pipes a vendor install script into a shell. InstallScript InstallMethod = "script" // InstallBinary downloads a binary. The caller does the download. InstallBinary InstallMethod = "binary" )
type InstallRecipe ¶ added in v0.8.0
type InstallRecipe struct {
Harness Harness
Method InstallMethod
// Package is the npm package, the brew formula, the script URL, or the
// download URL.
Package string
// Bin is the binary that the install puts on PATH.
Bin string
// Requires lists the programs that must be on PATH before the install.
Requires []string
// Update is the vendor self-update command after Bin. Nil means install
// again.
Update []string
// UpdateTo is the command after Bin that installs one version. The
// version goes last. Nil means install again.
UpdateTo []string
// UpdateOffEnv is the env that stops the vendor auto-update.
UpdateOffEnv map[string]string
// UpdateOffArgs are launch args that stop the vendor auto-update.
UpdateOffArgs []string
}
InstallRecipe holds the vendor facts to install and update one harness. The library runs none of these commands.
func Recipe ¶ added in v0.8.0
func Recipe(h Harness) (InstallRecipe, bool)
Recipe returns the install facts of h. ok=false means that the harness has no vendor install, such as the native and fake harnesses.
func (InstallRecipe) Command ¶ added in v0.8.0
func (r InstallRecipe) Command(version string) []string
Command is the install command line. An empty version means the latest. The script method ignores the version. The binary method gives nil.
func (InstallRecipe) UpdateCommand ¶ added in v0.8.0
func (r InstallRecipe) UpdateCommand(version string) []string
UpdateCommand is the command line that updates Bin. An empty version means the latest. It falls back to Command when the vendor has no matching self-update.
type LedgerEntry ¶
type LedgerEntry struct {
Key string `json:"key"`
Harness string `json:"harness"`
PID int `json:"pid"`
PGID int `json:"pgid,omitempty"`
StartToken string `json:"start_token,omitempty"`
StartedAt time.Time `json:"started_at"`
Argv []string `json:"argv,omitempty"`
}
LedgerEntry is one spawned child, recorded so a crashed process can reconcile leftovers on boot. StartToken is the positive-match guard against pid reuse.
type LimitWindow ¶ added in v0.6.0
type LimitWindow = wire.LimitWindow
LimitWindow is the use of one plan limit window.
type LimitsReader ¶ added in v0.6.0
type LimitsReader interface {
ReadLimits(ctx context.Context, q ModelQuery) (Limits, error)
}
LimitsReader is the optional driver capability that reads the plan limits of the account without a live session.
type LoginOptions ¶ added in v0.9.0
type LoginOptions struct {
// Provider is the model provider of a harness that has many, such as
// OpenCode.
Provider string
// Separate is a login apart from the user's own login.
Separate bool
}
LoginOptions picks a vendor login.
type MCPCapability ¶
type MCPCapability string
MCPCapability reports how a harness accepts per-session MCP servers.
const ( // MCPNone means the harness cannot take an injected server. MCPNone MCPCapability = "none" // MCPFlags means the library renders the servers into the launch. MCPFlags MCPCapability = "flags" // MCPSession means the servers travel in the session-open request. MCPSession MCPCapability = "session" )
type MCPServer ¶
type MCPServer struct {
Name string
Command string
Args []string
Env map[string]string
URL string
Headers map[string]string
}
MCPServer is one Model Context Protocol server injected into a session. Command selects a stdio server; URL selects an HTTP server.
type ModelInfo ¶ added in v0.4.0
type ModelInfo struct {
// ID is the value StartRequest.Model and SetModel take.
ID string `json:"id"`
// Name is the display name. Empty means use ID.
Name string `json:"name,omitempty"`
// Description is a short vendor note, such as the context size.
Description string `json:"description,omitempty"`
// Default marks the model the harness uses when Model is empty.
Default bool `json:"default,omitempty"`
}
ModelInfo is one model a harness offers.
func StaticModels ¶ added in v0.8.0
StaticModels returns a fixed model list for a harness whose CLI cannot list models without a session, or nil. It needs no install and no login. Runtime.Models gives the live list.
type ModelLister ¶ added in v0.4.0
type ModelLister interface {
Models(ctx context.Context, q ModelQuery) ([]ModelInfo, error)
}
ModelLister is the optional driver capability that lists models without a live session.
type ModelQuery ¶ added in v0.4.0
type ModelQuery struct {
Binary string // empty searches PATH
Home string // same meaning as StartRequest.Home
Env map[string]string // same meaning as StartRequest.Env
WorkingDir string // some vendors read project config
}
ModelQuery scopes a model list to one install and one config home.
type ModelSetter ¶ added in v0.4.0
ModelSetter is the optional session capability that changes the model of a live session. It never interrupts the running turn.
type Options ¶
type Options struct {
// ClientName is the product name the harness sees in clientInfo and in
// vendor client markers, for example "trebi" or "sling".
ClientName string
// ClientVersion is the product version reported next to ClientName.
ClientVersion string
// LedgerPath is the crash ledger file. Empty disables the ledger.
LedgerPath string
// Logger receives structured lifecycle lines. Nil discards them.
Logger *slog.Logger
// FingerprintIgnoreEnv lists environment keys left out of the OpenCode
// server fingerprint, so per-run values do not split a shared server.
FingerprintIgnoreEnv []string
// MaxFrameBytes bounds one wire frame. Zero uses 16 MiB.
MaxFrameBytes int
// OnStderr receives live stderr lines from every child.
OnStderr func(Harness, string)
// AuthCacheTTL is how long a harness login probe answers from cache.
// Zero uses 5 min. A negative value disables the cache.
AuthCacheTTL time.Duration
// ModelCacheTTL is how long a model list answers from cache. Zero uses
// 10 min. A negative value disables the cache.
ModelCacheTTL time.Duration
// HTTPClient makes the release lookups of LatestVersion. Nil uses a
// client with a 10 s timeout.
HTTPClient *http.Client
}
Options configures a Runtime.
type Permission ¶
type Permission = wire.Permission
Permission is a vendor permission request awaiting a decision.
type PermissionMode ¶
type PermissionMode string
PermissionMode is the one policy that every harness maps onto its own mechanism.
const ( // PermissionAsk routes every request to the consumer as an // EventPermission. It is the default. PermissionAsk PermissionMode = "ask" // PermissionAutoEdit answers edit requests in the library and routes the // rest to the consumer. PermissionAutoEdit PermissionMode = "auto_edit" // PermissionAuto answers every request in the library. PermissionAuto PermissionMode = "auto" // PermissionInherit adds no permission-mode flag, so the operator's own // harness configuration decides. It is the mode for a consumer that must // not override a setting the operator made in the harness itself. The // host prompt callback is still installed, and requests the harness sends // are routed to the consumer, like ask. PermissionInherit PermissionMode = "inherit" )
type PermissionPolicy ¶
type PermissionPolicy struct {
Mode PermissionMode
// AllowTools lists extra tools that are allowed without asking, in "ask"
// and "auto_edit" mode. Patterns may end in "*", for example
// "mcp__sling__*".
AllowTools []string
}
PermissionPolicy is the normalized permission policy.
func (PermissionPolicy) Answer ¶
func (p PermissionPolicy) Answer(kind ToolKind, tool string) (Decision, bool)
Answer returns the decision the policy makes without the consumer. ok=false means the request becomes an EventPermission.
func (PermissionPolicy) Normalized ¶
func (p PermissionPolicy) Normalized() PermissionPolicy
Normalized returns the policy with a concrete mode.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry owns the live sessions and the pid ledger. A Runtime builds one when Options.LedgerPath is set.
func NewRegistry ¶
NewRegistry builds a registry whose ledger lives at path. An empty path disables persistence, which is what tests want.
func (*Registry) Reconcile ¶
Reconcile is the boot path: for each ledger row, kill the process only when it is positively matched (alive and start token equal); every row is then dropped. It returns the run keys whose processes were killed and every key that needs a session_gone row.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime owns every piece of per-process state: the driver table, the OpenCode server pool, version caches, the crash ledger and the id counter.
func (*Runtime) Detect ¶
Detect probes one harness: binary, version, floor and login state. A missing binary is a supported=false verdict, not an error. A driver that implements Detector answers for itself without a binary lookup.
func (*Runtime) Driver ¶
Driver resolves the driver for a harness. ok=false means the harness has no proven wire.
func (*Runtime) HelpText ¶
HelpText returns the cached `<bin> --help` output, for a decision that needs to compare two flags instead of testing one.
func (*Runtime) InvalidateDetect ¶ added in v0.2.2
InvalidateDetect drops the cached login probes of one harness. A consumer calls it after a login or a logout, so Detect sees the new state at once.
func (*Runtime) InvalidateModels ¶ added in v0.4.0
InvalidateModels drops the cached lists of one harness, for example after a login or a config change.
func (*Runtime) LatestVersion ¶ added in v0.8.0
LatestVersion asks the vendor registry for the newest release of h, such as "2.1.308". It uses Options.HTTPClient. A harness with no registry gives ErrUnsupported.
func (*Runtime) Limits ¶ added in v0.6.0
Limits reads the plan limits of one harness account. It starts a short-lived child and never caches. A harness with no reader returns ErrUnsupported.
func (*Runtime) MaxFrameBytes ¶
MaxFrameBytes is the effective frame cap.
func (*Runtime) Models ¶ added in v0.4.0
Models lists the models of one harness. It answers from a cache; the first call can start a short-lived child. A harness with no lister returns ErrUnsupported.
func (*Runtime) OpenCodeMessages ¶
OpenCodeMessages returns the persisted message list for one session from a live server. ok=false means no server currently holds the session.
func (*Runtime) Reconcile ¶
Reconcile kills leftover children from a previous process and drops the ledger. Only positively matched pids die: a reused pid is left alone.
func (*Runtime) Resume ¶
Resume reopens a known session. It returns ErrResumeUnsupported when the vendor no longer knows the session, or the protocol has no resume.
func (*Runtime) SetDriver ¶
SetDriver replaces the driver for a harness. Tests use it to inject a scripted driver. nil drops the override and restores the built-in driver, so a caller can always get back to the default table.
type Session ¶
type Session interface {
// Provider is the harness name.
Provider() string
// ID is the vendor session id; it may be empty until init.
ID() string
// PID is the child process id (0 for in-process sessions).
PID() int
// Prompt writes one user turn.
Prompt(ctx context.Context, p Prompt) error
// Interrupt asks the harness to stop the current turn.
Interrupt(ctx context.Context) error
// AnswerPermission routes a decision to the vendor.
AnswerPermission(ctx context.Context, permissionID string, d Decision) error
// InterruptTurn is the protocol-level interrupt. It is the same call as
// Interrupt for every built-in driver, and is kept for callers that want
// to be explicit about not falling back to a signal.
InterruptTurn(ctx context.Context) error
// Done is closed when the session has ended and Events is drained.
Done() <-chan struct{}
// Err is the first failure the session recorded, if any.
Err() error
// Close runs the graceful close sequence and waits for the drain.
Close(ctx context.Context) error
// Events is closed after the terminal events.
Events() <-chan Event
}
Session is one vendor conversation. The caller holds it for the life of the run.
A caller MUST read Events until it closes, or call Close. A caller that stops reading without closing leaks the framing goroutine.
type SessionModels ¶ added in v0.4.0
type SessionModels interface {
Models() []ModelInfo
}
SessionModels is the optional session capability that returns the models the live session offered in its handshake (Claude initialize, ACP session/new). It returns nil when the handshake offered none.
type SessionStatus ¶
type SessionStatus = wire.SessionStatus
SessionStatus is the activity view of a session.
type Skill ¶
type Skill struct {
// Name overrides the name in the SKILL.md frontmatter.
Name string
// Dir is the absolute path of the directory that holds SKILL.md.
Dir string
}
Skill is one extra skill made visible to a session.
type SkillSupport ¶
type SkillSupport string
SkillSupport reports how a harness takes extra skills for one session.
const ( // SkillNone means the harness gets no extra skills. SkillNone SkillSupport = "none" // SkillNative means the harness loads the skills itself, from a directory // the library generates or points at. SkillNative SkillSupport = "native" // SkillOverlay means the library links the skills into a per-session // config directory the harness already reads. SkillOverlay SkillSupport = "overlay" // SkillInstructions means the skills are described in the session // instructions and the agent reads them from disk. SkillInstructions SkillSupport = "instructions" )
type Snapshot ¶
type Snapshot struct {
State SessionStatus
TurnActive bool
Progressing bool
Stalled bool
StallSince time.Time
InflightTools int
OpenApprovals int
LastEventAt time.Time
LastEventKind EventType
LastToolName string
IdleSince time.Time
WaitingSince time.Time
LastResult *Result
// Exited reports that the session's process ended.
Exited bool
// ExitedAt is the moment the exit event landed.
ExitedAt time.Time
}
Snapshot is the derived state a consumer and its reaper read.
type StartRequest ¶
type StartRequest struct {
Harness Harness
// Binary is the executable. Empty searches PATH.
Binary string
WorkingDir string
// Env is added to the parent environment and wins on conflict.
Env map[string]string
// Home is an optional isolated config home. Empty uses the user's own
// configuration, including their login, MCP servers and skills.
Home string
// SessionID is a resume target, or a pre-assigned id where the harness
// allows one.
SessionID string
// Model is the vendor model name. Empty uses the vendor default.
Model string
// Effort is one of low, medium, high, max. Empty uses the vendor default.
Effort string
Permissions PermissionPolicy
MCPServers []MCPServer
Skills []Skill
Instructions string
// Credentials carries the provider credentials for the native harness
// only. The library never reads env or secrets to fill it, and the CLI
// drivers ignore it.
Credentials *Credentials
// OneShot writes OneShotPrompt and closes stdin, so the child exits after
// the turn. Use it for a job with no follow-up surface.
OneShot bool
OneShotPrompt string
// HandshakeTimeout overrides the protocol handshake wait.
HandshakeTimeout time.Duration
// ExtraArgs is appended verbatim after the library's own arguments. Use
// it for consumer flags such as --settings or -c notify=...
ExtraArgs []string
// BaseCommand is an expert override: when it is set the launch builder is
// skipped and the command is used as-is.
BaseCommand []string
// Raw carries per-harness overrides the typed fields do not cover:
// "strict_mcp" (bool, Claude), "acp_auth_method" (string), "approvalPolicy"
// and "sandbox" (string, Codex), "auth_method" (string, ACP).
Raw map[string]any
// LogPath writes the frames in and out as NDJSON. Secrets are not
// redacted, so the file is created mode 0600. Stream fragments that a
// later complete frame repeats are left out unless LogFragments is set.
LogPath string
// FragmentLogPath gets the buffered fragments of the open message when
// the stream fails or ends before the complete message. Empty drops them.
FragmentLogPath string
// LogFragments writes every stream fragment to LogPath (debug).
LogFragments bool
// FS is the optional ACP file-system adapter.
FS FileSystem
// OnStderr receives live stderr lines from this child.
OnStderr func(Harness, string)
}
StartRequest describes one session. The caller describes; the library builds the command.
func (StartRequest) RawBool ¶
func (r StartRequest) RawBool(key string) (bool, bool)
RawBool reads a boolean override.
func (StartRequest) RawString ¶
func (r StartRequest) RawString(key string) string
RawString reads a string override.
type Steerer ¶ added in v0.4.0
Steerer is the optional session capability that adds input to the running turn. It returns ErrNoActiveTurn when no turn runs; the caller then uses Prompt. It returns ErrUnsupported when the vendor refused the steer; the caller then queues the input. It never interrupts the turn.
type ToolKind ¶
ToolKind is the coarse class of a tool invocation.
func ClassifyTool ¶
ClassifyTool maps a vendor tool name to a coarse kind, so a consumer can render or auto-approve without a per-vendor name table.
type Tracker ¶
type Tracker struct {
// contains filtered or unexported fields
}
Tracker is the per-run activity tracker. Wire events are the only input; a consumer reads snapshots instead of scraping a terminal.
func (*Tracker) InflightCount ¶
InflightCount reports tool invocations without a matching result.
func (*Tracker) Observe ¶
Observe folds one event into the tracker and returns the derived snapshot.
func (*Tracker) OldestApprovalID ¶
OldestApprovalID returns the oldest open wire permission id, or "" when the pending approval has none.
func (*Tracker) PermissionAdded ¶
PermissionAdded registers an approval the wire did not open.
func (*Tracker) PermissionDecided ¶
PermissionDecided clears an open approval. An empty id clears the oldest one (approvals that arrived without a wire id have none).
func (*Tracker) PromptWritten ¶
func (t *Tracker) PromptWritten()
PromptWritten marks the optimistic running state when a prompt is written: model latency is not idleness.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
internal
|
|
|
flight
Package flight collapses concurrent same-key calls into one execution.
|
Package flight collapses concurrent same-key calls into one execution. |
|
jsonrpc
Package jsonrpc is the JSON-RPC 2.0 client shared by the harness drivers that speak it (Codex app-server, ACP agents).
|
Package jsonrpc is the JSON-RPC 2.0 client shared by the harness drivers that speak it (Codex app-server, ACP agents). |
|
proc
Package proc spawns and reaps one child process with explicit pipes, group control, and a single Wait.
|
Package proc spawns and reaps one child process with explicit pipes, group control, and a single Wait. |
|
wire
Package wire is the session plumbing shared by every harness driver: it owns the child process, the NDJSON framing, the event fan-out, and the graceful close sequence.
|
Package wire is the session plumbing shared by every harness driver: it owns the child process, the NDJSON framing, the event fan-out, and the graceful close sequence. |
|
native
module
|
|
|
provider/anthropic
module
|
|
|
provider/openai
module
|
|
|
Package tui reads the screen of a vendor TUI that runs in a terminal.
|
Package tui reads the screen of a vendor TUI that runs in a terminal. |