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

holder

package
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package holder owns the PTY or the agent-wire session of one session, so that the session lives through a restart of the visor. It imports nothing from this repository: an old holder keeps its protocol until its session ends.

Index

Constants

View Source
const (
	Protocol    = 2
	MinProtocol = 1
)

Protocol is the version of the holder protocol of this build. Version 2 adds the wire mode. MinProtocol is the oldest holder that a client speaks to.

View Source
const CodeEnding = "ending"

CodeEnding is the reply code of a holder that ends at idle.

View Source
const (
	DefaultRing = 256 << 10
)

Defaults and limits.

View Source
const MaxSocketPath = 103

MaxSocketPath is the macOS limit of a Unix socket path, less one.

Variables

View Source
var ErrProtocol = errors.New("holder: unknown protocol")

ErrProtocol means that the other side speaks a holder protocol that this build does not know.

Functions

func Run

func Run(ctx context.Context, c Config) error

Run starts the process in a PTY, or the agent-wire session of a wire holder, and serves the socket until the process ends. When ctx ends, Run ends the process first.

Types

type Call

type Call struct {
	ID        uint64              `json:"id"`
	Op        Op                  `json:"op"`
	Prompt    *agentwire.Prompt   `json:"prompt,omitempty"`
	RequestID string              `json:"request_id,omitempty"`
	Decision  *agentwire.Decision `json:"decision,omitempty"`
}

Call is one operation on the session of a wire holder.

type Client

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

Client is one connection of a visor to a holder.

func Dial

func Dial(ctx context.Context, path string, from Cursor) (*Client, error)

Dial connects to the holder at path and exchanges the hellos. A wire holder sends the events after from, when from is of its run.

func (*Client) Ack

func (c *Client) Ack(seq uint64) error

Ack tells a wire holder that the client stored the events up to seq.

func (*Client) Call

func (c *Client) Call(call Call) error

Call sends one call to a wire holder. The reply comes as a MsgReply.

func (*Client) Close

func (c *Client) Close() error

Close closes the connection. The holder and its process keep running.

func (*Client) Hello

func (c *Client) Hello() Hello

Hello is the hello of the holder.

func (*Client) Input

func (c *Client) Input(p []byte) error

Input writes bytes to the PTY.

func (*Client) Kill

func (c *Client) Kill() error

Kill ends the process. The holder sends the exit message when it ends.

func (*Client) Read

func (c *Client) Read() (Msg, error)

Read waits for the next message from the holder.

func (*Client) Resize

func (c *Client) Resize(cols, rows int) error

Resize sets the size of the PTY.

type Config

type Config struct {
	ID   string `json:"id"`
	Mode Mode   `json:"mode,omitempty"`
	// Socket is the path of the holder socket, mode 0600.
	Socket  string   `json:"socket"`
	Command []string `json:"command"`
	Dir     string   `json:"dir,omitempty"`
	// Env is the full env of the process, as KEY=value.
	Env  []string `json:"env,omitempty"`
	Cols int      `json:"cols,omitempty"`
	Rows int      `json:"rows,omitempty"`
	// Log gets all output, mode 0600. Empty writes no log.
	Log string `json:"log,omitempty"`
	// ExitFile gets the JSON Exit when the process ends, mode 0600.
	ExitFile string `json:"exit_file,omitempty"`
	// Ring is the size of the screen buffer in bytes. Zero is 256 KiB.
	Ring int `json:"ring,omitempty"`
	// Wire is the session of a wire holder.
	Wire *WireConfig `json:"wire,omitempty"`
	// Spool gets the events that no client stored when a wire holder ends,
	// mode 0600.
	Spool  string       `json:"spool,omitempty"`
	Logger *slog.Logger `json:"-"`
}

Config tells a holder what to run. The visor sends it as JSON on stdin, because Env can hold secrets.

func ReadConfig

func ReadConfig(r io.Reader, id string) (Config, error)

ReadConfig reads the config of the holder of session id from r.

type Cursor

type Cursor struct {
	Run string
	Seq uint64
}

Cursor is the last event of a wire holder run that a client has.

type Exit

type Exit struct {
	Code  int    `json:"code"`
	Idle  bool   `json:"idle,omitempty"`
	Last  uint64 `json:"last,omitempty"`
	Error string `json:"error,omitempty"`
}

Exit is the end of the process. Code is 128 plus the signal number when a signal ended it. Idle means that a wire holder closed its session at the end of a turn, and Last is the seq of its last event.

type Hello

type Hello struct {
	Protocol int    `json:"protocol"`
	Mode     Mode   `json:"mode,omitempty"`
	ID       string `json:"id,omitempty"`
	// PID is the holder process, and ChildPID the process in the PTY or the
	// vendor process.
	PID       int       `json:"pid,omitempty"`
	ChildPID  int       `json:"child_pid,omitempty"`
	Cols      int       `json:"cols,omitempty"`
	Rows      int       `json:"rows,omitempty"`
	StartedAt time.Time `json:"started_at,omitzero"`
	// Run names one run of a wire holder. Its event seq starts at 1.
	Run      string `json:"run,omitempty"`
	VendorID string `json:"vendor_id,omitempty"`
	// Status and Pending are the activity and the open requests of a wire
	// session.
	Status  agentwire.SessionStatus `json:"status,omitempty"`
	Pending []agentwire.Permission  `json:"pending,omitempty"`
	// After is the last event seq of Run that the client has. The holder
	// sends the events after it.
	After uint64 `json:"after,omitempty"`
}

Hello is the first message of each side. The holder sends its hello first, and the client answers with the protocol of the holder.

type Mode

type Mode string

Mode is the kind of a holder.

const (
	ModePTY  Mode = ""
	ModeWire Mode = "wire"
)

Modes.

type Msg

type Msg struct {
	Type MsgType
	// Data is the screen buffer of a snapshot, or the bytes of an output.
	Data  []byte
	Size  Size
	Exit  Exit
	Event WireEvent
	Reply Reply
}

Msg is one message from the holder.

type MsgType

type MsgType byte

MsgType is the type of one message on the holder socket.

const (
	MsgHello    MsgType = 1 // both ways: JSON Hello
	MsgSnapshot MsgType = 2 // holder: the screen buffer
	MsgOutput   MsgType = 3 // holder: new output
	MsgResized  MsgType = 4 // holder: JSON Size
	MsgExit     MsgType = 5 // holder: JSON Exit
	MsgInput    MsgType = 6 // client: bytes for the PTY
	MsgResize   MsgType = 7 // client: JSON Size
	MsgKill     MsgType = 8 // client: end the process
	// Version 2, wire mode.
	MsgEvent MsgType = 9  // holder: JSON WireEvent
	MsgAck   MsgType = 10 // client: JSON seq; the client stored the events up to it
	MsgCall  MsgType = 11 // client: JSON Call
	MsgReply MsgType = 12 // holder: JSON Reply
)

Messages. Each is type (1 byte) | length (4 bytes, big endian) | payload.

type Op

type Op string

Op is the operation of a call to a wire holder.

const (
	OpSend      Op = "send"
	OpInterrupt Op = "interrupt"
	OpAnswer    Op = "answer"
	OpClose     Op = "close"
)

Ops.

type Reply

type Reply struct {
	ID       uint64             `json:"id"`
	Delivery agentwire.Delivery `json:"delivery,omitempty"`
	Error    string             `json:"error,omitempty"`
	Code     string             `json:"code,omitempty"`
}

Reply is the result of a call. Code CodeEnding means that the holder ends at idle and takes no new call.

type Size

type Size struct {
	Cols int `json:"cols"`
	Rows int `json:"rows"`
}

Size is a terminal size in cells.

type Spool

type Spool struct {
	Run    string      `json:"run"`
	Events []WireEvent `json:"events"`
}

Spool is the content of Config.Spool: the events of run that no client stored.

func ReadSpool

func ReadSpool(path string) (Spool, error)

ReadSpool reads the spool of a wire holder.

type WireConfig

type WireConfig struct {
	Harness    string            `json:"harness"`
	Binary     string            `json:"binary,omitempty"`
	WorkingDir string            `json:"working_dir,omitempty"`
	Env        map[string]string `json:"env,omitempty"`
	Home       string            `json:"home,omitempty"`
	// Resume continues the vendor session VendorID.
	Resume       bool                       `json:"resume,omitempty"`
	VendorID     string                     `json:"vendor_id,omitempty"`
	Model        string                     `json:"model,omitempty"`
	Effort       string                     `json:"effort,omitempty"`
	Permissions  agentwire.PermissionPolicy `json:"permissions"`
	MCPServers   []agentwire.MCPServer      `json:"mcp_servers,omitempty"`
	Skills       []agentwire.Skill          `json:"skills,omitempty"`
	Instructions string                     `json:"instructions,omitempty"`
	ExtraArgs    []string                   `json:"extra_args,omitempty"`
	Raw          map[string]any             `json:"raw,omitempty"`
	// FrameLog gets each frame in and out, mode 0600.
	FrameLog string `json:"frame_log,omitempty"`
	// Ledger is the agent-wire process ledger of the session.
	Ledger        string `json:"ledger,omitempty"`
	ClientName    string `json:"client_name,omitempty"`
	ClientVersion string `json:"client_version,omitempty"`
	// Drivers replace agent-wire drivers when Run runs in the caller process.
	Drivers map[string]agentwire.Driver `json:"-"`
}

WireConfig is the agent-wire session of a wire holder.

type WireEvent

type WireEvent struct {
	Seq   uint64          `json:"seq"`
	Event agentwire.Event `json:"event"`
}

WireEvent is one agent-wire event with the seq of its holder run.

Jump to

Keyboard shortcuts

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