Documentation
¶
Overview ¶
Package agentsession implements the Agent Session Format: an append-only, tree-structured JSONL record of one agent session whose conversation payloads are Open Responses items. The format is specified in docs/rfcs/0001-agent-session-format.md; this package is its reference implementation.
Shape ¶
A session file is a header line followed by entries, one JSON object per line. Entries form a tree through their id and parent members, so a branch is a child of an earlier entry, in place, and an abandoned branch stays in the file. Header and Entry are the two line shapes; the concrete entry types are ItemEntry (one Open Responses item, verbatim), ResponseEntry (the envelope of one model call), ConfigEntry (a delta to request settings), CompactionEntry and BranchSummaryEntry (summaries that enter context), and the out-of-context LabelEntry, InfoEntry, EnvEntry, OutcomeEntry, LinkEntry and CustomEntry. Namespaced types decode to UnknownEntry and are written back byte for byte, as are namespaced items inside an item entry.
Sessions ¶
Session is the tree in memory: Read loads one, Write emits one, and Session.Append adds an entry as a child of the current leaf. Session.Branch moves the leaf so the next append forks; a fresh root follows Session.ResetLeaf. A file cut short by a crash still loads, and Session.Truncated reports the broken line.
Context ¶
Session.ContextAt runs the format's context algorithm: it walks the path to an entry, replays config entries into Settings, applies the last compaction and returns the item list a model call there would receive. Settings.Request turns that into the canonical openresponses.Request, and RequestHash hashes it as the format defines (RFC 8785 canonical JSON, SHA-256). Session.Verify checks a stored response's hash against the rebuilt request.
Stores ¶
Store is the persistence interface; MemoryStore is the in-memory one and the jsonl subpackage is the file store. The storetest subpackage is the conformance suite every store runs.
Export ¶
The export subpackage turns a session's root-to-leaf paths into ATIF documents, using the types in the atif subpackage, with the raw items carried in the extras so nothing is lost.
Index ¶
- Constants
- Variables
- func GitRevision(dir string) (string, error)
- func HashBytes(data []byte) string
- func HashFile(path string) (string, error)
- func HashFiles(dir string, paths ...string) (map[string]string, error)
- func HashRequestJSON(data []byte) (string, error)
- func InContext(e Entry) bool
- func IsExtension(typ string) bool
- func MarshalEntry(e Entry) ([]byte, error)
- func NewEntryID() string
- func NewSessionID() string
- func ParseFormat(format string) (major, minor int, err error)
- func RecordResponse(ctx context.Context, store Store, sessionID string, req openresponses.Request, ...) (string, error)
- func RequestHash(req openresponses.Request) (string, error)
- func ToolName(t openresponses.Tool) string
- func Write(w io.Writer, s *Session) error
- type BranchSummaryEntry
- type CompactionEntry
- type ConfigEntry
- type Context
- type CustomEntry
- type Entry
- type EntryBase
- type EnvEntry
- func (e *EnvEntry) AddRead(path, hash string)
- func (e *EnvEntry) AddTool(name, version string)
- func (e *EnvEntry) AddWritten(path, hash string)
- func (*EnvEntry) EntryType() string
- func (e *EnvEntry) MarshalJSON() ([]byte, error)
- func (e *EnvEntry) SetGit(dir string, dirty bool) error
- func (e *EnvEntry) UnmarshalJSON(data []byte) error
- type FileHashes
- type Harness
- type Header
- type InfoEntry
- type ItemEntry
- type LabelEntry
- type LinkEntry
- type ListFilter
- type MemoryStore
- func (m *MemoryStore) Append(ctx context.Context, sessionID string, e Entry) (string, error)
- func (m *MemoryStore) Create(_ context.Context, h Header) (*Session, error)
- func (m *MemoryStore) Delete(_ context.Context, id string) error
- func (m *MemoryStore) List(_ context.Context, f ListFilter) iter.Seq2[Summary, error]
- func (m *MemoryStore) Open(_ context.Context, id string) (*Session, error)
- type OutcomeEntry
- func (*OutcomeEntry) EntryType() string
- func (e *OutcomeEntry) MarshalJSON() ([]byte, error)
- func (e *OutcomeEntry) UnmarshalJSON(data []byte) error
- func (e *OutcomeEntry) WithDetails(v any) *OutcomeEntry
- func (e *OutcomeEntry) WithLabel(label string) *OutcomeEntry
- func (e *OutcomeEntry) WithScore(score float64) *OutcomeEntry
- type ResponseEntry
- type Session
- func (s *Session) Append(e Entry) (string, error)
- func (s *Session) Branch(id string) error
- func (s *Session) Children(id string) []string
- func (s *Session) Compact(firstKept string, summary openresponses.Item) (*CompactionEntry, error)
- func (s *Session) Context() (Context, error)
- func (s *Session) ContextAt(id string) (Context, error)
- func (s *Session) Entries() []Entry
- func (s *Session) Entry(id string) (Entry, bool)
- func (s *Session) Header() Header
- func (s *Session) ID() string
- func (s *Session) Labels() map[string]string
- func (s *Session) Leaf() string
- func (s *Session) Leaves() []string
- func (s *Session) Len() int
- func (s *Session) Name() string
- func (s *Session) Path(id string) []Entry
- func (s *Session) RequestContext(id string) (Context, error)
- func (s *Session) ResetLeaf()
- func (s *Session) Roots() []string
- func (s *Session) SummarizeBranch(from string, summary openresponses.Item) (*BranchSummaryEntry, error)
- func (s *Session) Truncated() *TruncatedLine
- func (s *Session) Verify(id string) error
- type Settings
- type Store
- type Summary
- type TruncatedLine
- type UnknownEntry
- type VCS
Constants ¶
const ( TypeItem = "item" TypeResponse = "response" TypeConfig = "config" TypeCompaction = "compaction" TypeBranchSummary = "branch_summary" TypeLabel = "label" TypeInfo = "info" TypeEnv = "env" TypeOutcome = "outcome" TypeLink = "link" TypeCustom = "custom" )
Entry types defined by the format. Any other type of the form "ns:name" is an extension and decodes to UnknownEntry.
const ( RelSubsession = "subsession" RelForkOf = "fork_of" RelContinuedIn = "continued_in" )
Relations a LinkEntry may carry.
const ( OutcomeFeedback = "feedback" OutcomeTest = "test" OutcomeTask = "task" OutcomeToolError = "tool_error" OutcomeCustom = "custom" )
Kinds an OutcomeEntry may carry.
const ( MediaInline = "inline" MediaSidecar = "sidecar" )
Media storage modes named by the header.
const Format = "agentsession/0.1"
Format is the session format version this package writes.
const FormatMajor = 0
FormatMajor is the major version of the format this package reads. Any minor version of it is accepted; files are migrated in memory.
const HashPrefix = "sha256:"
HashPrefix precedes the hexadecimal digest in a request hash.
const Payload = "openresponses/" + openresponses.SpecVersion
Payload is the payload profile this package writes: Open Responses items at the specification version openresponses targets.
Variables ¶
var ErrDuplicateEntry = errors.New("agentsession: duplicate entry id")
ErrDuplicateEntry is returned when an appended entry reuses an ID.
var ErrHashMismatch = errors.New("agentsession: request hash mismatch")
ErrHashMismatch is returned by Session.Verify when the rebuilt request does not hash to the recorded value.
var ErrNoEntry = errors.New("agentsession: no such entry")
ErrNoEntry is returned when an entry ID is not in the session.
var ErrNoSession = errors.New("agentsession: no such session")
ErrNoSession is returned when a session ID is not in the store.
var ErrNotGit = errors.New("agentsession: not a git checkout")
ErrNotGit is returned by GitRevision when dir is not inside a git checkout.
var ErrSessionExists = errors.New("agentsession: session already exists")
ErrSessionExists is returned when Create is given an ID already in the store.
var ErrUnsupportedFormat = errors.New("agentsession: unsupported format")
ErrUnsupportedFormat is returned when a header names a format this package cannot read.
Functions ¶
func GitRevision ¶
GitRevision returns the commit HEAD points at for the checkout containing dir, reading .git directly so no git binary is needed. It follows symbolic refs through loose refs and packed-refs and handles worktrees and submodules whose .git is a file.
func HashFile ¶
HashFile returns the content hash of a file in the form the env entry uses: "sha256:" followed by lowercase hex.
func HashFiles ¶
HashFiles hashes each path, keyed as given. Paths are hashed as they are; callers that want keys relative to a directory pass them that way and resolve against dir.
func HashRequestJSON ¶
HashRequestJSON computes the request hash of an already-encoded request. Member order and whitespace in data do not matter.
func InContext ¶
InContext reports whether an entry contributes an item to the model context: item, branch_summary and compaction entries do. Whether a compaction is actually selected depends on the path; see Session.ContextAt.
func IsExtension ¶
IsExtension reports whether typ is a namespaced extension type.
func MarshalEntry ¶
MarshalEntry encodes one entry as a single JSON line without the trailing newline. The envelope members come first in a fixed order, then the type's members, then any unknown members in key order.
func NewEntryID ¶
func NewEntryID() string
NewEntryID returns a short random entry ID: eight hexadecimal characters. Session.Append regenerates on the rare collision within a file, so callers need not check.
func NewSessionID ¶
func NewSessionID() string
NewSessionID returns a UUIDv7 in its canonical text form. The leading 48 bits are the current Unix time in milliseconds, so IDs sort by creation time; the rest is random.
func ParseFormat ¶
ParseFormat splits a format string such as "agentsession/0.1" into its major and minor versions.
func RecordResponse ¶
func RecordResponse(ctx context.Context, store Store, sessionID string, req openresponses.Request, resp *openresponses.Response, latency time.Duration) (string, error)
RecordResponse writes one model call to a session: every output item of resp as an item entry carrying resp.ID, then the response entry with the response's model, status, usage, incomplete details, error, the hash of req and the latency. req must be the request as it was sent, so the recorded hash is the one a reader rebuilds from the path; pass a zero latency to leave latency_ms out. It returns the ID of the response entry.
The caller records the user items and function call outputs that precede the request before calling this, as the format requires.
func RequestHash ¶
func RequestHash(req openresponses.Request) (string, error)
RequestHash computes the request hash the format defines: the request serialised with the JSON Canonicalization Scheme (RFC 8785) and digested with SHA-256, rendered as "sha256:" plus lowercase hex. The input must be the request as it was sent, passthrough members included, because those reached the model.
func ToolName ¶
func ToolName(t openresponses.Tool) string
ToolName returns the name of a tool: the function name for a function tool, the "name" member of an extension tool when it has one, else "".
Types ¶
type BranchSummaryEntry ¶
type BranchSummaryEntry struct {
EntryBase `json:"-"`
From string `json:"from"`
Summary openresponses.Item `json:"summary"`
Usage *openresponses.Usage `json:"usage,omitempty"`
}
BranchSummaryEntry carries context across a branch switch. Its parent is where the new branch continues; From is the leaf that was left. It is in context through its summary.
func (*BranchSummaryEntry) EntryType ¶
func (*BranchSummaryEntry) EntryType() string
EntryType returns "branch_summary".
func (*BranchSummaryEntry) MarshalJSON ¶
func (e *BranchSummaryEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*BranchSummaryEntry) UnmarshalJSON ¶
func (e *BranchSummaryEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type CompactionEntry ¶
type CompactionEntry struct {
EntryBase `json:"-"`
// FirstKept names the earliest entry on the path that stays in
// context.
FirstKept string `json:"first_kept"`
// Summary is an item: the server's compaction item verbatim, or a
// message for a local summary.
Summary openresponses.Item `json:"summary"`
// Config is a full settings checkpoint so a reader need not replay
// config entries from before the compaction.
Config Settings `json:"config"`
TokensBefore int `json:"tokens_before,omitempty"`
Usage *openresponses.Usage `json:"usage,omitempty"`
}
CompactionEntry replaces the context before FirstKept with a summary. It is in context through its summary.
func (*CompactionEntry) EntryType ¶
func (*CompactionEntry) EntryType() string
EntryType returns "compaction".
func (*CompactionEntry) MarshalJSON ¶
func (e *CompactionEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*CompactionEntry) UnmarshalJSON ¶
func (e *CompactionEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type ConfigEntry ¶
type ConfigEntry struct {
EntryBase `json:"-"`
Model string `json:"model,omitempty"`
Instructions *string `json:"instructions,omitempty"`
Reasoning *openresponses.ReasoningConfig `json:"reasoning,omitempty"`
Text *openresponses.TextConfig `json:"text,omitempty"`
ToolsAdded openresponses.Tools `json:"tools_added,omitempty"`
ToolsRemoved []string `json:"tools_removed,omitempty"`
// Extra carries request members beyond the named ones, such as
// temperature or provider passthrough keys. A null value removes
// the key from the settings.
Extra map[string]json.RawMessage `json:"extra,omitempty"`
Replace bool `json:"replace,omitempty"`
}
ConfigEntry is a delta to request settings. Fields left at their zero value are unchanged; Replace discards all earlier config on the path before this one applies. The first entry on a root should be a config carrying full settings.
func ConfigFromRequest ¶
func ConfigFromRequest(req openresponses.Request) (*ConfigEntry, error)
ConfigFromRequest builds the full config entry for the settings a request was sent with: its model, instructions, reasoning, text and tools, with every other request member that is not about the one call (temperature, tool_choice, metadata, provider passthrough keys and so on) in Extra under its wire name. Replay of the result over empty settings followed by Settings.Request over the same input hashes to the same value as the request, which is what the first entry on a root should establish. Replace is set so the entry stands alone wherever it is placed.
func (*ConfigEntry) MarshalJSON ¶
func (e *ConfigEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*ConfigEntry) UnmarshalJSON ¶
func (e *ConfigEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type Context ¶
type Context struct {
Settings Settings
Items openresponses.Items
// Entries are the entries selected by the context algorithm, in
// order: after a compaction, the compaction itself, then the kept
// entries from FirstKept up to it, then everything after. Entries
// that contribute no item are included so a renderer can show them.
Entries []Entry
}
Context is what a model call at a point on a path receives: the replayed settings, the item list ready to be the request input and the entries the list was built from, for renderers.
func BuildContext ¶
BuildContext runs the context algorithm over a root-first path. Only the last compaction on the path is applied. FirstKept must name an entry on the path before the compaction.
type CustomEntry ¶
type CustomEntry struct {
EntryBase `json:"-"`
NS string `json:"ns"`
Data json.RawMessage `json:"data,omitempty"`
}
CustomEntry is application state that is not in context. State that the model should see is an ItemEntry holding a namespaced item.
func (*CustomEntry) MarshalJSON ¶
func (e *CustomEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*CustomEntry) UnmarshalJSON ¶
func (e *CustomEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type Entry ¶
Entry is one line of a session after the header. Concrete types are ItemEntry, ResponseEntry, ConfigEntry, CompactionEntry, BranchSummaryEntry, LabelEntry, InfoEntry, EnvEntry, OutcomeEntry, LinkEntry, CustomEntry and UnknownEntry. Decoded values are always pointers, so switch on *ItemEntry and so on. An entry must not be modified once it has been appended to a session; corrections are new entries.
func UnmarshalEntry ¶
UnmarshalEntry decodes one line, dispatching on its type. Types this package does not define decode to *UnknownEntry.
type EntryBase ¶
type EntryBase struct {
// ID is unique within the session. Session.Append assigns one when
// it is empty.
ID string
// Parent is the ID of the parent entry, or "" for a root.
Parent string
// Timestamp is when the entry was written.
Timestamp time.Time
// Unknown holds envelope members this package does not define,
// preserved so a later minor version's optional fields survive a
// rewrite. It is nil when there are none.
Unknown map[string]json.RawMessage
}
EntryBase is the envelope every entry carries.
type EnvEntry ¶
type EnvEntry struct {
EntryBase `json:"-"`
CWD string `json:"cwd,omitempty"`
VCS *VCS `json:"vcs,omitempty"`
Files *FileHashes `json:"files,omitempty"`
Tools map[string]string `json:"tools,omitempty"`
}
EnvEntry is a snapshot of the environment for replay.
func NewEnvEntry ¶
NewEnvEntry starts an env entry for a working directory. Use EnvEntry.SetGit, EnvEntry.AddRead and EnvEntry.AddWritten to fill it in.
func (*EnvEntry) AddWritten ¶
AddWritten records the hash of a file the session wrote.
func (*EnvEntry) MarshalJSON ¶
MarshalJSON emits the entry as one JSON object.
func (*EnvEntry) SetGit ¶
SetGit records the git revision of dir, read from its .git directory without running git, and whether the tree is known to be dirty. A directory that is not a git checkout leaves VCS unset and returns nil; other errors are returned.
func (*EnvEntry) UnmarshalJSON ¶
UnmarshalJSON decodes the entry.
type FileHashes ¶
type FileHashes struct {
Read map[string]string `json:"read,omitempty"`
Written map[string]string `json:"written,omitempty"`
}
FileHashes maps paths to content hashes ("sha256:...") for files read and written.
type Header ¶
type Header struct {
Format string `json:"format"`
ID string `json:"id"`
CreatedAt time.Time `json:"created_at"`
Payload string `json:"payload"`
Harness *Harness `json:"harness,omitempty"`
CWD string `json:"cwd,omitempty"`
ParentSession string `json:"parent_session,omitempty"`
Media string `json:"media,omitempty"`
// Extra holds header fields this package does not define.
Extra map[string]json.RawMessage `json:"-"`
}
Header is the first line of a session file. It is not part of the tree. Unknown fields decode into Extra and are written back, as the format requires of any tool that rewrites a file.
func (Header) MarshalJSON ¶
MarshalJSON emits the header with its type discriminator first and Extra flattened into the object.
func (*Header) UnmarshalJSON ¶
UnmarshalJSON decodes the header, keeping unknown fields in Extra.
type InfoEntry ¶
InfoEntry carries display metadata such as a session name. Further members are kept in Unknown.
func (*InfoEntry) MarshalJSON ¶
MarshalJSON emits the entry as one JSON object.
func (*InfoEntry) UnmarshalJSON ¶
UnmarshalJSON decodes the entry.
type ItemEntry ¶
type ItemEntry struct {
EntryBase `json:"-"`
// Item is the Open Responses item, verbatim. Extension items decode
// to *openresponses.UnknownItem and re-encode byte for byte.
Item openresponses.Item `json:"item"`
// ResponseID names the response this item belongs to when the item
// was model output; it matches ResponseEntry.ResponseID.
ResponseID string `json:"response,omitempty"`
// Visible is false for an item that is in context but that a
// renderer should hide. Nil means visible.
Visible *bool `json:"visible,omitempty"`
}
ItemEntry is one conversation item in the payload profile. It is in model context.
func NewItemEntry ¶
func NewItemEntry(item openresponses.Item) *ItemEntry
NewItemEntry builds an item entry.
func (*ItemEntry) MarshalJSON ¶
MarshalJSON emits the entry as one JSON object.
func (*ItemEntry) UnmarshalJSON ¶
UnmarshalJSON decodes the entry, dispatching the item through the openresponses item registry.
type LabelEntry ¶
type LabelEntry struct {
EntryBase `json:"-"`
Target string `json:"target"`
Label *string `json:"label"`
}
LabelEntry bookmarks another entry. A nil Label clears an earlier label on the same target.
func NewLabelEntry ¶
func NewLabelEntry(target, label string) *LabelEntry
NewLabelEntry builds a label on target; an empty label clears.
func (*LabelEntry) MarshalJSON ¶
func (e *LabelEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*LabelEntry) UnmarshalJSON ¶
func (e *LabelEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type LinkEntry ¶
type LinkEntry struct {
EntryBase `json:"-"`
Rel string `json:"rel"`
Session string `json:"session"`
// CallID ties a subsession to the function call that spawned it.
CallID string `json:"call_id,omitempty"`
}
LinkEntry references another session, for subagents and forks.
func NewLinkEntry ¶
NewLinkEntry builds a link to another session.
func NewSubsessionLink ¶
NewSubsessionLink builds the link entry the format prescribes for a subagent session spawned by the function call callID.
func (*LinkEntry) MarshalJSON ¶
MarshalJSON emits the entry as one JSON object.
func (*LinkEntry) UnmarshalJSON ¶
UnmarshalJSON decodes the entry.
type ListFilter ¶
type ListFilter struct {
// CWD matches the header's working directory exactly.
CWD string
// ParentSession matches sessions forked or spawned from the given
// one.
ParentSession string
// After and Before bound created_at, exclusive.
After, Before time.Time
// Limit caps the number of results; zero means no cap.
Limit int
}
ListFilter narrows a List. Zero fields do not filter.
func (ListFilter) Matches ¶
func (f ListFilter) Matches(h Header) bool
Matches reports whether a header passes the filter.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore keeps sessions in memory. It is the reference store for tests and for sessions that are never persisted.
func (*MemoryStore) Delete ¶
func (m *MemoryStore) Delete(_ context.Context, id string) error
Delete implements Store.
func (*MemoryStore) List ¶
func (m *MemoryStore) List(_ context.Context, f ListFilter) iter.Seq2[Summary, error]
List implements Store.
type OutcomeEntry ¶
type OutcomeEntry struct {
EntryBase `json:"-"`
Kind string `json:"kind"`
Target string `json:"target,omitempty"`
Score *float64 `json:"score,omitempty"`
Label string `json:"label,omitempty"`
Details json.RawMessage `json:"details,omitempty"`
}
OutcomeEntry is a signal about how the session, or a range of it, went.
func NewOutcomeEntry ¶
func NewOutcomeEntry(kind, target string) *OutcomeEntry
NewOutcomeEntry builds an outcome entry of the given kind about target, which may be "" for the session as a whole.
func (*OutcomeEntry) EntryType ¶
func (*OutcomeEntry) EntryType() string
EntryType returns "outcome".
func (*OutcomeEntry) MarshalJSON ¶
func (e *OutcomeEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*OutcomeEntry) UnmarshalJSON ¶
func (e *OutcomeEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
func (*OutcomeEntry) WithDetails ¶
func (e *OutcomeEntry) WithDetails(v any) *OutcomeEntry
WithDetails encodes v as the details and returns the entry, for chaining. An encoding failure leaves Details unset and is returned by the next Session.Append through MarshalEntry only if v cannot be marshalled at all, so callers should pass plain data.
func (*OutcomeEntry) WithLabel ¶
func (e *OutcomeEntry) WithLabel(label string) *OutcomeEntry
WithLabel sets the label and returns the entry, for chaining.
func (*OutcomeEntry) WithScore ¶
func (e *OutcomeEntry) WithScore(score float64) *OutcomeEntry
WithScore sets the score and returns the entry, for chaining.
type ResponseEntry ¶
type ResponseEntry struct {
EntryBase `json:"-"`
ResponseID string `json:"response_id"`
Model string `json:"model,omitempty"`
Status openresponses.ResponseStatus `json:"status"`
Usage *openresponses.Usage `json:"usage,omitempty"`
Incomplete *openresponses.IncompleteDetails `json:"incomplete,omitempty"`
Error *openresponses.ErrorPayload `json:"error,omitempty"`
RequestHash string `json:"request_hash,omitempty"`
LatencyMS int64 `json:"latency_ms,omitempty"`
}
ResponseEntry is the envelope of one model call, written after its output items. It is not in context.
func (*ResponseEntry) EntryType ¶
func (*ResponseEntry) EntryType() string
EntryType returns "response".
func (*ResponseEntry) MarshalJSON ¶
func (e *ResponseEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the entry as one JSON object.
func (*ResponseEntry) UnmarshalJSON ¶
func (e *ResponseEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the entry.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is one session in memory: the header, the entries in file order, the tree they form and the current leaf. It is safe for concurrent use. Entries are shared, not copied, and must not be modified after they are appended.
func New ¶
New creates an empty session. Header fields left empty are filled: a UUIDv7 ID, the current time, this package's format and payload.
func Read ¶
Read decodes a session from its JSONL form. A final line that does not parse is tolerated and reported through Session.Truncated; any other malformed line, a missing parent or a repeated ID is an error.
func (*Session) Append ¶
Append adds e to the tree and makes it the leaf. An empty ID is assigned; an empty Parent is set to the current leaf, so an explicit Parent branches in place; a zero Timestamp is set to now. The parent must exist and the ID must be new. On success e is owned by the session and must not be modified.
func (*Session) Branch ¶
Branch moves the leaf to id, so the next append becomes a child of that entry.
func (*Session) Children ¶
Children returns the IDs of the entries whose parent is id, in file order. Pass "" for the roots.
func (*Session) Compact ¶
func (s *Session) Compact(firstKept string, summary openresponses.Item) (*CompactionEntry, error)
Compact builds the compaction entry for the current leaf: FirstKept names the earliest entry on the path that stays in context, summary is the item that replaces everything before it, and the settings checkpoint is taken from the context at the leaf. The entry is not appended; set TokensBefore or Usage if known, then append it through the store.
func (*Session) ContextAt ¶
ContextAt builds the context at entry id, the request a model call appended after that entry would receive. An empty id yields an empty context.
func (*Session) Entries ¶
Entries returns the entries in file order. The slice is a copy; the entries are shared.
func (*Session) Labels ¶
Labels returns the current label of every labelled entry: the last label entry per target wins, and a null label clears.
func (*Session) Leaf ¶
Leaf returns the ID of the entry the next append will name as its parent, or "" when the next append starts a new root.
func (*Session) Leaves ¶
Leaves returns the IDs of the entries that have no children, in file order.
func (*Session) Path ¶
Path returns the entries from the root to id, root first, or nil when id is not in the session.
func (*Session) RequestContext ¶
RequestContext rebuilds the context of the request that produced the response entry id: the path to the entry with the response's own output items removed. Output items are the item entries directly before the response entry whose ResponseID matches.
func (*Session) ResetLeaf ¶
func (s *Session) ResetLeaf()
ResetLeaf clears the leaf, so the next append starts a new root.
func (*Session) SummarizeBranch ¶
func (s *Session) SummarizeBranch(from string, summary openresponses.Item) (*BranchSummaryEntry, error)
SummarizeBranch builds the branch summary that carries context from the abandoned leaf from to the current leaf, where the new branch continues. Move the leaf with Branch first, then append the result through the store; its parent is set on append.
func (*Session) Truncated ¶
func (s *Session) Truncated() *TruncatedLine
Truncated reports the final line of the file this session was read from when that line did not parse, or nil. A truncated line is what a crash mid-append leaves behind; the entries before it are intact.
type Settings ¶
type Settings struct {
Model string `json:"model,omitempty"`
Instructions string `json:"instructions,omitempty"`
Reasoning openresponses.ReasoningConfig `json:"reasoning,omitzero"`
Text openresponses.TextConfig `json:"text,omitzero"`
Tools openresponses.Tools `json:"tools,omitempty"`
// Extra carries request members beyond the named ones, keyed by
// their wire name.
Extra map[string]json.RawMessage `json:"extra,omitempty"`
}
Settings are the request settings in force at a point on a path: the result of replaying config entries. The JSON form is the full-config checkpoint a compaction entry carries.
func (Settings) Apply ¶
func (s Settings) Apply(c *ConfigEntry) Settings
Apply returns the settings after the delta c. The receiver is not modified.
func (Settings) Request ¶
func (s Settings) Request(items openresponses.Items) (openresponses.Request, error)
Request builds the canonical request for these settings over items: store false and no previous_response_id, as the context algorithm requires. Extra members ride in Request.Extra and are flattened on encode.
type Store ¶
type Store interface {
// Create starts a new session from h, filling empty header fields.
Create(ctx context.Context, h Header) (*Session, error)
// Open loads the session with the given ID.
Open(ctx context.Context, id string) (*Session, error)
// Append adds e to the session and returns its ID.
Append(ctx context.Context, sessionID string, e Entry) (string, error)
// List enumerates sessions matching f, newest first.
List(ctx context.Context, f ListFilter) iter.Seq2[Summary, error]
// Delete removes the session.
Delete(ctx context.Context, id string) error
}
Store persists sessions. Append is the only write to a session's content; the entry is added to the in-memory tree of the open session and made durable according to the store's policy. Sessions returned by Create and Open are shared with the store, so leaf moves through Session.Branch and Session.ResetLeaf are seen by later appends.
type Summary ¶
type Summary struct {
Header Header
// Path is where the session lives, for file-backed stores.
Path string
// Size is the stored size in bytes, when known.
Size int64
// Modified is when the session last changed, when known.
Modified time.Time
}
Summary describes a stored session without loading it.
type TruncatedLine ¶
type TruncatedLine struct {
// Line is the 1-based line number in the file.
Line int
// Data is the line as read, without its terminator.
Data []byte
// Err is the decode error.
Err error
}
TruncatedLine describes a final line that did not parse.
func (*TruncatedLine) Unwrap ¶
func (t *TruncatedLine) Unwrap() error
Unwrap returns the decode error.
type UnknownEntry ¶
type UnknownEntry struct {
EntryBase
Type string
Raw json.RawMessage
}
UnknownEntry is an entry whose type this package does not define, typically a namespaced extension. Raw holds the original line and is re-emitted verbatim. It is not in context.
func (*UnknownEntry) EntryType ¶
func (e *UnknownEntry) EntryType() string
EntryType returns the wire type.
func (*UnknownEntry) MarshalJSON ¶
func (e *UnknownEntry) MarshalJSON() ([]byte, error)
MarshalJSON emits the original bytes.
func (*UnknownEntry) UnmarshalJSON ¶
func (e *UnknownEntry) UnmarshalJSON(data []byte) error
UnmarshalJSON records the envelope and the raw bytes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package atif holds Go types for the Agent Trajectory Interchange Format (ATIF) v1.8, Harbor's interchange format for agent trajectories, as defined by its RFC and the Pydantic models in harbor.models.trajectories.
|
Package atif holds Go types for the Agent Trajectory Interchange Format (ATIF) v1.8, Harbor's interchange format for agent trajectories, as defined by its RFC and the Pydantic models in harbor.models.trajectories. |
|
Package export turns session trees into linear trajectories and ATIF documents.
|
Package export turns session trees into linear trajectories and ATIF documents. |
|
internal
|
|
|
jcs
Package jcs implements the JSON Canonicalization Scheme (RFC 8785): members sorted by UTF-16 code units, no insignificant whitespace, strings with the minimal escapes the scheme prescribes and numbers in the ECMAScript Number.prototype.toString form.
|
Package jcs implements the JSON Canonicalization Scheme (RFC 8785): members sorted by UTF-16 code units, no insignificant whitespace, strings with the minimal escapes the scheme prescribes and numbers in the ECMAScript Number.prototype.toString form. |
|
jsonx
Package jsonx holds the encoding/json helpers the agentsession packages share: escape-free marshalling, member joining for objects with unknown members, and struct key discovery.
|
Package jsonx holds the encoding/json helpers the agentsession packages share: escape-free marshalling, member joining for objects with unknown members, and struct key discovery. |
|
Package jsonl is the default session store: one append-only JSONL file per session under a root directory, laid out as
|
Package jsonl is the default session store: one append-only JSONL file per session under a root directory, laid out as |
|
otel
module
|
|
|
sqlite
module
|
|
|
Package storetest is the conformance suite for agentsession.Store implementations.
|
Package storetest is the conformance suite for agentsession.Store implementations. |