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

statefile

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package statefile reads and writes the append-only files that hold an agent session. A record is one JSON header line, a body of exactly len bytes, and a newline. The body is never escaped.

Index

Constants

This section is empty.

Variables

View Source
var ErrTorn = errors.New("torn record")

Functions

func Copy

func Copy(src, dst string, n int) error

Copy makes dst from records 1 through n-1 of src, byte for byte. The prefix of an append-only file never changes, so the copy is the same value under a new name.

func Encode

func Encode(r Record) ([]byte, error)

Encode is the bytes of one record: header line, body, newline.

func NewID

func NewID() string

func Prompt

func Prompt(chain []Record) int

Prompt is the size of the last step's prompt in tokens: what the context costs now. Input excludes cache reads and writes on every provider.

func ValidID

func ValidID(id string) bool

ValidID is true for what NewID makes. Ids from outside become paths, so anything else is refused before it reaches the filesystem.

Types

type Conf

type Conf struct {
	Model   string   `json:"model"`
	Tools   string   `json:"tools"`
	Workers []Worker `json:"workers"`
	Context int      `json:"context"`
	Input   []string `json:"input,omitempty"`
}

Conf is the body of the config record, record 2, fixed for the session's life. Model is one provider/model string. Context is the token limit past which the harness refuses to step. Input is the media types read hands to the model as media; text is always text, and any other file is read as text.

type File

type File struct {
	Path string
	// contains filtered or unexported fields
}

File is a state file open for appending. One writer per file.

func Create

func Create(path string, config []byte) (*File, error)

Create makes a new file whose first two records are start and config.

func Open

func Open(path string) (*File, error)

Open opens an existing file for appending. A torn final record is cut off.

func (*File) Append

func (sf *File) Append(r Record) error

Append writes one record and fills in n, id, time, and len.

func (*File) Close

func (sf *File) Close() error

func (*File) N

func (sf *File) N() int

N is the index of the last record written.

type Header struct {
	N    int       `json:"n"`
	Kind Kind      `json:"kind"`
	ID   string    `json:"id"`
	Time time.Time `json:"time"`
	Len  int       `json:"len"`
	Type string    `json:"type,omitempty"`

	Step     string `json:"step,omitempty"`     // text, thinking, call: the step that closes it
	Provider string `json:"provider,omitempty"` // thinking: who signed it. step: who served it

	For        string `json:"for,omitempty"`         // result, error: the record it answers
	Exit       *int   `json:"exit,omitempty"`        // result of run
	Truncated  bool   `json:"truncated,omitempty"`   // result
	FullOutput string `json:"full_output,omitempty"` // result: path in worker scratch

	Via    string `json:"via,omitempty"`    // message: connector name. error: who stopped the session
	Source string `json:"source,omitempty"` // system: where the text came from

	Upto    int             `json:"upto,omitempty"`    // step: last record in its context
	Model   string          `json:"model,omitempty"`   // step
	Harness string          `json:"harness,omitempty"` // step: version that built the request
	Request string          `json:"request,omitempty"` // step: sha256 of the request bytes
	Usage   *Usage          `json:"usage,omitempty"`   // step
	Cache   json.RawMessage `json:"cache,omitempty"`   // step: provider cache markers
}

Header is the JSON line before every body. Fields beyond the first six belong to particular kinds and are omitted otherwise.

type Kind

type Kind string
const (
	Start    Kind = "start"
	Config   Kind = "config"
	System   Kind = "system"
	Message  Kind = "message"
	Text     Kind = "text"
	Thinking Kind = "thinking"
	Call     Kind = "call"
	Step     Kind = "step"
	Result   Kind = "result"
	Error    Kind = "error"
)

type Record

type Record struct {
	Header
	Body []byte
}

func Build

func Build(chain []Record) ([]Record, int)

Build reorders a file into context order and returns it with the index the next step's upto must carry. File order is time order; the API wants each step's results directly after it. So for each step: the results it saw, then the messages it saw as one user turn, then its blocks, then the step record itself. Blocks no step closed are dropped. Start and config never enter.

func Decode

func Decode(br *bufio.Reader) (Record, error)

Decode reads one record. io.EOF at a record boundary is returned as is. EOF anywhere inside a record is ErrTorn.

func LastStep

func LastStep(chain []Record) *Record

LastStep is the newest step record, or nil.

func Read

func Read(path string) ([]Record, error)

Read returns every whole record in a file. A torn final record is dropped.

func Waiting

func Waiting(chain []Record) []Record

Waiting returns the calls closed by a step that have no result, in file order.

type Sessions

type Sessions struct {
	Dir string
}

Sessions is the directory that holds one state file per session, named by its id. The filesystem is the registry.

func (Sessions) Copy

func (s Sessions) Copy(from, id string, n int) error

Copy creates session id from records 1 through n-1 of session from. Fork and revert are both this call.

func (Sessions) List

func (s Sessions) List() ([]string, error)

List returns every session id: the file names.

func (Sessions) Load

func (s Sessions) Load(id string) ([]Record, error)

Load returns a session's records. A file with none is a create that died before its first write, not a session.

func (Sessions) Open

func (s Sessions) Open(id string) (*File, error)

Open opens a session's file for appending.

func (Sessions) Path

func (s Sessions) Path(id string) string

func (Sessions) Start

func (s Sessions) Start(id string, config []byte) (*File, error)

Start creates a session: start, then config.

type Status

type Status string
const (
	StatusOpen        Status = "open"        // a message or result is unaddressed. needs a step
	StatusClosed      Status = "closed"      // the last step addressed everything and made no calls
	StatusInterrupted Status = "interrupted" // a closed call has no result and nobody holds the lock
	StatusFailed      Status = "failed"      // the last record is an error
	StatusStepping    Status = "stepping"    // the harness holds the session. Never derived from the file
)

func Derive

func Derive(chain []Record) Status

Derive reads status off the tip. Stepping is the lock's word, not the file's, so a caller that holds the lock knows better than this.

type Usage

type Usage struct {
	Input      int `json:"input"`
	Output     int `json:"output"`
	CacheRead  int `json:"cache_read,omitempty"`
	CacheWrite int `json:"cache_write,omitempty"`
}

Usage counts tokens. Input excludes cache reads and writes on every provider, so Input + CacheRead + CacheWrite is the prompt.

type Worker

type Worker struct {
	Name   string   `json:"name"`
	Drives []string `json:"drives,omitempty"`
}

Worker is one worker the session may use and the drives it has. A drive is a directory at the same path on every worker that lists it; a path only one worker lists is a local directory used as one.

Jump to

Keyboard shortcuts

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