Help us shape the future of Go! Take the 2026 Go Developer Survey

wire

package
v0.12.1 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 13 Imported by: 0

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

View Source
const (
	WindowFiveHour = "five_hour"
	WindowDaily    = "daily"
	WindowWeekly   = "weekly"
	WindowMonthly  = "monthly"
	WindowCustom   = "custom"
)

Window keys of a LimitWindow.

View Source
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.

View Source
const DefaultMaxFrameBytes = 16 << 20

DefaultMaxFrameBytes bounds one NDJSON frame when the caller sets no limit. Giant tool payloads fit; a runaway line does not.

View Source
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

View Source
var ErrNoActiveTurn = errors.New("agentwire: no active turn")

ErrNoActiveTurn reports a Steer with no running turn.

View Source
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.

View Source
var ErrUnsupported = errors.New("agentwire: unsupported by this harness")

ErrUnsupported reports a capability the harness or protocol does not have.

Functions

func JSONLine

func JSONLine(v any) ([]byte, error)

JSONLine marshals v into one newline-terminated NDJSON frame.

func WindowKey added in v0.6.0

func WindowKey(minutes int) string

WindowKey maps a window length in minutes to its key.

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

func DroppedEvent(held []Prompt) Event

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

type FragmentClassifier interface {
	Fragment(line []byte) bool
}

FragmentClassifier is implemented by adapters whose protocol streams part of a message that a later complete frame repeats.

type InterruptEncoder

type InterruptEncoder interface {
	EncodeInterrupt() ([]byte, error)
}

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) Drop added in v0.5.0

func (o *Outbox) Drop() []Prompt

Drop empties the queue and returns what it held.

func (*Outbox) Flush added in v0.5.0

func (o *Outbox) Flush(ctx context.Context, prompt func(context.Context, Prompt) error) []Prompt

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.

func (*Outbox) Pending added in v0.5.0

func (o *Outbox) Pending() bool

Pending reports whether prompts wait for the turn to end.

func (*Outbox) Send added in v0.5.0

func (o *Outbox) Send(ctx context.Context, ops SendOps, p Prompt) (Delivery, error)

Send steers the running turn, else prompts, else holds p until the turn ends.

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

type Prompter interface {
	PromptSession(ctx context.Context, p Prompt) error
}

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

func (s *Session) AnswerPermission(ctx context.Context, permissionID string, d Decision) error

AnswerPermission routes a decision back to the vendor.

func (*Session) Argv

func (s *Session) Argv() []string

Argv is the child command line (ledger evidence).

func (*Session) Close

func (s *Session) Close(ctx context.Context) error

Close runs the graceful sequence and waits for the event channel to drain.

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done is closed when the session ends and the event channel is closed.

func (*Session) Err

func (s *Session) Err() error

Err returns the first failure the session recorded, if any.

func (*Session) Events

func (s *Session) Events() <-chan Event

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) Harness

func (s *Session) Harness() string

Harness is the session's harness name.

func (*Session) ID

func (s *Session) ID() string

ID is the vendor session id; it may be empty until init.

func (*Session) Interrupt

func (s *Session) Interrupt(ctx context.Context) error

Interrupt is the Session method: a protocol interrupt where available, a signal otherwise.

func (*Session) InterruptTurn

func (s *Session) InterruptTurn(ctx context.Context) error

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) KillTree

func (s *Session) KillTree() error

KillTree escalates straight to a hard kill of the process tree.

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) PID

func (s *Session) PID() int

PID is the child process id (0 for in-process sessions).

func (*Session) Pgid

func (s *Session) Pgid() int

Pgid is the child's process group.

func (*Session) Prompt

func (s *Session) Prompt(ctx context.Context, p Prompt) error

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) Provider

func (s *Session) Provider() string

Provider is the harness name (Session interface).

func (*Session) Send added in v0.5.0

func (s *Session) Send(ctx context.Context, p Prompt) (Delivery, error)

Send steers the running turn, else prompts, else holds p and sends it when the turn ends.

func (*Session) SetID

func (s *Session) SetID(id string)

SetID records the vendor session id a driver learned or pre-assigned.

func (*Session) Turn

func (s *Session) Turn() int

Turn is the number of user turns this session has written.

func (*Session) WriteFrame

func (s *Session) WriteFrame(frame []byte) error

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

type SteerAdapter interface {
	Steer(ctx context.Context, p Prompt) error
}

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.

const (
	ToolRead   ToolKind = "read"
	ToolEdit   ToolKind = "edit"
	ToolExec   ToolKind = "exec"
	ToolMCP    ToolKind = "mcp"
	ToolSearch ToolKind = "search"
	ToolOther  ToolKind = "other"
)

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) Harness

func (w *Writer) Harness() string

Harness is the harness name the session runs.

func (*Writer) SetSessionID

func (w *Writer) SetSessionID(id string)

SetSessionID records the vendor session id learned on the wire.

func (*Writer) Write

func (w *Writer) Write(b []byte) error

Write sends one or more frames to the child.

type WriterSetter

type WriterSetter interface {
	SetWriter(*Writer)
}

WriterSetter is implemented by adapters that need the stdin writer before Handshake runs (every JSON-RPC driver).

Jump to

Keyboard shortcuts

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