Documentation
¶
Overview ¶
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. Drivers own parse and encode only.
The public event types live here and are re-exported by the root package, so a driver never imports the root and the root never reaches into a driver's framing.
Index ¶
- Constants
- Variables
- func JSONLine(v any) ([]byte, error)
- func WindowKey(minutes int) string
- type Adapter
- type Attachment
- type ConcurrentPrompter
- type Config
- type Decision
- type Delivery
- type Event
- type EventType
- type FragmentClassifier
- type InterruptEncoder
- type LimitWindow
- type Limits
- type Outbox
- type Permission
- type Prompt
- type Prompter
- type Result
- type SendOps
- type Session
- func (s *Session) AnswerPermission(ctx context.Context, permissionID string, d Decision) error
- func (s *Session) Argv() []string
- func (s *Session) Close(ctx context.Context) error
- func (s *Session) Done() <-chan struct{}
- func (s *Session) Err() error
- func (s *Session) Events() <-chan Event
- func (s *Session) Harness() string
- func (s *Session) ID() string
- func (s *Session) Interrupt(ctx context.Context) error
- func (s *Session) InterruptTurn(ctx context.Context) error
- func (s *Session) KillTree() error
- func (s *Session) OnClose(fn func())
- func (s *Session) PID() int
- func (s *Session) Pgid() int
- func (s *Session) Prompt(ctx context.Context, p Prompt) error
- func (s *Session) Provider() string
- func (s *Session) Send(ctx context.Context, p Prompt) (Delivery, error)
- func (s *Session) SetID(id string)
- func (s *Session) Turn() int
- func (s *Session) WriteFrame(frame []byte) error
- type SessionStatus
- type SteerAdapter
- type ToolEvent
- type ToolKind
- type TurnStater
- type Usage
- type Writer
- type WriterSetter
Constants ¶
const ( WindowFiveHour = "five_hour" WindowDaily = "daily" WindowWeekly = "weekly" WindowMonthly = "monthly" WindowCustom = "custom" )
Window keys of a LimitWindow.
const CodeHeldPromptDropped = "held_prompt_dropped"
CodeHeldPromptDropped is the error code of held prompts that the session dropped, because the process exited before the turn ended.
const DefaultMaxFrameBytes = 16 << 20
DefaultMaxFrameBytes bounds one NDJSON frame when the caller sets no limit. Giant tool payloads fit; a runaway line does not.
const EndReasonProtocol = "protocol"
EndReasonProtocol is the failure family of a wire-level failure. It mirrors the root package's FailureClass "protocol"; framing cannot import the root package, so the value is restated here.
Variables ¶
var ErrNoActiveTurn = errors.New("agentwire: no active turn")
ErrNoActiveTurn reports a Steer with no running turn.
var ErrTurnActive = errors.New("agentwire: a turn is active")
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 = errors.New("agentwire: unsupported by this harness")
ErrUnsupported reports a capability the harness or protocol does not have.
Functions ¶
Types ¶
type Adapter ¶
type Adapter interface {
// Handshake writes protocol initialization (control initialize, thread
// setup) and returns any immediately-known events. It runs inside Start,
// which blocks until it returns. A non-nil error fails the start.
Handshake(ctx context.Context, w *Writer) ([]Event, error)
// EncodePrompt renders one user turn as one frame.
EncodePrompt(p Prompt) ([]byte, error)
// Parse maps one stdout line to zero or more events.
Parse(line []byte) []Event
// EncodeDecision answers a permission request.
EncodeDecision(id string, d Decision) ([]byte, error)
// Exit maps process exit (after stdout EOF) to events. It is not called
// when the session produced its own terminal result and exited cleanly.
Exit(code int, err error, stderr string) []Event
}
Adapter is one vendor protocol codec.
type Attachment ¶
type Attachment struct {
// MIME is the media type, for example "image/png".
MIME string
// Path is a file on disk the library reads and encodes itself.
Path string
// Data is the raw bytes, used when Path is empty.
Data []byte
}
Attachment is one out-of-band prompt payload. Data wins over Path when both are set. Images are sent before text.
type ConcurrentPrompter ¶ added in v0.5.0
type ConcurrentPrompter interface {
ConcurrentPrompt() bool
}
ConcurrentPrompter is the optional adapter capability of a vendor that queues a second prompt during a turn.
type Config ¶
type Config struct {
// MaxFrameBytes bounds one frame. Zero uses DefaultMaxFrameBytes.
MaxFrameBytes int
// LogPath records the frames in and out as NDJSON, one line per frame.
// Secrets are not redacted, so the file is created mode 0600. Stream
// fragments 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, mode 0600.
FragmentLogPath string
// LogFragments writes every fragment to LogPath.
LogFragments bool
}
Config tunes one wire session.
type Decision ¶
type Decision struct {
Allow bool
Message string
UpdatedInput json.RawMessage
}
Decision answers a Permission. Message is shown to the model on deny.
type Delivery ¶ added in v0.5.0
type Delivery string
Delivery tells how Send delivered a prompt.
const ( // DeliverySteered means the prompt joined the running turn. DeliverySteered Delivery = "steered" // DeliveryPrompted means a new turn starts now, or the vendor queues it. DeliveryPrompted Delivery = "prompted" // DeliveryHeld means the prompt starts a new turn when the running turn ends. DeliveryHeld Delivery = "held" )
type Event ¶
type Event struct {
Type EventType
At time.Time
// Turn counts completed user turns. It is 1 for the first turn.
Turn int
// SessionID carries the vendor session/thread id on init and result.
SessionID string
// Text is assistant/user text or a short human summary.
Text string
// Delta marks Text as a stream delta rather than a complete block.
Delta bool
Tool *ToolEvent
Permission *Permission
Result *Result
Usage *Usage
Limits *Limits
// Status is the tracker hint of a status event.
Status SessionStatus
// Error is a human-readable failure for EventError/EventExit.
Error string
// Code is the stable machine code of a failure (for example
// "frame_too_large", "process_exited"). Consumers map it to their own
// text; the library never ships operator prose.
Code string
// EndReason is the classified failure family (auth|limit|entitlement|...).
EndReason string
// ExitCode is set on EventExit.
ExitCode *int
// Raw is the vendor frame, kept for fixtures and the run log.
Raw []byte
}
Event is one normalized wire event from a vendor session.
func DroppedEvent ¶ added in v0.5.0
DroppedEvent reports held prompts that never reached the vendor.
type EventType ¶
type EventType string
EventType is the normalized wire vocabulary. One vendor turn emits status, progress, permissions, and exactly one terminal result.
const ( // EventInit reports the vendor session is live (system/init, thread id). EventInit EventType = "init" // EventAssistant is assistant text; Delta=true means a stream delta. EventAssistant EventType = "assistant" // EventThought is reasoning text the model surfaces separately from the // answer; Delta works as for EventAssistant. EventThought EventType = "thought" // EventUser echoes a user turn (prompt write). EventUser EventType = "user" // EventTool is a tool lifecycle event (started/completed/failed). EventTool EventType = "tool" // EventPermission is a human decision request (can_use_tool, approvals). EventPermission EventType = "permission" // EventResult is the terminal turn event. Exactly one per turn. EventResult EventType = "result" // EventError is a classified failure (wire or process). EventError EventType = "error" // EventUsage carries token/cost counters. EventUsage EventType = "usage" // EventStatus is a coarse session status signal (busy/idle/compaction). EventStatus EventType = "status" // EventExit reports the child process ended. It is always the last event. EventExit EventType = "exit" // EventLimits carries the plan limit windows of the account. EventLimits EventType = "limits" )
type FragmentClassifier ¶ added in v0.10.0
FragmentClassifier is implemented by adapters whose protocol streams part of a message that a later complete frame repeats.
type InterruptEncoder ¶
InterruptEncoder is the optional protocol-level interrupt frame.
type LimitWindow ¶ added in v0.6.0
type LimitWindow struct {
// Key is five_hour, daily, weekly, monthly, or custom.
Key string
// Scope narrows the window, for example "opus" or a Codex limit id.
Scope string
// Minutes is the window length. It is 0 when not known.
Minutes int
// UsedPercent is 0–100.
UsedPercent float64
// ResetsAt is zero when not known.
ResetsAt time.Time
}
LimitWindow is the use of one plan limit window.
type Limits ¶ added in v0.6.0
type Limits struct {
// Plan is the vendor plan name, for example "plus". Empty when not known.
Plan string
// Rejected reports that the harness refused the last request on a limit.
Rejected bool
Windows []LimitWindow
}
Limits is the plan limit state of the account behind a session.
type Outbox ¶ added in v0.5.0
type Outbox struct {
// contains filtered or unexported fields
}
Outbox holds the prompts that wait for the running turn to end.
func (*Outbox) Flush ¶ added in v0.5.0
Flush sends the held prompts as one followup turn. The caller calls it after the turn ended. It returns the prompts it could not send.
type Permission ¶
type Permission struct {
ID string
Tool string
Kind ToolKind
Question string
Input string
Options []string
// ToolUseID is the tool_use id the request belongs to, when the vendor
// carries it. A consumer joins an approval card to its tool chip.
ToolUseID string
}
Permission is a vendor permission request awaiting a decision.
type Prompt ¶
type Prompt struct {
Text string
// Kind is the origin: job|assistant|agent|memory_fix|followup|wake. The
// library never interprets it; it is carried for consumer log lines.
Kind string
// Attachments are images or files sent with the turn, images first.
Attachments []Attachment
}
Prompt is one user turn written to a live session.
type Prompter ¶
Prompter is implemented by adapters whose prompt is a request with a response (Codex turn/start, turn/steer). They own ack handling and the busy-turn fallback instead of the fire-and-forget frame path.
type Result ¶
type Result struct {
Subtype string
IsError bool
Text string
SessionID string
Usage Usage
EndReason string
// Code is the classified machine code of an error result.
Code string
}
Result is the terminal turn payload. Subtype and IsError come from the vendor; EndReason is the classified family when the result is an error.
type SendOps ¶ added in v0.5.0
type SendOps struct {
Active func() bool
Prompt func(context.Context, Prompt) error
// Steer is nil when the session cannot steer.
Steer func(context.Context, Prompt) error
// Concurrent means Prompt is safe during a turn.
Concurrent bool
}
SendOps are the session calls that one Send uses.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is one conversation over a child process.
func NewMemorySession ¶
func NewMemorySession(harness string, adapter Adapter, stdin io.Writer, stdout io.Reader, ctx context.Context, cfg Config) *Session
NewMemorySession builds an in-memory session: stdin is the writer the driver uses, stdout the reader the peer writes responses into. It is the test seam for driver tests and the substitution point for a scripted peer.
func Start ¶
func Start(ctx context.Context, harness string, p *proc.Proc, adapter Adapter, cfg Config) (*Session, error)
Start spawns the child and starts the framing loop. It blocks until the adapter handshake returns; a handshake failure kills the child and is returned as an error. ctx covers the handshake only: the process lifetime does not depend on it.
func (*Session) AnswerPermission ¶
AnswerPermission routes a decision back to the vendor.
func (*Session) Done ¶
func (s *Session) Done() <-chan struct{}
Done is closed when the session ends and the event channel is closed.
func (*Session) Events ¶
Events is closed after the session is finished and its terminal events are drained. A consumer MUST read until it closes, or call Close: a consumer that walks away without either leaks the framing goroutine.
func (*Session) Interrupt ¶
Interrupt is the Session method: a protocol interrupt where available, a signal otherwise.
func (*Session) InterruptTurn ¶
InterruptTurn sends the protocol interrupt when the adapter has one, else a graceful signal to the process group. The session survives a protocol interrupt; a signal-based interrupt asks the child to stop the turn itself.
func (*Session) OnClose ¶
func (s *Session) OnClose(fn func())
OnClose registers a cleanup hook (temp dirs, files). Hooks run once, after the session ends.
func (*Session) Prompt ¶
Prompt writes one user turn. The child must still be alive. During a turn it returns ErrTurnActive, unless the vendor queues a second prompt.
func (*Session) Send ¶ added in v0.5.0
Send steers the running turn, else prompts, else holds p and sends it when the turn ends.
func (*Session) WriteFrame ¶
WriteFrame writes one newline-terminated NDJSON frame.
type SessionStatus ¶
type SessionStatus string
SessionStatus is the activity view of a session.
const ( StatusUnknown SessionStatus = "" StatusRunning SessionStatus = "running" StatusWaiting SessionStatus = "waiting" StatusIdle SessionStatus = "idle" )
type SteerAdapter ¶ added in v0.5.0
SteerAdapter is the optional adapter capability that adds input to the running turn.
type ToolEvent ¶
type ToolEvent struct {
ID string
Name string
Kind ToolKind
Input string
Output string
Status string // started|completed|failed
// Paths lists the files an edit touches, where the protocol says so.
Paths []string
ExitCode *int
}
ToolEvent is one tool invocation (start or completion).
type ToolKind ¶
type ToolKind string
ToolKind is the coarse class of a tool invocation. Consumers use it to decide what to render or auto-approve without parsing vendor tool names.
type TurnStater ¶ added in v0.5.0
type TurnStater interface {
TurnActive() bool
}
TurnStater is the optional adapter capability that reports a running turn.
type Usage ¶
type Usage struct {
Input int64
Output int64
CacheRead int64
CacheCreation int64
Model string
CostUSD float64
}
Usage is token/cost accounting (vendor units).
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer is an adapter's handle on the child's stdin plus the session id.
func (*Writer) SetSessionID ¶
SetSessionID records the vendor session id learned on the wire.
type WriterSetter ¶
type WriterSetter interface {
SetWriter(*Writer)
}
WriterSetter is implemented by adapters that need the stdin writer before Handshake runs (every JSON-RPC driver).