store

package
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package store persists sessions and messages to a local SQLite database so the daemon remains the single source of truth across restarts — a client disconnecting, or the daemon itself being restarted, never loses a session's history, including its tool-call trail.

Index

Constants

View Source
const (
	SearchScopeUser = "user" // default: exclude subagent-run sessions
	SearchScopeAll  = "all"  // include subagent-run sessions too
)

SearchScope controls whether subagent-run sessions (title prefixed "subagent: ", see internal/daemon/agent RunTask) are included in session_search results. Subagent sessions are internal execution noise from delegate_task, not conversations the user had, so they're excluded by default rather than merely ranked lower — a noisy subagent transcript that happens to repeat the user's search term would otherwise crowd out the real conversation it was talking about.

View Source
const GlobalScope = "_global"

GlobalScope holds memory that applies across every project, not just the one it was written in — e.g. a standing user preference.

Variables

This section is empty.

Functions

This section is empty.

Types

type MemoryEntry

type MemoryEntry struct {
	ID        int64  `json:"id"`
	Scope     string `json:"scope"`
	Content   string `json:"content"`
	Pinned    bool   `json:"pinned"`
	CreatedAt int64  `json:"created_at"`
	UpdatedAt int64  `json:"updated_at"`
}

MemoryEntry is one compiled fact or note the agent chose to remember — written by the agent itself via a tool call, not captured automatically from raw conversation logs. Scope is either a workspace path (memory specific to one project) or GlobalScope (memory that applies everywhere).

type Message

type Message struct {
	ID         int64             `json:"id"`
	SessionID  string            `json:"session_id"`
	Role       string            `json:"role"`
	Content    string            `json:"content"`
	Provider   string            `json:"provider,omitempty"`
	ToolCalls  []openai.ToolCall `json:"tool_calls,omitempty"`
	ToolCallID string            `json:"tool_call_id,omitempty"`
	Name       string            `json:"name,omitempty"`
	Images     []string          `json:"images,omitempty"`
	CreatedAt  int64             `json:"created_at"`
}

Message is one turn within a session — a user message, an assistant reply (Provider set to whoever served it, ToolCalls set if it's requesting tool invocations instead of/before answering), or a tool result (Role "tool", ToolCallID + Name identifying which call it answers). Name doubles as the marker for a compaction summary message (Name == CompactionMarker) — see internal/daemon/compaction.

type SearchResult

type SearchResult struct {
	Message      Message   `json:"message"`
	SessionTitle string    `json:"session_title"`
	IsSubagent   bool      `json:"is_subagent"`
	Window       []Message `json:"window"`
	// Score is the raw FTS5 bm25() value for this match (negative,
	// more-negative-is-better) — exported mainly so ranking behavior is
	// directly testable/inspectable, not something callers need to
	// interpret themselves.
	Score float64 `json:"-"`
}

SearchResult is one match from SearchMessages: the message that matched the query, which session it's from, and a chronological window of surrounding messages from that same session for context.

type Session

type Session struct {
	ID        string `json:"id"`
	Title     string `json:"title"`
	CreatedAt int64  `json:"created_at"`
	UpdatedAt int64  `json:"updated_at"`
}

Session is a durable conversation thread owned by the daemon.

type Store

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

Store wraps the SQLite connection and the daemon's persistence methods.

func Open

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

Open opens (creating if needed) the SQLite database at path and applies the schema. The connection pool is capped at 1 writer to avoid SQLite's "database is locked" errors under concurrent writes — fine for a local daemon's request volume.

func (*Store) AppendMessage

func (s *Store) AppendMessage(sessionID string, msg Message) (Message, error)

AppendMessage stores one message and touches the parent session's updated_at timestamp. Callers set only the fields relevant to the message's role; ID and CreatedAt are assigned here.

func (*Store) Close

func (s *Store) Close() error

Close releases the underlying database connection.

func (*Store) CreateSession

func (s *Store) CreateSession(id, title string) (Session, error)

CreateSession inserts a new, empty session.

func (*Store) DeleteMemoryEntry

func (s *Store) DeleteMemoryEntry(id int64) error

DeleteMemoryEntry removes one entry by ID.

func (*Store) GetSession

func (s *Store) GetSession(id string) (Session, error)

GetSession returns one session and returns sql.ErrNoRows if it doesn't exist.

func (*Store) ListMessages

func (s *Store) ListMessages(sessionID string) ([]Message, error)

ListMessages returns every message in a session, oldest first, including the full tool-call/tool-result trail and any compaction summaries.

func (*Store) ListSessions

func (s *Store) ListSessions() ([]Session, error)

ListSessions returns all sessions, most recently updated first.

func (*Store) RecentMemory

func (s *Store) RecentMemory(scopes []string, limit int) ([]MemoryEntry, error)

RecentMemory returns pinned entries first, then the most recently updated ones, across the given scopes (typically the current workspace plus GlobalScope) — this is what gets injected automatically at the start of every turn, so it's kept small and bounded by limit; anything older or from another scope is reachable via SearchMemory instead.

func (*Store) ScopeMemory

func (s *Store) ScopeMemory(scope string) ([]MemoryEntry, error)

ScopeMemory returns every entry in one scope, pinned first then newest, with no limit — used to enforce the per-scope size cap and to show the agent everything it has to work with when consolidating.

func (*Store) ScopeMemorySize

func (s *Store) ScopeMemorySize(scope string) (int, error)

ScopeMemorySize is the total character count of a scope's memory — what the cap is enforced against.

func (*Store) SearchMemory

func (s *Store) SearchMemory(scopes []string, query string, limit int) ([]MemoryEntry, error)

SearchMemory does a full-text search (SQLite FTS5) over memory content within the given scopes — this is the agent's memory_search tool.

func (*Store) SearchMessages

func (s *Store) SearchMessages(query string, limit int, scope string) ([]SearchResult, error)

SearchMessages does a full-text search (SQLite FTS5, BM25 ranking) over real conversation history — user and assistant messages actually exchanged, never tool output or system/compaction framing (see searchSchema). Ranking is BM25 first; matches whose scores are within relevanceTieTolerance of each other are then reordered by recency (newest first), since "how relevant" and "how long ago" both matter and a near-tie on relevance shouldn't be decided by incidental row order. scope controls whether subagent-run sessions are included (SearchScopeUser excludes them, SearchScopeAll includes them); anything else is treated as SearchScopeUser.

func (*Store) UpdateMemoryEntry

func (s *Store) UpdateMemoryEntry(id int64, content string) error

UpdateMemoryEntry replaces one entry's content in place, keeping its ID and created_at — the "replace" half of the add/replace/remove trio the agent needs to consolidate memory when it hits the size cap.

func (*Store) WriteMemoryEntry

func (s *Store) WriteMemoryEntry(scope, content string, pinned bool) (MemoryEntry, error)

WriteMemoryEntry stores one compiled memory entry.

Jump to

Keyboard shortcuts

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