session

package
v0.0.369 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TranscriptFlagCompactionTail uint8 = 1 << iota
	TranscriptFlagEmptyBody
)

Transcript index flags describe durable rows without materializing bodies.

View Source
const TranscriptMaterializationMaxRanges = 32

Variables

View Source
var ErrNotFound = errors.New("session: not found")

ErrNotFound is returned when a lookup or update targets a row that does not exist (e.g., UpdateMessage against a deleted/never-persisted message ID).

View Source
var ErrTranscriptRevisionUnsupported = errors.New("session: transcript revision unsupported")

ErrTranscriptRevisionUnsupported indicates that a store does not support a mutation method that reports the exact transcript revision it commits.

Functions

func ApplyCompaction added in v0.0.234

func ApplyCompaction(ctx context.Context, store Store, sess *Session, full []Message, result *llm.CompactionResult) ([]Message, int, *Session, error)

ApplyCompaction persists a compaction result, appends the compacted rows to the caller's scrollback snapshot, returns the new active start index, refreshes session metadata when possible, and best-effort clears any persisted context estimate baseline so future turns don't seed context management with pre-compaction token counts. The full argument is the caller's scrollback snapshot and may be nil for non-UI owners that only need persistence.

func ApplyReasoningPersistencePolicy added in v0.0.258

func ApplyReasoningPersistencePolicy(msg llm.Message, cfg config.ReasoningConfig) llm.Message

ApplyReasoningPersistencePolicy removes display-only reasoning summary text when the user disabled summary persistence, while preserving provider replay identifiers/encrypted payloads. Raw reasoning is left unchanged because some providers use it as replay/debug metadata and display/export remain gated separately.

func ExpandShortID added in v0.0.52

func ExpandShortID(shortID string) string

ExpandShortID converts a short ID to a SQL LIKE pattern for prefix matching. Example: "240115-1430" -> "20240115-1430%"

func ExportToHTML added in v0.0.322

func ExportToHTML(sess *Session, messages []Message, opts ExportOptions) (string, error)

ExportToHTML renders a self-contained, interactive transcript document.

func ExportToMarkdown added in v0.0.56

func ExportToMarkdown(sess *Session, messages []Message, opts ExportOptions) string

ExportToMarkdown exports a session and its messages to a pretty markdown format.

func ExtractHandoverPath added in v0.0.317

func ExtractHandoverPath(prompt, dir string) string

ExtractHandoverPath recovers a handover file path embedded in a system prompt via {{handover_path}}. It matches the first path under dir with the "<date>-<slug>.md" shape. Returns "" when the prompt names no such file.

func FindMessagesByClientMessageIDs added in v0.0.363

func FindMessagesByClientMessageIDs(ctx context.Context, store Store, sessionID string, clientMessageIDs []string) (map[string]*Message, error)

FindMessagesByClientMessageIDs uses a batch capability when available and otherwise performs at most one full transcript scan.

func GetDBPath

func GetDBPath() (string, error)

GetDBPath returns the path to the sessions database.

func GetDataDir

func GetDataDir() (string, error)

GetDataDir returns the XDG data directory for term-llm. Uses $XDG_DATA_HOME if set, otherwise ~/.local/share

func GetHandoverDir added in v0.0.146

func GetHandoverDir(cwd string) (string, error)

GetHandoverDir returns the handover directory for the given working directory. The path is XDG_DATA_HOME/term-llm/handover/<basename>-<sha256[:6]>/ where the hash is computed from the absolute cwd to avoid collisions.

func GetHandoverPath added in v0.0.146

func GetHandoverPath(cwd, date string) (string, error)

GetHandoverPath returns a full handover file path with a random name like "2026-04-03-amber-creek-bloom.md". A fresh slug is generated per call so concurrent sessions in the same project get distinct plan files. The expanded system prompt is the durable per-session record of the path; use ExtractHandoverPath to recover it.

func GistFiles added in v0.0.324

func GistFiles(sess *Session, messages []Message, opts ExportOptions) (map[string]string, error)

GistFiles builds the canonical HTML and Markdown transcript files.

func GistPreviewURL added in v0.0.324

func GistPreviewURL(id string) string

GistPreviewURL returns the gisthost preview URL for a valid gist ID.

func HasCompactionBoundary added in v0.0.234

func HasCompactionBoundary(sess *Session) bool

HasCompactionBoundary reports whether a session has an explicit persisted compaction boundary. Checking the count (or a positive sequence from older persisted sessions) avoids treating a zero-value Session as compacted at sequence 0.

func IsRandomHandoverName added in v0.0.146

func IsRandomHandoverName(name string) bool

IsRandomHandoverName returns true if the filename matches the random 3-word pattern generated by GetHandoverPath and all three words are from the handoverWords list. This prevents LLM-generated descriptive slugs (e.g. "fix-auth-bug") from being treated as random and renamed repeatedly.

func LLMActiveMessages added in v0.0.234

func LLMActiveMessages(messages []Message, activeStart int, systemPrompt string) []llm.Message

LLMActiveMessages converts the active slice of session messages into LLM messages, injecting systemPrompt only when the active context doesn't already include a system message, then applies provider-safe conversation filtering.

func MaybeRenameHandover added in v0.0.146

func MaybeRenameHandover(ctx context.Context, path string, slugGen HandoverSlugGenerator) error

MaybeRenameHandover checks if the given handover file should be renamed. It renames when the file has a random-word name and contains >= 1000 bytes. After renaming, a symlink is created from the old path to the new file so that the system prompt path remains valid (preserving LLM cache).

slugGen is called to produce the new slug; if nil or if it returns an error, the rename is silently skipped.

func NewID

func NewID() string

NewID generates a unique session ID using a timestamp prefix and random suffix. Format: YYYYMMDD-HHMMSS-RANDOM (e.g., "20240115-143052-a1b2c3") This format:

  • Sorts chronologically by default
  • Is human-readable for debugging
  • Has enough randomness to prevent collisions

func ParseIDTime

func ParseIDTime(id string) time.Time

ParseIDTime extracts the timestamp from a session ID. Returns zero time if parsing fails.

func PrettifyHandoverName added in v0.0.317

func PrettifyHandoverName(ctx context.Context, path, description string, slugGen HandoverSlugGenerator) error

PrettifyHandoverName renames a random-named handover file to a short descriptive name derived from the session's first user message, so the file has a nice name from the start. The original random path — baked into the session's system prompt — keeps working via a symlink. When the agent has not written the file yet, an empty descriptive target is atomically reserved before the symlink is created so concurrent sessions cannot share a target.

slugGen receives the description and should return roughly two words; the result is sanitized and capped at two dash-separated words. Errors from slugGen are silently skipped — the file simply keeps its random name.

func RandomHandoverSlug added in v0.0.146

func RandomHandoverSlug() string

RandomHandoverSlug returns a string like "amber-creek-bloom" using crypto/rand for word selection.

func RenderExportReasoning added in v0.0.258

func RenderExportReasoning(part llm.Part, opts ExportOptions) string

RenderExportReasoning renders non-encrypted reasoning metadata according to explicit export options. Raw reasoning is never included unless requested.

func ResetContextEstimate added in v0.0.234

func ResetContextEstimate(ctx context.Context, store Store, sess *Session) error

ResetContextEstimate clears the persisted context estimate baseline for the session after compaction.

func ResolveDBPath added in v0.0.85

func ResolveDBPath(pathOverride string) (string, error)

ResolveDBPath resolves an optional DB path override. Empty path uses the default XDG location. Supports :memory: for ephemeral in-memory storage.

func ResolvePinnedHandoverPath added in v0.0.323

func ResolvePinnedHandoverPath(prompt string, candidateDirs ...string) (path string, pinned bool)

ResolvePinnedHandoverPath recovers the handover path assigned by the system prompt. Candidate directories support sessions whose effective directory and process working directory differ. The planner's assignment is also recovered across directory changes, but only when exactly one assignment points under term-llm's global handover root.

pinned is true when an assignment was found even if it was ambiguous. Callers must not fall back to scanning another file when pinned is true.

func ShortID

func ShortID(id string) string

ShortID returns a shortened version of the session ID for display. Example: "20240115-143052-a1b2c3" -> "240115-1430"

func TruncateSummary

func TruncateSummary(content string) string

TruncateSummary returns the first line of content, truncated to 100 chars.

func UpdateGeneratedTitle added in v0.0.320

func UpdateGeneratedTitle(ctx context.Context, store Store, sess *Session, shortTitle, longTitle string, generatedAt time.Time, basisMsgSeq int) error

UpdateGeneratedTitle persists generated title fields using a title-only fast path when available, and falls back to Store.Update for test/custom stores.

func UpdateGoal added in v0.0.321

func UpdateGoal(ctx context.Context, store Store, sessionID string, goal *Goal) error

UpdateGoal persists a session goal using a goal-only fast path when available, and falls back to Store.Get + Store.Update for custom stores.

func UpdateShare added in v0.0.324

func UpdateShare(ctx context.Context, store Store, sessionID string, share *ShareState) error

UpdateShare persists share metadata using a narrow update when available.

func UpdateStreamingMessage added in v0.0.289

func UpdateStreamingMessage(ctx context.Context, store Store, sessionID string, msg *Message, finalizeText bool) error

UpdateStreamingMessage updates an in-progress assistant message using the store's streaming-aware fast path when available, otherwise it falls back to Store.UpdateMessage.

Types

type ClientMessageBatchLookup added in v0.0.363

type ClientMessageBatchLookup interface {
	GetMessagesByClientMessageIDs(ctx context.Context, sessionID string, clientMessageIDs []string) (map[string]*Message, error)
}

ClientMessageBatchLookup retrieves durable first-party intents by identity.

type ClientMessageLookup added in v0.0.363

type ClientMessageLookup interface {
	GetMessageByClientMessageID(ctx context.Context, sessionID, clientMessageID string) (*Message, error)
}

ClientMessageLookup retrieves the durable owner of a first-party user intent. Implementations should return ErrNotFound when the identity is absent.

type CompactedTranscriptRevisionWriter added in v0.0.353

type CompactedTranscriptRevisionWriter interface {
	ReplaceCompactedMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)
}

CompactedTranscriptRevisionWriter reports the exact revision committed by an atomic compaction replacement.

type Config

type Config struct {
	Enabled          bool   `mapstructure:"enabled"`            // Master switch
	MaxAgeDays       int    `mapstructure:"max_age_days"`       // Auto-delete after N days (0=never)
	MaxCount         int    `mapstructure:"max_count"`          // Keep at most N sessions (0=unlimited)
	Path             string `mapstructure:"path"`               // Optional DB path override (supports :memory:)
	StripImageBase64 bool   `mapstructure:"strip_image_base64"` // Store path/metadata only for images with ImagePath (smaller DB, less portable)
	ReadOnly         bool   `mapstructure:"-"`                  // Open DB in read-only mode (skip schema init/cleanup)
}

Config holds session storage configuration.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default session configuration.

type ExportOptions added in v0.0.56

type ExportOptions struct {
	IncludeSystem             bool // Include system prompt in export
	IncludeReasoningSummaries bool // Include provider-sanctioned reasoning summaries
	IncludeRawReasoning       bool // Include raw reasoning; caller must enforce safety gate
}

ExportOptions configures session export.

type FallbackTranscriptIndexer added in v0.0.353

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

FallbackTranscriptIndexer adapts a Store without native revisioned transcript reads to the single web transcript protocol. Revisions are monotonic for the lifetime of the adapter and advance whenever the coherent message projection or compaction metadata changes.

func NewFallbackTranscriptIndexer added in v0.0.353

func NewFallbackTranscriptIndexer(store Store) *FallbackTranscriptIndexer

func (*FallbackTranscriptIndexer) GetMessagesByTranscriptRanges added in v0.0.353

func (f *FallbackTranscriptIndexer) GetMessagesByTranscriptRanges(ctx context.Context, sessionID string, ranges []TranscriptRange) (int64, []Message, error)

func (*FallbackTranscriptIndexer) GetTranscriptIndex added in v0.0.353

func (f *FallbackTranscriptIndexer) GetTranscriptIndex(ctx context.Context, sessionID string) (int64, []TranscriptIndexItem, error)

func (*FallbackTranscriptIndexer) GetTranscriptSnapshot added in v0.0.353

func (f *FallbackTranscriptIndexer) GetTranscriptSnapshot(ctx context.Context, sessionID string) (TranscriptSnapshot, error)

func (*FallbackTranscriptIndexer) TranscriptRev added in v0.0.353

func (f *FallbackTranscriptIndexer) TranscriptRev(ctx context.Context, sessionID string) (int64, error)

type GeneratedTitleUpdater added in v0.0.320

type GeneratedTitleUpdater interface {
	UpdateGeneratedTitle(ctx context.Context, id, shortTitle, longTitle string, generatedAt time.Time, basisMsgSeq int) error
}

GeneratedTitleUpdater is an optional Store capability for updating only the generated title fields. It avoids full-session Update writes from async title generation paths, where a stale in-memory Session snapshot could clobber concurrently updated metadata such as status or pinned state.

type Goal added in v0.0.321

type Goal struct {
	Objective       string     `json:"objective"`
	Status          GoalStatus `json:"status"`
	TokenBudget     int        `json:"token_budget,omitempty"`
	TokensUsed      int        `json:"tokens_used,omitempty"`
	TimeUsedSeconds int        `json:"time_used_seconds,omitempty"`
	CreatedAt       time.Time  `json:"created_at,omitempty"`
	UpdatedAt       time.Time  `json:"updated_at,omitempty"`
	CompletedAt     time.Time  `json:"completed_at,omitempty"`
	BlockedAt       time.Time  `json:"blocked_at,omitempty"`
	PausedAt        time.Time  `json:"paused_at,omitempty"`
	LastReason      string     `json:"last_reason,omitempty"`
	LastEvidence    string     `json:"last_evidence,omitempty"`
	UpdatedNotice   bool       `json:"updated_notice,omitempty"` // true when the next goal prompt should use objective_updated.md
}

Goal is the persisted, cross-frontend state for a session objective. A nil *Goal means the session has no goal configured.

func NewGoal added in v0.0.321

func NewGoal(objective string, tokenBudget int, now time.Time) *Goal

NewGoal constructs an active goal with normalized timestamps and budget.

func (*Goal) BudgetExhausted added in v0.0.321

func (g *Goal) BudgetExhausted() bool

BudgetExhausted reports whether a finite token budget has been consumed.

func (*Goal) Clone added in v0.0.321

func (g *Goal) Clone() *Goal

Clone returns a deep-enough copy for callers that should not mutate the persisted object in place.

func (*Goal) Exists added in v0.0.321

func (g *Goal) Exists() bool

Exists reports whether the goal has meaningful persisted state.

func (*Goal) IsActive added in v0.0.321

func (g *Goal) IsActive() bool

IsActive reports whether the runner should continue pursuing this goal.

func (*Goal) Normalize added in v0.0.321

func (g *Goal) Normalize(now time.Time)

Normalize fills defaults and clamps invalid counters.

func (*Goal) RemainingTokens added in v0.0.321

func (g *Goal) RemainingTokens() int

RemainingTokens returns the remaining token budget. A zero budget is unlimited.

type GoalStatus added in v0.0.321

type GoalStatus string

GoalStatus represents the lifecycle state of a persistent session goal.

const (
	GoalStatusActive        GoalStatus = "active"
	GoalStatusPaused        GoalStatus = "paused"
	GoalStatusComplete      GoalStatus = "complete"
	GoalStatusBlocked       GoalStatus = "blocked"
	GoalStatusBudgetLimited GoalStatus = "budget_limited"
)

type GoalUpdater added in v0.0.321

type GoalUpdater interface {
	UpdateGoal(ctx context.Context, id string, goal *Goal) error
}

GoalUpdater is an optional Store capability for updating only the persisted session goal. It avoids full-session Update writes from runner callbacks where a stale Session snapshot could clobber concurrently updated metadata.

type HandoverSlugGenerator added in v0.0.146

type HandoverSlugGenerator func(ctx context.Context, content string) (string, error)

HandoverSlugGenerator produces a short filesystem-safe slug from document content.

type ListOptions

type ListOptions struct {
	Name             string        // Filter by name
	Provider         string        // Filter by provider
	Model            string        // Filter by model
	Mode             SessionMode   // Filter by mode (chat, ask, plan, exec)
	Status           SessionStatus // Filter by status
	Tag              string        // Filter by tag (substring match)
	Categories       []string      // Sidebar/web categories (all, chat, web, ask, plan, exec)
	Limit            int           // Max results (0 = use default)
	Offset           int           // Pagination offset
	BeforeNumber     int64         // Keyset cursor: only sessions with number < this value
	SortByNumberDesc bool          // Order by session number descending instead of activity sort
	Archived         bool          // Include archived sessions
	SortByActivity   bool          // Sort by last_message_at (web sidebar); defaults to last_user_message_at
}

ListOptions configures session listing.

type LoggingStore added in v0.0.41

type LoggingStore struct {
	Store
	// contains filtered or unexported fields
}

LoggingStore wraps a Store and logs errors instead of silently discarding them. This preserves the best-effort semantics (operations don't fail the caller) while providing visibility into persistence issues.

func NewLoggingStore added in v0.0.41

func NewLoggingStore(store Store, warnFunc WarnFunc) *LoggingStore

NewLoggingStore creates a new LoggingStore wrapper. The warnFunc is called when persistence operations fail.

func (*LoggingStore) AddMessage added in v0.0.41

func (s *LoggingStore) AddMessage(ctx context.Context, sessionID string, msg *Message) error

AddMessage wraps Store.AddMessage with error logging.

func (*LoggingStore) AddMessageWithTranscriptRev added in v0.0.353

func (s *LoggingStore) AddMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message) (int64, error)

func (*LoggingStore) ClearCompactionBoundary added in v0.0.234

func (s *LoggingStore) ClearCompactionBoundary(ctx context.Context, id string) error

ClearCompactionBoundary wraps optional Store.ClearCompactionBoundary with error logging.

func (*LoggingStore) Create added in v0.0.41

func (s *LoggingStore) Create(ctx context.Context, sess *Session) error

Create wraps Store.Create with error logging.

func (*LoggingStore) DeletePlanSnapshot added in v0.0.339

func (s *LoggingStore) DeletePlanSnapshot(ctx context.Context, sessionID string) error

DeletePlanSnapshot delegates the optional latest-plan capability when available.

func (*LoggingStore) DeleteProviderState added in v0.0.289

func (s *LoggingStore) DeleteProviderState(ctx context.Context, sessionID, providerKey string) error

DeleteProviderState delegates optional provider resume state deletion.

func (*LoggingStore) GetLatestVisibleMessageID added in v0.0.250

func (s *LoggingStore) GetLatestVisibleMessageID(ctx context.Context, sessionID string) (int64, error)

GetLatestVisibleMessageID returns the latest persisted user/assistant message id for a session.

func (*LoggingStore) GetMessageByClientMessageID added in v0.0.363

func (s *LoggingStore) GetMessageByClientMessageID(ctx context.Context, sessionID, clientMessageID string) (*Message, error)

GetMessageByClientMessageID wraps an optional indexed client identity lookup.

func (*LoggingStore) GetMessageByID added in v0.0.225

func (s *LoggingStore) GetMessageByID(ctx context.Context, msgID int64) (*Message, error)

GetMessageByID wraps Store.GetMessageByID with error logging.

func (*LoggingStore) GetMessagesByClientMessageIDs added in v0.0.363

func (s *LoggingStore) GetMessagesByClientMessageIDs(ctx context.Context, sessionID string, clientMessageIDs []string) (map[string]*Message, error)

GetMessagesByClientMessageIDs unwraps the logger so fallback stores are scanned once rather than once per identity.

func (*LoggingStore) GetMessagesByTranscriptRanges added in v0.0.344

func (s *LoggingStore) GetMessagesByTranscriptRanges(ctx context.Context, sessionID string, ranges []TranscriptRange) (int64, []Message, error)

GetMessagesByTranscriptRanges delegates coherent complete-segment body reads.

func (*LoggingStore) GetMessagesPageDescending added in v0.0.261

func (s *LoggingStore) GetMessagesPageDescending(ctx context.Context, sessionID string, beforeSeq, limit int) ([]Message, error)

GetMessagesPageDescending returns a reverse-ordered page of messages. It delegates when the wrapped store supports efficient paging; otherwise it falls back to in-memory paging over GetMessages.

func (*LoggingStore) GetTranscriptIndex added in v0.0.344

func (s *LoggingStore) GetTranscriptIndex(ctx context.Context, sessionID string) (int64, []TranscriptIndexItem, error)

GetTranscriptIndex delegates coherent transcript identity reads.

func (*LoggingStore) GetTranscriptSnapshot added in v0.0.344

func (s *LoggingStore) GetTranscriptSnapshot(ctx context.Context, sessionID string) (TranscriptSnapshot, error)

GetTranscriptSnapshot delegates coherent transcript envelope reads.

func (*LoggingStore) IncrementUserTurns added in v0.0.41

func (s *LoggingStore) IncrementUserTurns(ctx context.Context, id string) error

IncrementUserTurns wraps Store.IncrementUserTurns with error logging.

func (*LoggingStore) LoadPlanSnapshot added in v0.0.339

func (s *LoggingStore) LoadPlanSnapshot(ctx context.Context, sessionID string) (planpkg.Snapshot, int64, error)

LoadPlanSnapshot delegates the optional latest-plan capability when available.

func (*LoggingStore) LoadProviderState added in v0.0.289

func (s *LoggingStore) LoadProviderState(ctx context.Context, sessionID, providerKey string) ([]byte, error)

LoadProviderState delegates optional provider resume state loading.

func (*LoggingStore) NextUserPrompt added in v0.0.281

func (s *LoggingStore) NextUserPrompt(ctx context.Context, agent string, afterID int64) (*PromptHistoryEntry, error)

NextUserPrompt delegates the optional PromptHistoryStore capability when the wrapped store supports it.

func (*LoggingStore) NextUserPromptOutsideSession added in v0.0.281

func (s *LoggingStore) NextUserPromptOutsideSession(ctx context.Context, excludeSessionID string, afterID int64, afterCreatedAt time.Time) (*PromptHistoryEntry, error)

NextUserPromptOutsideSession delegates the optional global prompt-history capability when the wrapped store supports it.

func (*LoggingStore) PreviousUserPrompt added in v0.0.281

func (s *LoggingStore) PreviousUserPrompt(ctx context.Context, agent string, beforeID int64) (*PromptHistoryEntry, error)

PreviousUserPrompt delegates the optional PromptHistoryStore capability when the wrapped store supports it.

func (*LoggingStore) PreviousUserPromptOutsideSession added in v0.0.281

func (s *LoggingStore) PreviousUserPromptOutsideSession(ctx context.Context, excludeSessionID string, beforeID int64, beforeCreatedAt time.Time) (*PromptHistoryEntry, error)

PreviousUserPromptOutsideSession delegates the optional global prompt-history capability when the wrapped store supports it.

func (*LoggingStore) ReplaceCompactedMessages added in v0.0.313

func (s *LoggingStore) ReplaceCompactedMessages(ctx context.Context, sessionID string, messages []Message) error

ReplaceCompactedMessages wraps optional Store.ReplaceCompactedMessages with error logging.

func (*LoggingStore) ReplaceCompactedMessagesWithTranscriptRev added in v0.0.353

func (s *LoggingStore) ReplaceCompactedMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)

func (*LoggingStore) ReplaceMessagesWithTranscriptRev added in v0.0.353

func (s *LoggingStore) ReplaceMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)

func (*LoggingStore) SavePlanSnapshot added in v0.0.339

func (s *LoggingStore) SavePlanSnapshot(ctx context.Context, sessionID string, snapshot planpkg.Snapshot) (int64, error)

SavePlanSnapshot delegates the optional latest-plan capability when available. Unsupported custom stores retain the controller's in-memory state only.

func (*LoggingStore) SaveProviderState added in v0.0.289

func (s *LoggingStore) SaveProviderState(ctx context.Context, sessionID, providerKey string, state []byte) error

SaveProviderState delegates optional provider resume state persistence.

func (*LoggingStore) SessionSummariesIncludeTranscriptRev added in v0.0.344

func (s *LoggingStore) SessionSummariesIncludeTranscriptRev() bool

SessionSummariesIncludeTranscriptRev preserves the wrapped store's list-query capability through the logging decorator.

func (*LoggingStore) SetCurrent added in v0.0.41

func (s *LoggingStore) SetCurrent(ctx context.Context, sessionID string) error

SetCurrent wraps Store.SetCurrent with error logging.

func (*LoggingStore) TranscriptRev added in v0.0.344

func (s *LoggingStore) TranscriptRev(ctx context.Context, sessionID string) (int64, error)

TranscriptRev delegates durable transcript revision reads.

func (*LoggingStore) TranscriptVersioned added in v0.0.344

func (s *LoggingStore) TranscriptVersioned() bool

TranscriptVersioned reports whether the wrapped store has a revisioned schema.

func (*LoggingStore) Update added in v0.0.41

func (s *LoggingStore) Update(ctx context.Context, sess *Session) error

Update wraps Store.Update with error logging.

func (*LoggingStore) UpdateContextEstimate added in v0.0.161

func (s *LoggingStore) UpdateContextEstimate(ctx context.Context, id string, lastTotalTokens, lastMessageCount int) error

UpdateContextEstimate wraps Store.UpdateContextEstimate with error logging.

func (*LoggingStore) UpdateGeneratedTitle added in v0.0.320

func (s *LoggingStore) UpdateGeneratedTitle(ctx context.Context, id, shortTitle, longTitle string, generatedAt time.Time, basisMsgSeq int) error

UpdateGeneratedTitle wraps the optional title-only update path with error logging.

func (*LoggingStore) UpdateGoal added in v0.0.321

func (s *LoggingStore) UpdateGoal(ctx context.Context, id string, goal *Goal) error

UpdateGoal wraps the optional goal-only update path with error logging.

func (*LoggingStore) UpdateMessage added in v0.0.174

func (s *LoggingStore) UpdateMessage(ctx context.Context, sessionID string, msg *Message) error

UpdateMessage wraps Store.UpdateMessage with error logging. ErrNotFound is returned to the caller verbatim (no logging) so upsert callers can fall back to AddMessage without noise.

func (*LoggingStore) UpdateMetrics added in v0.0.41

func (s *LoggingStore) UpdateMetrics(ctx context.Context, id string, llmTurns, toolCalls, inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens int) error

UpdateMetrics wraps Store.UpdateMetrics with error logging.

func (*LoggingStore) UpdateShare added in v0.0.324

func (s *LoggingStore) UpdateShare(ctx context.Context, id string, share *ShareState) error

UpdateShare wraps the optional share-only update path with error logging.

func (*LoggingStore) UpdateStatus added in v0.0.41

func (s *LoggingStore) UpdateStatus(ctx context.Context, id string, status SessionStatus) error

UpdateStatus wraps Store.UpdateStatus with error logging.

func (*LoggingStore) UpdateStreamingMessage added in v0.0.289

func (s *LoggingStore) UpdateStreamingMessage(ctx context.Context, sessionID string, msg *Message, finalizeText bool) error

UpdateStreamingMessage wraps the optional streaming-aware update path with the same error logging semantics as UpdateMessage.

func (*LoggingStore) UpdateStreamingMessageWithTranscriptRev added in v0.0.353

func (s *LoggingStore) UpdateStreamingMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message, finalizeText bool) (int64, error)

type Message

type Message struct {
	ID                      int64      `json:"id"`
	SessionID               string     `json:"session_id"`
	Role                    llm.Role   `json:"role"`
	Parts                   []llm.Part `json:"parts"`        // Full parts array
	TextContent             string     `json:"text_content"` // Extracted text for display/FTS
	DurationMs              int64      `json:"duration_ms,omitempty"`
	TurnIndex               int        `json:"turn_index,omitempty"`
	CreatedAt               time.Time  `json:"created_at"`
	Sequence                int        `json:"sequence"`
	CompactionTail          bool       `json:"compaction_tail,omitempty"` // Persisted display hint: retained post-compaction context already visible before the marker
	ClientMessageID         string     `json:"client_message_id,omitempty"`
	ResponseID              string     `json:"response_id,omitempty"`
	AssistantSegmentOrdinal int        `json:"assistant_segment_ordinal"` // Response-scoped; -1 when the row is not an assistant segment.
	SegmentStartSequence    int64      `json:"segment_start_sequence,omitempty"`
	SegmentEndSequence      int64      `json:"segment_end_sequence,omitempty"`
}

Message represents a message in a session. The Parts field stores the full llm.Message.Parts as JSON to preserve tool calls, uploaded images/files, and provider replay state exactly.

func FindMessageByClientMessageID added in v0.0.363

func FindMessageByClientMessageID(ctx context.Context, store Store, sessionID, clientMessageID string) (*Message, error)

FindMessageByClientMessageID uses an indexed lookup when available and falls back to scanning stores that do not implement the optional capability.

func LoadActiveMessages added in v0.0.234

func LoadActiveMessages(ctx context.Context, store Store, sess *Session) ([]Message, error)

LoadActiveMessages loads the messages that should be sent as active LLM context for a session. If the session has been compacted, older scrollback rows are intentionally skipped and callers receive only rows at/after the compaction boundary.

func LoadInitialScrollbackWithBoundary added in v0.0.309

func LoadInitialScrollbackWithBoundary(ctx context.Context, store Store, sess *Session) ([]Message, int, error)

LoadInitialScrollbackWithBoundary loads the messages needed for the first UI paint while also returning the index where active LLM context begins. For compacted sessions it loads only rows at/after the persisted boundary so long resumes avoid an eager full-transcript read; callers may load older display history lazily if needed.

func LoadScrollbackWithBoundary added in v0.0.234

func LoadScrollbackWithBoundary(ctx context.Context, store Store, sess *Session) ([]Message, int, error)

LoadScrollbackWithBoundary loads all persisted messages for display while also returning the index where active LLM context begins.

func NewMessage

func NewMessage(sessionID string, msg llm.Message, sequence int) *Message

NewMessage creates a new Message from an llm.Message with the given session ID and sequence.

func NewMessageWithReasoningPolicy added in v0.0.258

func NewMessageWithReasoningPolicy(sessionID string, msg llm.Message, sequence int, cfg config.ReasoningConfig) *Message

NewMessageWithReasoningPolicy creates a session message after applying the configured reasoning persistence policy.

func VisibleExportMessages added in v0.0.322

func VisibleExportMessages(messages []Message) []Message

VisibleExportMessages returns messages intended for human-readable exports. Retained post-compaction context is already represented earlier in scrollback.

func (*Message) ExtractTextContent

func (m *Message) ExtractTextContent() string

ExtractTextContent extracts and concatenates all text parts from the message.

func (*Message) PartsJSON

func (m *Message) PartsJSON() (string, error)

PartsJSON returns the Parts field serialized to JSON for database storage.

func (*Message) PartsJSONForStorage added in v0.0.312

func (m *Message) PartsJSONForStorage(stripImageBase64 bool) (string, error)

func (*Message) SetPartsFromJSON

func (m *Message) SetPartsFromJSON(data string) error

SetPartsFromJSON deserializes JSON into the Parts field.

func (*Message) ToLLMMessage

func (m *Message) ToLLMMessage() llm.Message

ToLLMMessage converts a Message back to an llm.Message.

type MessageSequenceStore added in v0.0.344

type MessageSequenceStore interface {
	MaxMessageSequences(ctx context.Context, sessionIDs []string) (map[string]int, error)
}

MessageSequenceStore is an optional Store capability for fetching the latest message sequence for many sessions without issuing one query per session. Callers must preserve behavior when a store does not implement this fast path.

type MessagesDescendingPager added in v0.0.261

type MessagesDescendingPager interface {
	GetMessagesPageDescending(ctx context.Context, sessionID string, beforeSeq, limit int) ([]Message, error)
}

MessagesDescendingPager is an optional Store capability for efficient reverse pagination over session messages. Implementations return messages ordered by descending sequence and, when beforeSeq > 0, only rows with sequence < beforeSeq.

type NoopStore

type NoopStore struct{}

NoopStore is a no-op implementation of Store used when sessions are disabled. It silently discards all writes and returns empty results for reads.

func (*NoopStore) AddMessage

func (s *NoopStore) AddMessage(ctx context.Context, sessionID string, msg *Message) error

func (*NoopStore) ClearCurrent

func (s *NoopStore) ClearCurrent(ctx context.Context) error

func (*NoopStore) Close

func (s *NoopStore) Close() error

func (*NoopStore) CompactMessages added in v0.0.115

func (s *NoopStore) CompactMessages(ctx context.Context, sessionID string, messages []Message) error

func (*NoopStore) Create

func (s *NoopStore) Create(ctx context.Context, sess *Session) error

func (*NoopStore) Delete

func (s *NoopStore) Delete(ctx context.Context, id string) error

func (*NoopStore) DeletePushSubscription added in v0.0.114

func (s *NoopStore) DeletePushSubscription(ctx context.Context, endpoint string) error

func (*NoopStore) Get

func (s *NoopStore) Get(ctx context.Context, id string) (*Session, error)

func (*NoopStore) GetByNumber added in v0.0.56

func (s *NoopStore) GetByNumber(ctx context.Context, number int64) (*Session, error)

func (*NoopStore) GetByPrefix added in v0.0.52

func (s *NoopStore) GetByPrefix(ctx context.Context, prefix string) (*Session, error)

func (*NoopStore) GetCurrent

func (s *NoopStore) GetCurrent(ctx context.Context) (*Session, error)

func (*NoopStore) GetMessageByID added in v0.0.225

func (s *NoopStore) GetMessageByID(ctx context.Context, msgID int64) (*Message, error)

func (*NoopStore) GetMessages

func (s *NoopStore) GetMessages(ctx context.Context, sessionID string, limit, offset int) ([]Message, error)

func (*NoopStore) GetMessagesFrom added in v0.0.115

func (s *NoopStore) GetMessagesFrom(ctx context.Context, sessionID string, fromSeq, limit int) ([]Message, error)

func (*NoopStore) IncrementUserTurns added in v0.0.41

func (s *NoopStore) IncrementUserTurns(ctx context.Context, id string) error

func (*NoopStore) List

func (s *NoopStore) List(ctx context.Context, opts ListOptions) ([]SessionSummary, error)

func (*NoopStore) ListPushSubscriptions added in v0.0.114

func (s *NoopStore) ListPushSubscriptions(ctx context.Context) ([]PushSubscription, error)

func (*NoopStore) MarkTitleSkipped added in v0.0.131

func (s *NoopStore) MarkTitleSkipped(ctx context.Context, id string, t time.Time) error

func (*NoopStore) NextUserPrompt added in v0.0.281

func (s *NoopStore) NextUserPrompt(ctx context.Context, agent string, afterID int64) (*PromptHistoryEntry, error)

func (*NoopStore) NextUserPromptOutsideSession added in v0.0.281

func (s *NoopStore) NextUserPromptOutsideSession(ctx context.Context, excludeSessionID string, afterID int64, afterCreatedAt time.Time) (*PromptHistoryEntry, error)

func (*NoopStore) PreviousUserPrompt added in v0.0.281

func (s *NoopStore) PreviousUserPrompt(ctx context.Context, agent string, beforeID int64) (*PromptHistoryEntry, error)

func (*NoopStore) PreviousUserPromptOutsideSession added in v0.0.281

func (s *NoopStore) PreviousUserPromptOutsideSession(ctx context.Context, excludeSessionID string, beforeID int64, beforeCreatedAt time.Time) (*PromptHistoryEntry, error)

func (*NoopStore) ReplaceMessages added in v0.0.80

func (s *NoopStore) ReplaceMessages(ctx context.Context, sessionID string, messages []Message) error

func (*NoopStore) SavePushSubscription added in v0.0.114

func (s *NoopStore) SavePushSubscription(ctx context.Context, sub *PushSubscription) error

func (*NoopStore) Search

func (s *NoopStore) Search(ctx context.Context, opts SearchOptions) ([]SearchResult, error)

func (*NoopStore) SetCurrent

func (s *NoopStore) SetCurrent(ctx context.Context, sessionID string) error

func (*NoopStore) Update

func (s *NoopStore) Update(ctx context.Context, sess *Session) error

func (*NoopStore) UpdateContextEstimate added in v0.0.161

func (s *NoopStore) UpdateContextEstimate(ctx context.Context, id string, lastTotalTokens, lastMessageCount int) error

func (*NoopStore) UpdateMessage added in v0.0.174

func (s *NoopStore) UpdateMessage(ctx context.Context, sessionID string, msg *Message) error

func (*NoopStore) UpdateMetrics added in v0.0.41

func (s *NoopStore) UpdateMetrics(ctx context.Context, id string, llmTurns, toolCalls, inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens int) error

func (*NoopStore) UpdateStatus added in v0.0.41

func (s *NoopStore) UpdateStatus(ctx context.Context, id string, status SessionStatus) error

type PlanSnapshotStore added in v0.0.339

type PlanSnapshotStore interface {
	LoadPlanSnapshot(ctx context.Context, sessionID string) (planpkg.Snapshot, int64, error)
	SavePlanSnapshot(ctx context.Context, sessionID string, snapshot planpkg.Snapshot) (int64, error)
	DeletePlanSnapshot(ctx context.Context, sessionID string) error
}

PlanSnapshotStore is an optional Store capability for the authoritative latest update_plan snapshot. Transcript tool-call/result parts remain the durable replay record; this narrow store supports efficient resume restoration.

type PromptHistoryEntry added in v0.0.281

type PromptHistoryEntry struct {
	ID        int64
	CreatedAt time.Time
	Text      string
}

PromptHistoryEntry is a user prompt recalled from composer history.

type PromptHistoryOutsideSessionStore added in v0.0.281

type PromptHistoryOutsideSessionStore interface {
	PreviousUserPromptOutsideSession(ctx context.Context, excludeSessionID string, beforeID int64, beforeCreatedAt time.Time) (*PromptHistoryEntry, error)
	NextUserPromptOutsideSession(ctx context.Context, excludeSessionID string, afterID int64, afterCreatedAt time.Time) (*PromptHistoryEntry, error)
}

PromptHistoryOutsideSessionStore is an optional Store capability for the TUI composer history sequence after the current session's in-memory prompts have been exhausted. It traverses persisted user prompts from all agents while excluding the current session to avoid duplicate recalls.

type PromptHistoryStore added in v0.0.281

type PromptHistoryStore interface {
	PreviousUserPrompt(ctx context.Context, agent string, beforeID int64) (*PromptHistoryEntry, error)
	NextUserPrompt(ctx context.Context, agent string, afterID int64) (*PromptHistoryEntry, error)
}

PromptHistoryStore is an optional Store capability for shell-style composer history recall. Implementations traverse persisted user prompts globally so multiple TUI processes share the same prompt history.

type ProviderStateStore added in v0.0.289

type ProviderStateStore interface {
	SaveProviderState(ctx context.Context, sessionID, providerKey string, state []byte) error
	LoadProviderState(ctx context.Context, sessionID, providerKey string) ([]byte, error)
	DeleteProviderState(ctx context.Context, sessionID, providerKey string) error
}

ProviderStateStore is an optional Store capability for provider-specific resume state. It stores opaque JSON/blob payloads keyed by term-llm session and provider key, allowing stateful CLI providers to survive runtime eviction without leaking that state into the user-visible transcript.

type PushSubscription added in v0.0.114

type PushSubscription struct {
	ID        string
	Endpoint  string
	KeyP256DH string
	KeyAuth   string
}

PushSubscription represents a Web Push subscription stored in the database.

type SQLiteStore

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

SQLiteStore implements Store using SQLite.

func NewSQLiteStore

func NewSQLiteStore(cfg Config) (*SQLiteStore, error)

NewSQLiteStore creates a new SQLite-based session store.

func (*SQLiteStore) AddMessage

func (s *SQLiteStore) AddMessage(ctx context.Context, sessionID string, msg *Message) error

AddMessage adds a message to a session. If msg.Sequence < 0, the sequence number is auto-allocated atomically.

func (*SQLiteStore) AddMessageWithTranscriptRev added in v0.0.353

func (s *SQLiteStore) AddMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message) (int64, error)

AddMessageWithTranscriptRev adds a message and returns the revision bumped by the same transaction.

func (*SQLiteStore) ClearCompactionBoundary added in v0.0.234

func (s *SQLiteStore) ClearCompactionBoundary(ctx context.Context, id string) error

func (*SQLiteStore) ClearCurrent

func (s *SQLiteStore) ClearCurrent(ctx context.Context) error

ClearCurrent removes the current session marker.

func (*SQLiteStore) Close

func (s *SQLiteStore) Close() error

Close closes the database connections.

func (*SQLiteStore) CompactMessages added in v0.0.115

func (s *SQLiteStore) CompactMessages(ctx context.Context, sessionID string, messages []Message) error

CompactMessages appends compacted messages to the session, preserving old history, and updates compaction_seq so that resume loads only post-compaction messages. Old messages remain in the database for scrollback/history.

func (*SQLiteStore) Create

func (s *SQLiteStore) Create(ctx context.Context, sess *Session) error

Create inserts a new session.

func (*SQLiteStore) Delete

func (s *SQLiteStore) Delete(ctx context.Context, id string) error

Delete removes a session and its messages.

func (*SQLiteStore) DeletePlanSnapshot added in v0.0.339

func (s *SQLiteStore) DeletePlanSnapshot(ctx context.Context, sessionID string) error

DeletePlanSnapshot clears the current snapshot row for a session.

func (*SQLiteStore) DeleteProviderState added in v0.0.289

func (s *SQLiteStore) DeleteProviderState(ctx context.Context, sessionID, providerKey string) error

DeleteProviderState removes provider-owned resume state for a session.

func (*SQLiteStore) DeletePushSubscription added in v0.0.114

func (s *SQLiteStore) DeletePushSubscription(ctx context.Context, endpoint string) error

DeletePushSubscription removes a Web Push subscription by endpoint.

func (*SQLiteStore) Get

func (s *SQLiteStore) Get(ctx context.Context, id string) (*Session, error)

Get retrieves a session by ID.

func (*SQLiteStore) GetByNumber added in v0.0.56

func (s *SQLiteStore) GetByNumber(ctx context.Context, number int64) (*Session, error)

GetByNumber retrieves a session by its sequential number.

func (*SQLiteStore) GetByPrefix added in v0.0.52

func (s *SQLiteStore) GetByPrefix(ctx context.Context, prefix string) (*Session, error)

GetByPrefix retrieves a session by number (with # prefix), exact ID, or by short ID prefix match. It tries in order: #number (e.g., #42), exact ID match, short ID prefix match.

func (*SQLiteStore) GetCurrent

func (s *SQLiteStore) GetCurrent(ctx context.Context) (*Session, error)

GetCurrent retrieves the current session.

func (*SQLiteStore) GetLatestVisibleMessageID added in v0.0.250

func (s *SQLiteStore) GetLatestVisibleMessageID(ctx context.Context, sessionID string) (int64, error)

GetLatestVisibleMessageID retrieves the latest persisted user/assistant message id for a session.

func (*SQLiteStore) GetMessageByClientMessageID added in v0.0.363

func (s *SQLiteStore) GetMessageByClientMessageID(ctx context.Context, sessionID, clientMessageID string) (*Message, error)

GetMessageByClientMessageID retrieves a first-party user message by its session-scoped stable identity.

func (*SQLiteStore) GetMessageByID added in v0.0.224

func (s *SQLiteStore) GetMessageByID(ctx context.Context, msgID int64) (*Message, error)

GetMessageByID retrieves a single message by its global message id.

func (*SQLiteStore) GetMessages

func (s *SQLiteStore) GetMessages(ctx context.Context, sessionID string, limit, offset int) ([]Message, error)

GetMessages retrieves messages for a session.

func (*SQLiteStore) GetMessagesByClientMessageIDs added in v0.0.363

func (s *SQLiteStore) GetMessagesByClientMessageIDs(ctx context.Context, sessionID string, clientMessageIDs []string) (map[string]*Message, error)

GetMessagesByClientMessageIDs resolves a batch through the indexed lookup.

func (*SQLiteStore) GetMessagesByTranscriptRanges added in v0.0.344

func (s *SQLiteStore) GetMessagesByTranscriptRanges(ctx context.Context, sessionID string, ranges []TranscriptRange) (int64, []Message, error)

GetMessagesByTranscriptRanges returns complete durable transcript segments in authoritative order and the revision describing them from one SQLite read transaction. Each segment uses four bind variables regardless of how many durable rows it expands to, so a giant tool turn never approaches SQLite's variable limit.

func (*SQLiteStore) GetMessagesFrom added in v0.0.115

func (s *SQLiteStore) GetMessagesFrom(ctx context.Context, sessionID string, fromSeq, limit int) ([]Message, error)

GetMessagesFrom retrieves messages for a session starting from a given sequence number. Used on resume and for keyset-style pagination when walking long transcripts. When limit <= 0, all rows at/after fromSeq are returned.

func (*SQLiteStore) GetMessagesPageDescending added in v0.0.261

func (s *SQLiteStore) GetMessagesPageDescending(ctx context.Context, sessionID string, beforeSeq, limit int) ([]Message, error)

GetMessagesPageDescending retrieves messages for a session in reverse sequence order. When beforeSeq > 0, only rows with sequence < beforeSeq are returned. Used for reverse tail pagination without loading entire sessions.

func (*SQLiteStore) GetTranscriptIndex added in v0.0.344

func (s *SQLiteStore) GetTranscriptIndex(ctx context.Context, sessionID string) (int64, []TranscriptIndexItem, error)

GetTranscriptIndex returns every durable non-internal row and the revision describing it from one SQLite read transaction.

func (*SQLiteStore) GetTranscriptSnapshot added in v0.0.344

func (s *SQLiteStore) GetTranscriptSnapshot(ctx context.Context, sessionID string) (TranscriptSnapshot, error)

GetTranscriptSnapshot returns the complete transcript envelope from one SQLite read transaction.

func (*SQLiteStore) IncrementUserTurns added in v0.0.41

func (s *SQLiteStore) IncrementUserTurns(ctx context.Context, id string) error

IncrementUserTurns increments the user turn count and updates last_user_message_at.

func (*SQLiteStore) List

func (s *SQLiteStore) List(ctx context.Context, opts ListOptions) ([]SessionSummary, error)

List returns sessions matching the options.

func (*SQLiteStore) ListPushSubscriptions added in v0.0.114

func (s *SQLiteStore) ListPushSubscriptions(ctx context.Context) ([]PushSubscription, error)

ListPushSubscriptions returns all stored Web Push subscriptions.

func (*SQLiteStore) LoadPlanSnapshot added in v0.0.339

func (s *SQLiteStore) LoadPlanSnapshot(ctx context.Context, sessionID string) (planpkg.Snapshot, int64, error)

LoadPlanSnapshot loads the authoritative latest update_plan snapshot.

func (*SQLiteStore) LoadProviderState added in v0.0.289

func (s *SQLiteStore) LoadProviderState(ctx context.Context, sessionID, providerKey string) ([]byte, error)

LoadProviderState returns opaque provider-owned resume state for a session.

func (*SQLiteStore) MarkTitleSkipped added in v0.0.131

func (s *SQLiteStore) MarkTitleSkipped(ctx context.Context, id string, t time.Time) error

MarkTitleSkipped sets title_skipped_at on a session without bumping updated_at. This lets the autotitle job skip trivial sessions until real new messages arrive.

func (*SQLiteStore) MaxMessageSequences added in v0.0.344

func (s *SQLiteStore) MaxMessageSequences(ctx context.Context, sessionIDs []string) (map[string]int, error)

MaxMessageSequences returns the greatest persisted message sequence for each requested session. Sessions without messages are returned with sequence -1.

func (*SQLiteStore) NextUserPrompt added in v0.0.281

func (s *SQLiteStore) NextUserPrompt(ctx context.Context, agent string, afterID int64) (*PromptHistoryEntry, error)

NextUserPrompt returns the oldest persisted user prompt newer than afterID.

func (*SQLiteStore) NextUserPromptOutsideSession added in v0.0.281

func (s *SQLiteStore) NextUserPromptOutsideSession(ctx context.Context, excludeSessionID string, afterID int64, afterCreatedAt time.Time) (*PromptHistoryEntry, error)

NextUserPromptOutsideSession returns the oldest persisted user prompt newer than the cursor, ordered by message timestamp across all agents, excluding the current session.

func (*SQLiteStore) PersistCompactionTailHints added in v0.0.278

func (s *SQLiteStore) PersistCompactionTailHints(ctx context.Context, sessionID string, messageIDs []int64) error

func (*SQLiteStore) PreviousUserPrompt added in v0.0.281

func (s *SQLiteStore) PreviousUserPrompt(ctx context.Context, agent string, beforeID int64) (*PromptHistoryEntry, error)

PreviousUserPrompt returns the newest persisted user prompt older than beforeID. When beforeID <= 0, traversal starts at the newest prompt. History is global across sessions and optionally filtered by agent.

func (*SQLiteStore) PreviousUserPromptOutsideSession added in v0.0.281

func (s *SQLiteStore) PreviousUserPromptOutsideSession(ctx context.Context, excludeSessionID string, beforeID int64, beforeCreatedAt time.Time) (*PromptHistoryEntry, error)

PreviousUserPromptOutsideSession returns the newest persisted user prompt older than the cursor, ordered by message timestamp across all agents, excluding the current session.

func (*SQLiteStore) ReplaceCompactedMessages added in v0.0.313

func (s *SQLiteStore) ReplaceCompactedMessages(ctx context.Context, sessionID string, messages []Message) error

ReplaceCompactedMessages reconciles the active post-compaction history for a session while preserving pre-compaction scrollback and the compaction boundary. It must only be used with snapshots that start at the current compaction_seq.

func (*SQLiteStore) ReplaceCompactedMessagesWithTranscriptRev added in v0.0.353

func (s *SQLiteStore) ReplaceCompactedMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)

func (*SQLiteStore) ReplaceMessages added in v0.0.80

func (s *SQLiteStore) ReplaceMessages(ctx context.Context, sessionID string, messages []Message) error

ReplaceMessages reconciles the complete persisted history for a session. It preserves any unchanged prefix and rewrites only the changed suffix, avoiding a DELETE+INSERT of long histories when serve/web persists an appended snapshot. Because the replacement snapshot becomes the complete persisted history, any previous compaction boundary is cleared.

func (*SQLiteStore) ReplaceMessagesWithTranscriptRev added in v0.0.353

func (s *SQLiteStore) ReplaceMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)

func (*SQLiteStore) SavePlanSnapshot added in v0.0.339

func (s *SQLiteStore) SavePlanSnapshot(ctx context.Context, sessionID string, snapshot planpkg.Snapshot) (int64, error)

SavePlanSnapshot atomically replaces the current snapshot and increments the existing row's version. Saving after a clear creates a new row at version 1.

func (*SQLiteStore) SaveProviderState added in v0.0.289

func (s *SQLiteStore) SaveProviderState(ctx context.Context, sessionID, providerKey string, state []byte) error

SaveProviderState stores opaque provider-owned resume state for a session.

func (*SQLiteStore) SavePushSubscription added in v0.0.114

func (s *SQLiteStore) SavePushSubscription(ctx context.Context, sub *PushSubscription) error

SavePushSubscription upserts a Web Push subscription.

func (*SQLiteStore) Search

func (s *SQLiteStore) Search(ctx context.Context, opts SearchOptions) ([]SearchResult, error)

Search finds sessions containing the query text using FTS5.

func (*SQLiteStore) SessionSummariesIncludeTranscriptRev added in v0.0.344

func (s *SQLiteStore) SessionSummariesIncludeTranscriptRev() bool

SessionSummariesIncludeTranscriptRev reports whether List can read revisions from the sessions row without compatibility fallbacks.

func (*SQLiteStore) SetCurrent

func (s *SQLiteStore) SetCurrent(ctx context.Context, sessionID string) error

SetCurrent marks a session as the current one.

func (*SQLiteStore) TranscriptRev added in v0.0.344

func (s *SQLiteStore) TranscriptRev(ctx context.Context, sessionID string) (int64, error)

TranscriptRev returns the current durable transcript revision. Old read-only databases without the revision column are explicitly unversioned (revision 0).

func (*SQLiteStore) TranscriptVersioned added in v0.0.344

func (s *SQLiteStore) TranscriptVersioned() bool

TranscriptVersioned reports whether this database has durable transcript revisions. It is false only for old schemas opened read-only without migration.

func (*SQLiteStore) Update

func (s *SQLiteStore) Update(ctx context.Context, sess *Session) error

Update modifies an existing session's metadata fields. Token metrics (input_tokens, cached_input_tokens, cache_write_tokens, output_tokens) and turn counters (user_turns, llm_turns, tool_calls) are intentionally excluded — they are managed exclusively by atomic update paths to prevent stale in-memory values from clobbering accumulated totals.

func (*SQLiteStore) UpdateContextEstimate added in v0.0.161

func (s *SQLiteStore) UpdateContextEstimate(ctx context.Context, id string, lastTotalTokens, lastMessageCount int) error

UpdateContextEstimate persists the last observed provider context estimate so resumed sessions can display a realistic context meter before the next turn.

func (*SQLiteStore) UpdateGeneratedTitle added in v0.0.320

func (s *SQLiteStore) UpdateGeneratedTitle(ctx context.Context, id, shortTitle, longTitle string, generatedAt time.Time, basisMsgSeq int) error

UpdateGeneratedTitle updates only generated title columns for a session.

func (*SQLiteStore) UpdateGoal added in v0.0.321

func (s *SQLiteStore) UpdateGoal(ctx context.Context, id string, goal *Goal) error

UpdateGoal updates only the persisted goal state for a session.

func (*SQLiteStore) UpdateMessage added in v0.0.174

func (s *SQLiteStore) UpdateMessage(ctx context.Context, sessionID string, msg *Message) error

UpdateMessage replaces the content of an existing message (keyed by msg.ID within sessionID). Returns ErrNotFound if no row matches. Used by the "persist as we go" upsert path: the caller first calls AddMessage to stamp an ID, then subsequent snapshots call UpdateMessage with the same ID.

func (*SQLiteStore) UpdateMetrics added in v0.0.41

func (s *SQLiteStore) UpdateMetrics(ctx context.Context, id string, llmTurns, toolCalls, inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens int) error

UpdateMetrics atomically increments the metrics fields for a session. All token counters use += to avoid clobbering concurrent accumulation.

func (*SQLiteStore) UpdateShare added in v0.0.324

func (s *SQLiteStore) UpdateShare(ctx context.Context, id string, share *ShareState) error

UpdateShare updates only persisted share metadata for a session.

func (*SQLiteStore) UpdateStatus added in v0.0.41

func (s *SQLiteStore) UpdateStatus(ctx context.Context, id string, status SessionStatus) error

UpdateStatus updates just the session status.

func (*SQLiteStore) UpdateStreamingMessage added in v0.0.289

func (s *SQLiteStore) UpdateStreamingMessage(ctx context.Context, sessionID string, msg *Message, finalizeText bool) error

UpdateStreamingMessage updates an in-progress assistant message while letting the caller defer the FTS-backed text_content rewrite until finalization.

func (*SQLiteStore) UpdateStreamingMessageWithTranscriptRev added in v0.0.353

func (s *SQLiteStore) UpdateStreamingMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message, finalizeText bool) (int64, error)

type SearchOptions added in v0.0.281

type SearchOptions struct {
	Query      string   // Text query to search for
	Categories []string // Sidebar/web categories (all, chat, web, ask, plan, exec)
	Limit      int      // Max results (0 = use default)
	Archived   bool     // Include archived sessions
}

SearchOptions configures session full-text search.

type SearchResult

type SearchResult struct {
	SessionID           string             `json:"session_id"`
	SessionNumber       int64              `json:"session_number"` // Sequential session number
	MessageID           int64              `json:"message_id"`
	SessionName         string             `json:"session_name"`
	Summary             string             `json:"summary"`
	GeneratedShortTitle string             `json:"generated_short_title,omitempty"`
	GeneratedLongTitle  string             `json:"generated_long_title,omitempty"`
	TitleSource         SessionTitleSource `json:"title_source,omitempty"`
	Snippet             string             `json:"snippet"` // Matched text snippet
	Provider            string             `json:"provider"`
	ProviderKey         string             `json:"provider_key,omitempty"`
	Model               string             `json:"model"`
	Mode                SessionMode        `json:"mode,omitempty"`
	Origin              SessionOrigin      `json:"origin,omitempty"`
	Archived            bool               `json:"archived,omitempty"`
	Pinned              bool               `json:"pinned,omitempty"`
	Status              SessionStatus      `json:"status,omitempty"`
	MessageCount        int                `json:"message_count"`
	SessionCreatedAt    time.Time          `json:"session_created_at"`
	UpdatedAt           time.Time          `json:"updated_at"`
	LastMessageAt       time.Time          `json:"last_message_at,omitempty"`
	CreatedAt           time.Time          `json:"created_at"`
}

SearchResult represents a search match.

type Session

type Session struct {
	ID      string `json:"id"`
	Number  int64  `json:"number,omitempty"` // Sequential session number (1, 2, 3...)
	Name    string `json:"name,omitempty"`
	Summary string `json:"summary,omitempty"` // First user message or auto-generated

	GeneratedShortTitle string             `json:"generated_short_title,omitempty"`
	GeneratedLongTitle  string             `json:"generated_long_title,omitempty"`
	TitleSource         SessionTitleSource `json:"title_source,omitempty"`
	TitleGeneratedAt    time.Time          `json:"title_generated_at,omitempty"`
	TitleBasisMsgSeq    int                `json:"title_basis_msg_seq,omitempty"`
	TitleSkippedAt      time.Time          `json:"title_skipped_at,omitempty"` // Set when autotitle considers session untitlable; cleared when session is updated

	Provider        string              `json:"provider"`               // Provider display label
	ProviderKey     string              `json:"provider_key,omitempty"` // Canonical provider key (e.g. openai, chatgpt, custom alias)
	Model           string              `json:"model"`
	ReasoningEffort string              `json:"reasoning_effort,omitempty"` // Reasoning effort pinned at session creation (web only)
	ReasoningMode   string              `json:"reasoning_mode,omitempty"`   // Explicit Responses reasoning mode override (standard/pro).
	Mode            SessionMode         `json:"mode,omitempty"`             // Session mode (chat, ask, plan, exec)
	ApprovalMode    SessionApprovalMode `json:"approval_mode,omitempty"`    // Tool approval mode for chat sessions (prompt, auto, yolo)
	Origin          SessionOrigin       `json:"origin,omitempty"`           // Session surface/origin (tui, web, telegram)
	Agent           string              `json:"agent,omitempty"`            // Agent name used for this session
	CWD             string              `json:"cwd,omitempty"`              // Working directory at session start
	WorktreeDir     string              `json:"worktree_dir,omitempty"`     // Bound git worktree directory, if any
	CreatedAt       time.Time           `json:"created_at"`
	UpdatedAt       time.Time           `json:"updated_at"`
	Archived        bool                `json:"archived,omitempty"`
	Pinned          bool                `json:"pinned,omitempty"`
	ParentID        string              `json:"parent_id,omitempty"`   // For session branching
	IsSubagent      bool                `json:"is_subagent,omitempty"` // True if this is a subagent session

	// Session settings (restored on resume unless overridden)
	Search bool   `json:"search,omitempty"` // Web search enabled
	Tools  string `json:"tools,omitempty"`  // Enabled tools (comma-separated)
	MCP    string `json:"mcp,omitempty"`    // Enabled MCP servers (comma-separated)

	// Session metrics
	UserTurns         int           `json:"user_turns,omitempty"`          // Number of user messages
	LLMTurns          int           `json:"llm_turns,omitempty"`           // Number of LLM API round-trips
	ToolCalls         int           `json:"tool_calls,omitempty"`          // Total tool executions
	InputTokens       int           `json:"input_tokens,omitempty"`        // Total non-cached, non-cache-write input tokens
	CachedInputTokens int           `json:"cached_input_tokens,omitempty"` // Total cached input tokens read (cache hits)
	CacheWriteTokens  int           `json:"cache_write_tokens,omitempty"`  // Total tokens written to cache (cache misses)
	OutputTokens      int           `json:"output_tokens,omitempty"`       // Total output tokens used
	LastTotalTokens   int           `json:"last_total_tokens,omitempty"`   // Last observed request context size (input+cached+output)
	LastMessageCount  int           `json:"last_message_count,omitempty"`  // Legacy checkpoint count; estimator uses structural delta
	MessageCount      int           `json:"message_count,omitempty"`       // User/assistant conversation messages visible as chat bubbles
	Status            SessionStatus `json:"status,omitempty"`              // Session status
	Tags              string        `json:"tags,omitempty"`                // Comma-separated tags
	Goal              *Goal         `json:"goal,omitempty"`                // Persistent objective state for /goal
	Share             *ShareState   `json:"share,omitempty"`               // Persisted external share metadata
	CompactionSeq     int           `json:"compaction_seq,omitempty"`      // Sequence of first post-compaction message (-1 = none)
	CompactionCount   int           `json:"compaction_count,omitempty"`    // Number of times this session has been compacted
}

Session represents a chat session stored in the database.

func (Session) PreferredLongTitle added in v0.0.120

func (s Session) PreferredLongTitle() string

PreferredLongTitle returns the best long descriptive title available for the session.

func (Session) PreferredShortTitle added in v0.0.120

func (s Session) PreferredShortTitle() string

PreferredShortTitle returns the best short title available for the session.

type SessionApprovalMode added in v0.0.317

type SessionApprovalMode string
const (
	ApprovalModePrompt SessionApprovalMode = "prompt"
	ApprovalModeAuto   SessionApprovalMode = "auto"
	ApprovalModeYolo   SessionApprovalMode = "yolo"
)

type SessionMode added in v0.0.55

type SessionMode string

SessionMode represents the type/context of a session.

const (
	ModeChat SessionMode = "chat" // Interactive chat TUI
	ModeAsk  SessionMode = "ask"  // One-shot ask command
	ModePlan SessionMode = "plan" // Collaborative planning TUI
	ModeExec SessionMode = "exec" // Command suggestion/execution
)

type SessionOrigin added in v0.0.130

type SessionOrigin string
const (
	OriginTUI      SessionOrigin = "tui"
	OriginWeb      SessionOrigin = "web"
	OriginTelegram SessionOrigin = "telegram"
)

type SessionStatus added in v0.0.41

type SessionStatus string

SessionStatus represents the current state of a session.

const (
	StatusActive      SessionStatus = "active"      // Session is open/current (may or may not be streaming)
	StatusComplete    SessionStatus = "complete"    // Session finished normally
	StatusError       SessionStatus = "error"       // Session ended with an error
	StatusInterrupted SessionStatus = "interrupted" // Session was cancelled by user
)

type SessionSummary

type SessionSummary struct {
	ID                  string             `json:"id"`
	Number              int64              `json:"number,omitempty"` // Sequential session number
	Name                string             `json:"name,omitempty"`
	Summary             string             `json:"summary,omitempty"`
	GeneratedShortTitle string             `json:"generated_short_title,omitempty"`
	GeneratedLongTitle  string             `json:"generated_long_title,omitempty"`
	TitleSource         SessionTitleSource `json:"title_source,omitempty"`
	Provider            string             `json:"provider"`
	ProviderKey         string             `json:"provider_key,omitempty"`
	Model               string             `json:"model"`
	Mode                SessionMode        `json:"mode,omitempty"`
	Origin              SessionOrigin      `json:"origin,omitempty"`
	Archived            bool               `json:"archived,omitempty"`
	Pinned              bool               `json:"pinned,omitempty"`
	MessageCount        int                `json:"message_count"`
	TranscriptRev       int64              `json:"transcript_rev"`
	UserTurns           int                `json:"user_turns,omitempty"`
	LLMTurns            int                `json:"llm_turns,omitempty"`
	ToolCalls           int                `json:"tool_calls,omitempty"`
	InputTokens         int                `json:"input_tokens,omitempty"`
	CachedInputTokens   int                `json:"cached_input_tokens,omitempty"`
	CacheWriteTokens    int                `json:"cache_write_tokens,omitempty"`
	OutputTokens        int                `json:"output_tokens,omitempty"`
	Status              SessionStatus      `json:"status,omitempty"`
	Tags                string             `json:"tags,omitempty"`
	WorktreeDir         string             `json:"worktree_dir,omitempty"`
	Goal                *Goal              `json:"goal,omitempty"`
	Share               *ShareState        `json:"share,omitempty"`
	CreatedAt           time.Time          `json:"created_at"`
	UpdatedAt           time.Time          `json:"updated_at"`
	LastMessageAt       time.Time          `json:"last_message_at,omitempty"`
}

SessionSummary is a lightweight view of a session for listing.

func (SessionSummary) PreferredLongTitle added in v0.0.120

func (s SessionSummary) PreferredLongTitle() string

PreferredLongTitle returns the best long descriptive title available for the summary.

func (SessionSummary) PreferredShortTitle added in v0.0.120

func (s SessionSummary) PreferredShortTitle() string

PreferredShortTitle returns the best short title available for the summary.

type SessionSummaryTranscriptRevisionReporter added in v0.0.344

type SessionSummaryTranscriptRevisionReporter interface {
	SessionSummariesIncludeTranscriptRev() bool
}

SessionSummaryTranscriptRevisionReporter reports whether Store.List populates SessionSummary.TranscriptRev directly, allowing callers to avoid one revision query per listed session.

type SessionTitleSource added in v0.0.120

type SessionTitleSource string
const (
	TitleSourceNone      SessionTitleSource = ""
	TitleSourceUser      SessionTitleSource = "user"
	TitleSourceGenerated SessionTitleSource = "generated"
)

type ShareState added in v0.0.324

type ShareState struct {
	GistID     string    `json:"gist_id,omitempty"`
	GistURL    string    `json:"gist_url,omitempty"`
	PreviewURL string    `json:"preview_url,omitempty"`
	Public     bool      `json:"public,omitempty"`
	SharedAt   time.Time `json:"shared_at,omitempty"`
	UpdatedAt  time.Time `json:"updated_at,omitempty"`
}

ShareState records the current external share for a session.

func (*ShareState) Clone added in v0.0.324

func (s *ShareState) Clone() *ShareState

Clone returns a copy that callers may mutate safely.

func (*ShareState) Exists added in v0.0.324

func (s *ShareState) Exists() bool

Exists reports whether this state identifies a share.

type ShareUpdater added in v0.0.324

type ShareUpdater interface {
	UpdateShare(ctx context.Context, id string, share *ShareState) error
}

ShareUpdater is an optional Store capability for updating only share metadata.

type Store

type Store interface {
	// Session CRUD
	Create(ctx context.Context, s *Session) error
	Get(ctx context.Context, id string) (*Session, error)
	GetByNumber(ctx context.Context, number int64) (*Session, error)
	GetByPrefix(ctx context.Context, prefix string) (*Session, error)
	Update(ctx context.Context, s *Session) error
	MarkTitleSkipped(ctx context.Context, id string, t time.Time) error
	Delete(ctx context.Context, id string) error

	// Listing and search
	List(ctx context.Context, opts ListOptions) ([]SessionSummary, error)
	Search(ctx context.Context, opts SearchOptions) ([]SearchResult, error)

	// Message operations - stores full llm.Message with Parts
	AddMessage(ctx context.Context, sessionID string, msg *Message) error
	// UpdateMessage replaces the content of an existing message (by msg.ID) with
	// the supplied msg (role, parts, text, duration, sequence are updated in
	// place). Used for "persist as we go" upserts of an in-progress assistant
	// message during streaming. Returns ErrNotFound if the row does not exist.
	UpdateMessage(ctx context.Context, sessionID string, msg *Message) error
	GetMessages(ctx context.Context, sessionID string, limit, offset int) ([]Message, error)
	// GetMessagesFrom returns rows at/after fromSeq in sequence order. When limit
	// <= 0, all remaining rows are returned.
	GetMessagesFrom(ctx context.Context, sessionID string, fromSeq, limit int) ([]Message, error)
	// GetMessageByID retrieves a single message by its global message id.
	GetMessageByID(ctx context.Context, msgID int64) (*Message, error)
	ReplaceMessages(ctx context.Context, sessionID string, messages []Message) error
	CompactMessages(ctx context.Context, sessionID string, messages []Message) error

	// Metrics operations (for incremental session saving)
	UpdateMetrics(ctx context.Context, id string, llmTurns, toolCalls, inputTokens, outputTokens, cachedInputTokens, cacheWriteTokens int) error
	UpdateContextEstimate(ctx context.Context, id string, lastTotalTokens, lastMessageCount int) error
	UpdateStatus(ctx context.Context, id string, status SessionStatus) error
	IncrementUserTurns(ctx context.Context, id string) error

	// Current session tracking (for auto-resume)
	SetCurrent(ctx context.Context, sessionID string) error
	GetCurrent(ctx context.Context) (*Session, error)
	ClearCurrent(ctx context.Context) error

	// Push subscription management (for web push notifications)
	SavePushSubscription(ctx context.Context, sub *PushSubscription) error
	DeletePushSubscription(ctx context.Context, endpoint string) error
	ListPushSubscriptions(ctx context.Context) ([]PushSubscription, error)

	// Lifecycle
	Close() error
}

Store is the interface for session persistence.

func NewStore

func NewStore(cfg Config) (Store, error)

NewStore creates a new Store based on the configuration. If sessions are disabled, returns a no-op store.

type StreamingMessageUpdater added in v0.0.289

type StreamingMessageUpdater interface {
	UpdateStreamingMessage(ctx context.Context, sessionID string, msg *Message, finalizeText bool) error
}

StreamingMessageUpdater is an optional Store capability for the hot streaming assistant upsert path. Implementations may update role/parts/duration without rewriting the FTS-backed text_content column until finalizeText is true.

type TranscriptIndexItem added in v0.0.344

type TranscriptIndexItem struct {
	Seq                     int
	ID                      int64
	Role                    string
	Flags                   uint8
	ClientMessageID         string
	ResponseID              string
	AssistantSegmentOrdinal int
}

TranscriptIndexItem is the compact durable identity and ordering metadata for one UI-visible transcript row. IDs are stable identities; Seq is only the current ordering key.

type TranscriptIndexer added in v0.0.344

type TranscriptIndexer interface {
	GetTranscriptIndex(ctx context.Context, sessionID string) (rev int64, items []TranscriptIndexItem, err error)
	GetTranscriptSnapshot(ctx context.Context, sessionID string) (TranscriptSnapshot, error)
	GetMessagesByTranscriptRanges(ctx context.Context, sessionID string, ranges []TranscriptRange) (rev int64, messages []Message, err error)
	TranscriptRev(ctx context.Context, sessionID string) (int64, error)
}

TranscriptIndexer is an optional Store capability for coherent revisioned transcript reads. Implementations return each revision and its rows from one read transaction.

type TranscriptRange added in v0.0.344

type TranscriptRange struct {
	StartSeq int
	StartID  int64
	EndSeq   int
	EndID    int64
}

TranscriptRange identifies one complete, contiguous UI transcript segment by its inclusive durable ordering bounds. Sequence alone is not assumed unique, so IDs disambiguate both endpoints.

type TranscriptRevisionWriter added in v0.0.353

type TranscriptRevisionWriter interface {
	AddMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message) (int64, error)
	UpdateStreamingMessageWithTranscriptRev(ctx context.Context, sessionID string, msg *Message, finalizeText bool) (int64, error)
	ReplaceMessagesWithTranscriptRev(ctx context.Context, sessionID string, messages []Message) (int64, error)
}

TranscriptRevisionWriter reports the exact revision committed by a message mutation. Serve response handoff uses this optional capability instead of a session-wide post-write revision sample.

type TranscriptSnapshot added in v0.0.344

type TranscriptSnapshot struct {
	Rev             int64
	CompactionSeq   int
	CompactionCount int
	Items           []TranscriptIndexItem
}

TranscriptSnapshot is the complete compact identity stream and its session envelope read from one database snapshot.

type TranscriptVersionReporter added in v0.0.344

type TranscriptVersionReporter interface {
	TranscriptVersioned() bool
}

TranscriptVersionReporter distinguishes a current revisioned schema from an older read-only database where TranscriptIndexer exposes revision zero only.

type WarnFunc added in v0.0.41

type WarnFunc func(format string, args ...any)

WarnFunc is a function that logs warnings.

Jump to

Keyboard shortcuts

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