Documentation
¶
Overview ¶
Package search provides cross-session search indexing capabilities. It builds an index of session conversations for fast semantic lookup without importing pkg/agent to avoid circular dependencies.
Index ¶
- func DefaultIndexPath() string
- func FormatResults(results []SearchResult) string
- func InitGlobalUpdater(indexPath, sessionsDir string)
- func MarkSessionDirty(sessionID string)
- func RestoreGlobalUpdater(old *IndexUpdater)
- func SaveIndex(path string, idx *SessionIndex) error
- func WalkSessions(sessionsDir string) ([]string, error)
- type IndexUpdater
- type SearchOptions
- type SearchResult
- type SessionIndex
- type SessionIndexEntry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultIndexPath ¶
func DefaultIndexPath() string
DefaultIndexPath returns the default location for the search index file in the state directory. Returns "" if the state dir cannot be resolved.
func FormatResults ¶
func FormatResults(results []SearchResult) string
FormatResults renders search results as a human-readable text block suitable for CLI output. Each result is formatted as:
[YYYY-MM-DD] name — working_dir excerpt
Results are separated by a single blank line. If the slice is empty, the function returns "No matching sessions."
func InitGlobalUpdater ¶
func InitGlobalUpdater(indexPath, sessionsDir string)
InitGlobalUpdater lazily initializes the process-global IndexUpdater. Subsequent calls are no-ops (sync.Once).
func MarkSessionDirty ¶
func MarkSessionDirty(sessionID string)
MarkSessionDirty is a convenience wrapper that calls GlobalUpdater.MarkDirty. If the global updater hasn't been initialized yet, it does nothing (safe no-op).
func RestoreGlobalUpdater ¶
func RestoreGlobalUpdater(old *IndexUpdater)
RestoreGlobalUpdater puts the global back to its prior state after a test called ResetGlobalUpdaterForTest. Stops the current global first.
func SaveIndex ¶
func SaveIndex(path string, idx *SessionIndex) error
SaveIndex atomically writes the search index to disk.
The index is first written to path+".tmp" with 0600 permissions, synced to disk via Close(), then renamed into place. Parent directories are created if they do not exist. idx.BuiltAt is updated to the current time before serialisation.
func WalkSessions ¶
WalkSessions returns a sorted list of all session_*.json files found under sessionsDir (recursive). If the directory does not exist an empty slice is returned (not an error).
Types ¶
type IndexUpdater ¶
type IndexUpdater struct {
// contains filtered or unexported fields
}
IndexUpdater debounces index writes to avoid disk thrash.
var (
GlobalUpdater *IndexUpdater
)
func NewIndexUpdater ¶
func NewIndexUpdater(indexPath, sessionsDir string) *IndexUpdater
NewIndexUpdater creates an updater that writes to indexPath from sessionsDir.
func ResetGlobalUpdaterForTest ¶
func ResetGlobalUpdaterForTest() (old *IndexUpdater)
ResetGlobalUpdaterForTest stops the current global updater (if any), then re-initializes the sync.Once so subsequent InitGlobalUpdater calls take effect. Returns the previous updater so callers can restore it. Intended for tests that need to redirect the index to a temp dir.
Note: the underlying *IndexUpdater may still hold pending timer events scheduled with the OLD path. The Stop() call here cancels them.
func (*IndexUpdater) Flush ¶
func (u *IndexUpdater) Flush() error
Flush forces an immediate rebuild + save (e.g. on shutdown).
func (*IndexUpdater) MarkDirty ¶
func (u *IndexUpdater) MarkDirty(sessionID string)
MarkDirty marks a session ID as needing an index update. Coalesces with previous uncommitted marks. Schedules a debounced rebuild.
type SearchOptions ¶
type SearchOptions struct {
// Query is the search string (required). Whitespace-separated tokens
// are treated as individual terms; the full query is also tested as an
// exact phrase.
Query string
// WorkingDir restricts results to entries whose WorkingDir exactly
// matches this value. Empty string means no filter.
WorkingDir string
// Since limits results to entries with LastUpdated >= Since. Zero
// value disables the filter.
Since time.Time
// Until limits results to entries with LastUpdated <= Until. Zero
// value disables the filter.
Until time.Time
// Limit caps the number of returned results. Zero uses the default
// of 20.
Limit int
}
SearchOptions configures a search query against a SessionIndex.
type SearchResult ¶
type SearchResult struct {
SessionID string `json:"session_id"`
Name string `json:"name"`
WorkingDir string `json:"working_directory"`
LastUpdated time.Time `json:"last_updated"`
TotalCost float64 `json:"total_cost"`
Excerpt string `json:"excerpt"`
MatchScore int `json:"match_score"` // 1 (any term), 2 (all terms), 3 (exact phrase)
}
SearchResult is a single matched session with a formatted excerpt.
func Search ¶
func Search(idx *SessionIndex, opts SearchOptions) []SearchResult
Search runs the query against the index and returns ranked results.
Results are scored in three tiers (higher is better):
- 3: the full query phrase appears in the entry's text.
- 2: every whitespace-separated term appears (but not necessarily adjacent).
- 1: at least one term appears.
Ties are broken by recency (newer LastUpdated first). Filters (WorkingDir, Since, Until) are applied before ranking so that only eligible entries are considered.
type SessionIndex ¶
type SessionIndex struct {
Version int `json:"version"`
BuiltAt time.Time `json:"built_at"`
Sessions map[string]SessionIndexEntry `json:"sessions"`
}
SessionIndex is the top-level search index structure.
func BuildIndex ¶
func BuildIndex(sessionsDir string, idx *SessionIndex) (*SessionIndex, error)
BuildIndex walks the sessions directory and builds (or updates) the SessionIndex for every session_*.json file it finds.
The walk is recursive to discover scoped sub-directories under the sessions base (e.g. ~/.sprout/sessions/scoped/<hash>/).
Incremental update: if idx already has an entry for a session whose LastUpdated timestamp matches the file's mtime, that entry is kept without re-parsing. Entries whose session files no longer exist on disk are removed from the index.
idx.Version is set to 1 and idx.BuiltAt is updated to now.
func LoadIndex ¶
func LoadIndex(path string) (*SessionIndex, error)
LoadIndex reads and parses the search index from the given path.
If the file does not exist a zero-value SessionIndex with an initialised (non-nil) Sessions map is returned — not an error. Malformed JSON returns the underlying parse error.
type SessionIndexEntry ¶
type SessionIndexEntry struct {
SessionID string `json:"session_id"`
Name string `json:"name"`
WorkingDir string `json:"working_directory"`
LastUpdated time.Time `json:"last_updated"`
TotalCost float64 `json:"total_cost"`
MessageCount int `json:"message_count"`
Tokens map[string][]int `json:"tokens"` // [start, end] byte offsets in Text
Text string `json:"text"` // Concatenated user/assistant messages, lowercased
}
SessionIndexEntry holds indexed data for a single session.