Documentation
¶
Overview ¶
Package session provides the core session model: id, title, created_at, and conversation history. File-based persistence lives in internal/agentapp (SessionStore).
Index ¶
- Variables
- func CtxWithSessionID(ctx context.Context, id string) context.Context
- func EnsureTitleFromFirstUserMessage(s *Session, maxLen int)
- func NewID() string
- func SessionIDFromContext(ctx context.Context) (string, bool)
- type ConversationStats
- type Session
- func (s *Session) AddCompaction(summary string, summarizedCount int)
- func (s *Session) Append(msg llm.Message) error
- func (s *Session) CacheReadShare() (share float64, ok bool)
- func (s *Session) HistoryMessages() []llm.Message
- func (s *Session) Notes() []agent.Note
- func (s *Session) PriorSummary() string
- func (s *Session) SetNotes(notes []agent.Note, iter int)
- func (s *Session) SetTodos(todos []agent.Todo, iter int)
- func (s *Session) Todos() []agent.Todo
- func (s *Session) Usage() llm.Usage
- type SessionItem
- type ToolStats
Constants ¶
This section is empty.
Variables ¶
var ErrSessionNotFound = errors.New("session not found")
ErrSessionNotFound is returned when a session file does not exist.
Functions ¶
func CtxWithSessionID ¶
CtxWithSessionID returns a context that carries the given session ID.
func EnsureTitleFromFirstUserMessage ¶
EnsureTitleFromFirstUserMessage sets the session title from the first user message if the title is empty, truncated to maxLen runes. No-op otherwise.
Types ¶
type ConversationStats ¶
type ConversationStats struct {
// UserMessages counts messages the user actually wrote. A background
// event travels as a user-role message because no provider has a portable
// role for one, and counting those as things the user said would inflate
// the number that reads most like effort.
UserMessages int
// BackgroundMessages counts the user-role messages that carry a Source:
// command results, subagent results, monitor events.
BackgroundMessages int
// AssistantTurns counts assistant messages, including the ones whose whole
// content was a tool call.
AssistantTurns int
// ToolCalls counts calls the assistant issued. ToolResults counts the
// results that came back; the two differ when a run was cut short between
// the call and its result.
ToolCalls int
ToolResults int
// Tools is the per-tool breakdown, heaviest by result bytes first. A tool
// the assistant called but whose result never arrived still appears, with
// zero bytes.
Tools []ToolStats
// TextBytes is what the conversation's own text weighs — user prompts and
// assistant replies. ToolResultBytes is what came back from tools.
//
// Kept apart because they are spent differently: the first is the
// conversation, the second is what the run pulled into it, and on a long
// agent session the second is usually the larger by an order of magnitude.
TextBytes int
ToolResultBytes int
// CompactedMessages is how many messages sit before the compaction
// boundary — summarized away, still stored.
CompactedMessages int
// Notes and Todos are the durable state the session carries.
Notes int
Todos int
}
ConversationStats is the shape of a session's history: who said how much, which tools ran, and how many bytes each of them put back into the context.
It is derived from the stored messages alone and needs no run to be live, so it answers for a session whose traces have been removed. What it cannot answer is anything time-shaped — durations, run boundaries, which model ran — because the history carries no timestamps. That half comes from the traces.
func Stats ¶
func Stats(s *Session) ConversationStats
Stats folds a session's stored history into its shape.
A tool result names the call it answers rather than the tool it came from, so results are attributed by walking the assistant tool calls first and looking each result's call id up. A result whose call is not in the history — the assistant message was compacted out from under it — is counted in the totals under an empty name rather than dropped: the bytes are in the context either way.
type Session ¶
type Session struct {
ID string `json:"id"`
Title string `json:"title,omitempty"`
CreatedAt time.Time `json:"created_at"`
Messages []llm.Message `json:"messages,omitempty"`
PromptTokens int `json:"prompt_tokens,omitempty"`
CompletionTokens int `json:"completion_tokens,omitempty"`
// CacheReadTokens and CacheWriteTokens are the session's provider-reported
// cached prompt. They break PromptTokens down rather than add to it, so a
// reader totalling a session must not sum all three.
CacheReadTokens int `json:"cache_read_tokens,omitempty"`
CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
// Cost is what this session is estimated to have spent, accumulated as it
// ran. It is a running total rather than something recomputed on read,
// because the rates that applied to an earlier turn are not necessarily
// the ones configured now. Nil means nothing here was priced.
Cost *llm.Cost `json:"cost,omitempty"`
// CostIncomplete says the total above is missing part of the session: a
// turn ran against an unpriced model, or against one quoted in a different
// currency, which BuildMax does not convert. A number that silently
// dropped half a session is worse than one labelled incomplete.
CostIncomplete bool `json:"cost_incomplete,omitempty"`
// CompactionIdx is the index into Messages where the latest compaction boundary falls.
// Messages before this index have been summarized into CompactionSummary.
// Zero means no compaction has occurred.
CompactionIdx int `json:"compaction_idx,omitempty"`
CompactionSummary string `json:"compaction_summary,omitempty"`
// NoteEntries and TodoEntries are durable session state: unlike a tool result, they are
// not messages, so compaction cannot take them. The fields are named apart from the
// Notes/Todos accessors that implement agent.NoteStore; the JSON keys are the plain names.
NoteEntries []agent.Note `json:"notes,omitempty"`
TodoEntries []agent.Todo `json:"todos,omitempty"`
// AdditionalSystemPrompt records the extra system-prompt text this session actually ran
// under. It is a record — for the trace, and so a resumed session does not silently lose
// its identity when the flag that set it is not repeated — not the authority. Whoever
// assembles a run resolves it afresh, and the last writer wins.
AdditionalSystemPrompt string `json:"additional_system_prompt,omitempty"`
}
Session holds conversation history (user, assistant, tool messages) and metadata. The system message is not stored; it is prepended at call time by the agent. JSON tags match the on-disk session file format (snake_case).
func NewSession ¶
NewSession creates a new session with a generated UUID, the given title, created_at set to the current time, and empty history. Title may be empty.
func NewSessionFromData ¶
func NewSessionFromData(id, title string, createdAt time.Time, messages []llm.Message, promptTokens, completionTokens int) *Session
NewSessionFromData constructs a Session from persisted data.
func (*Session) AddCompaction ¶
AddCompaction advances the compaction boundary by summarizedCount messages and stores the summary. The summary is expected to subsume any earlier one, so replacing is correct. Implements agent.CompactionHistory so RunLoop can persist the boundary across turns.
func (*Session) CacheReadShare ¶
CacheReadShare is the fraction of the session's prompt that was served from a provider's cache, and ok=false when there is nothing to divide or the provider reported no cache usage at all. A zero share and an unreported one are different facts: only the first says the cache missed.
func (*Session) HistoryMessages ¶
HistoryMessages returns the LLM-facing message slice. When a compaction boundary exists, only messages from CompactionIdx onward are returned; earlier messages have been summarized.
func (*Session) PriorSummary ¶
PriorSummary returns the summary stored by the most recent compaction, or "" when this session has never been compacted. Implements agent.CompactionHistory so RunLoop can feed the previous summary back into the next compaction instead of discarding what it covered.
func (*Session) SetNotes ¶
SetNotes replaces the session's notes, preserving the age of entries whose text is unchanged so a rewrite of the list does not make every entry look new. Implements agent.NoteStore.
func (*Session) SetTodos ¶
SetTodos replaces the session's task list, preserving the age of entries whose content and status are both unchanged. Implements agent.NoteStore.
type SessionItem ¶
type SessionItem struct {
ID string `json:"id"`
Title string `json:"title,omitempty"`
Workspace string `json:"workspace,omitempty"`
CreatedAt string `json:"created_at"` // RFC3339
Pinned bool `json:"pinned,omitempty"`
}
SessionItem is one session's metadata in the session index file (sessions.json).
type ToolStats ¶
type ToolStats struct {
Name string
// Calls is how many times the assistant asked for it.
Calls int
// ResultBytes is what its results put back into the context. This is the
// number that answers which tool is filling the context window, and it is
// not derivable from the call count: one search can outweigh fifty reads.
ResultBytes int
// MaxResultBytes is the largest single result, so one outlier is not
// hidden inside an average.
MaxResultBytes int
}
ToolStats is one tool's share of a session.