pub struct SessionStore { /* private fields */ }Expand description
SQLite-backed persistent session and cache store with FTS5 full-text search.
Stores sessions, cache entries, compression logs, and known files in a single SQLite database. Uses WAL mode for concurrent read access.
use sqz_engine::SessionStore;
use std::path::Path;
let store = SessionStore::open_or_create(Path::new("~/.sqz/sessions.db")).unwrap();
let results = store.search("authentication refactor").unwrap();
for session in &results {
println!("{}: {}", session.id, session.compressed_summary);
}Implementations§
Source§impl SessionStore
impl SessionStore
Sourcepub fn open(path: &Path) -> Result<Self>
pub fn open(path: &Path) -> Result<Self>
Open an existing database at path. Returns an error if the file does
not exist or cannot be opened.
Sourcepub fn open_or_create(path: &Path) -> Result<Self>
pub fn open_or_create(path: &Path) -> Result<Self>
Open the database at path, creating it if it does not exist.
If the database is corrupted, a fresh database is created at the same
path and a warning is logged to stderr.
Sourcepub fn save_session(&self, session: &SessionState) -> Result<SessionId>
pub fn save_session(&self, session: &SessionState) -> Result<SessionId>
Persist a session. Returns the session id.
Sourcepub fn save_dashboard_session(&self, id: &str, summary: &str) -> Result<()>
pub fn save_dashboard_session(&self, id: &str, summary: &str) -> Result<()>
Save a lightweight session from just an id and summary for dashboard use.
Sourcepub fn load_session(&self, id: SessionId) -> Result<SessionState>
pub fn load_session(&self, id: SessionId) -> Result<SessionState>
Load a session by id.
Sourcepub fn search(&self, query: &str) -> Result<Vec<SessionSummary>>
pub fn search(&self, query: &str) -> Result<Vec<SessionSummary>>
Full-text search using FTS5 (porter stemmer, ASCII tokenizer).
Sourcepub fn search_by_date(
&self,
from: DateTime<Utc>,
to: DateTime<Utc>,
) -> Result<Vec<SessionSummary>>
pub fn search_by_date( &self, from: DateTime<Utc>, to: DateTime<Utc>, ) -> Result<Vec<SessionSummary>>
Query sessions whose updated_at falls within [from, to].
Sourcepub fn latest_session(&self) -> Result<Option<SessionSummary>>
pub fn latest_session(&self) -> Result<Option<SessionSummary>>
Return the most recently updated session, or None if no sessions exist.
Sourcepub fn search_by_project(&self, dir: &Path) -> Result<Vec<SessionSummary>>
pub fn search_by_project(&self, dir: &Path) -> Result<Vec<SessionSummary>>
Query sessions whose project_dir matches dir exactly.
Sourcepub fn save_cache_entry(
&self,
hash: &str,
compressed: &CompressedContent,
) -> Result<()>
pub fn save_cache_entry( &self, hash: &str, compressed: &CompressedContent, ) -> Result<()>
Persist a cache entry keyed by content hash.
Stores both the compressed JSON (data) used for dedup-hit
responses AND the raw uncompressed bytes (original) so that
sqz expand <prefix> can serve truly uncompressed content. See
save_cache_entry_with_original
for the original-aware version; this convenience wrapper exists for
callers that do not (yet) have the pre-compression bytes handy. Rows
written through this path leave original as NULL, and expand
will degrade to returning the compressed blob with a note.
Sourcepub fn save_cache_entry_with_original(
&self,
hash: &str,
compressed: &CompressedContent,
original: Option<&[u8]>,
) -> Result<()>
pub fn save_cache_entry_with_original( &self, hash: &str, compressed: &CompressedContent, original: Option<&[u8]>, ) -> Result<()>
Persist a cache entry with both compressed and original content.
original must be the exact bytes that produced compressed, so
that expand is a true inverse of dedup. We store the raw bytes
(not the UTF-8 string) because command output may include
non-UTF-8 sequences — storing the text would lose them.
Sourcepub fn recall_search(&self, query: &str, limit: u32) -> Result<Vec<RecallHit>>
pub fn recall_search(&self, query: &str, limit: u32) -> Result<Vec<RecallHit>>
BM25-ranked full-text search over indexed content. Returns the
best limit hits with a highlighted snippet each.
Sourcepub fn compression_period(&self) -> Result<Option<(String, String)>>
pub fn compression_period(&self) -> Result<Option<(String, String)>>
First and last compression timestamps (RFC 3339), or None when
nothing has been logged yet.
Sourcepub fn get_cache_entry_original(&self, hash: &str) -> Result<Option<Vec<u8>>>
pub fn get_cache_entry_original(&self, hash: &str) -> Result<Option<Vec<u8>>>
Retrieve the stored original bytes for a cached hash, if the
caller populated them via save_cache_entry_with_original.
Returns Ok(None) for missing entries AND for entries that were
saved by an older call site that did not pass original. The
caller should fall back to the compressed blob in the latter case
and surface a note to the user so they know this specific entry
wasn’t round-trippable.
Sourcepub fn recent_originals(
&self,
min_len: usize,
limit: usize,
) -> Result<Vec<SliceCandidate>>
pub fn recent_originals( &self, min_len: usize, limit: usize, ) -> Result<Vec<SliceCandidate>>
Most recently accessed entries that still hold their original bytes
and are at least min_len bytes long, newest first. Candidates for
slice matching: a ranged re-read can only be a slice of something
larger than itself.
Sourcepub fn delete_cache_entry(&self, hash: &str) -> Result<()>
pub fn delete_cache_entry(&self, hash: &str) -> Result<()>
Delete a cache entry by content hash.
Sourcepub fn list_cache_entries_lru(&self) -> Result<Vec<(String, u64)>>
pub fn list_cache_entries_lru(&self) -> Result<Vec<(String, u64)>>
Return all cache entries ordered by accessed_at ASC (oldest first),
as (hash, size_bytes) pairs where size_bytes is the byte length of
the stored JSON data.
Sourcepub fn get_cache_entry(&self, hash: &str) -> Result<Option<CompressedContent>>
pub fn get_cache_entry(&self, hash: &str) -> Result<Option<CompressedContent>>
Retrieve a cache entry by content hash, updating accessed_at.
Sourcepub fn get_cache_entry_by_prefix(
&self,
prefix: &str,
) -> Result<Option<(String, CompressedContent)>>
pub fn get_cache_entry_by_prefix( &self, prefix: &str, ) -> Result<Option<(String, CompressedContent)>>
Look up a cache entry by a prefix of the content hash.
The inline dedup refs we hand to the LLM carry only the first 16
hex chars of the SHA-256 (§ref:<16-hex>§), so when an agent runs
sqz expand <prefix> we need to resolve those 16 chars back to the
full 64-char key. Uses LIKE 'prefix%' with an index-friendly
anchored pattern so the query stays O(log n) on the primary key.
Returns Ok(Some((full_hash, entry))) on unique match.
Returns Ok(None) if no entries match.
Returns Err(_) if the prefix is ambiguous (2+ matches) — the
caller should tell the user to use a longer prefix. 16-hex
collisions are astronomically unlikely (one in 2^64) but we
refuse to guess rather than quietly serve a surprise file.
The prefix is validated as lowercase hex. Non-hex input returns
None without touching the database — this is how we handle the
common user-error case of pasting the ref with the § markers
still attached (they get rejected before we query SQLite).
Sourcepub fn get_cache_entry_accessed_at(
&self,
hash: &str,
) -> Result<Option<DateTime<Utc>>>
pub fn get_cache_entry_accessed_at( &self, hash: &str, ) -> Result<Option<DateTime<Utc>>>
Read the accessed_at timestamp for a cached hash without updating
it. Returns None if the hash is not cached.
Used by the dedup freshness check: if accessed_at is recent, the
LLM likely still has the original content in its context window, so
returning a ref is safe. If it’s old, re-send the full content.
Sourcepub fn cache_entry_exists(&self, hash: &str) -> Result<bool>
pub fn cache_entry_exists(&self, hash: &str) -> Result<bool>
Check if a cache entry exists without updating accessed_at.
Sourcepub fn touch_cache_entry(&self, hash: &str) -> Result<()>
pub fn touch_cache_entry(&self, hash: &str) -> Result<()>
Update accessed_at for a cached hash to the current time. Called by
the cache manager when a ref is served so the next staleness check
sees the recent send.
Sourcepub fn resolve_cache_hash_by_prefix(
&self,
prefix: &str,
) -> Result<Option<String>>
pub fn resolve_cache_hash_by_prefix( &self, prefix: &str, ) -> Result<Option<String>>
Resolve a hash prefix (or full hash) to the unique full hash of
the matching cache entry. Returns Ok(None) for non-existent
entries. Returns an error if the prefix is ambiguous (matches
more than one entry) so the caller can ask for a longer prefix.
Does not touch accessed_at.
Sourcepub fn pin_cache_entry(&self, hash: &str) -> Result<bool>
pub fn pin_cache_entry(&self, hash: &str) -> Result<bool>
Mark a cache entry as pinned so it bypasses the TTL freshness
check. Returns Ok(true) if a row was updated, Ok(false) if the
hash is not in the cache.
Sourcepub fn unpin_cache_entry(&self, hash: &str) -> Result<bool>
pub fn unpin_cache_entry(&self, hash: &str) -> Result<bool>
Unpin a cache entry so it returns to normal TTL-based freshness.
Returns Ok(true) if a row was updated, Ok(false) otherwise.
Sourcepub fn unpin_all_cache_entries(&self) -> Result<usize>
pub fn unpin_all_cache_entries(&self) -> Result<usize>
Unpin every cache entry. Returns the count of rows that were previously pinned.
Sourcepub fn is_cache_entry_pinned(&self, hash: &str) -> Result<bool>
pub fn is_cache_entry_pinned(&self, hash: &str) -> Result<bool>
Whether the given hash is pinned. Returns false for unpinned
entries AND for hashes not in the cache.
Sourcepub fn list_pinned_cache_entries(
&self,
) -> Result<Vec<(String, DateTime<Utc>, u64)>>
pub fn list_pinned_cache_entries( &self, ) -> Result<Vec<(String, DateTime<Utc>, u64)>>
List every pinned cache entry. Returns (hash, accessed_at, size_bytes)
tuples so the CLI can render a useful table.
Sourcepub fn set_metadata(&self, key: &str, value: &str) -> Result<()>
pub fn set_metadata(&self, key: &str, value: &str) -> Result<()>
Set a metadata key/value. Persists across sqz process boundaries (each shell-hook invocation is a short-lived process).
Sourcepub fn get_metadata(&self, key: &str) -> Result<Option<String>>
pub fn get_metadata(&self, key: &str) -> Result<Option<String>>
Get a metadata value. Returns None if the key has never been set.
Sourcepub fn log_compression(
&self,
tokens_original: u32,
tokens_compressed: u32,
stages: &[String],
mode: &str,
) -> Result<()>
pub fn log_compression( &self, tokens_original: u32, tokens_compressed: u32, stages: &[String], mode: &str, ) -> Result<()>
Log a compression event for cumulative stats tracking.
Sourcepub fn log_compression_with_project(
&self,
tokens_original: u32,
tokens_compressed: u32,
stages: &[String],
mode: &str,
project_dir: Option<&str>,
) -> Result<()>
pub fn log_compression_with_project( &self, tokens_original: u32, tokens_compressed: u32, stages: &[String], mode: &str, project_dir: Option<&str>, ) -> Result<()>
Log a compression event tagged with a project directory.
Sourcepub fn log_regret(
&self,
kind: &str,
cmd: &str,
hash: &str,
gap_secs: f64,
) -> Result<()>
pub fn log_regret( &self, kind: &str, cmd: &str, hash: &str, gap_secs: f64, ) -> Result<()>
Log a compression-regret signal. kind is "rerun" (byte-identical
output re-produced within the regret window) or "expand" (a
§ref:…§ token expanded back to original bytes). gap_secs is the
time since the content was last seen; 0.0 when unknown.
Sourcepub fn regret_stats(&self) -> Result<RegretStats>
pub fn regret_stats(&self) -> Result<RegretStats>
Aggregate regret counts for sqz stats.
Sourcepub fn formatter_gaps(&self, days: u32, limit: u32) -> Result<Vec<CommandStats>>
pub fn formatter_gaps(&self, days: u32, limit: u32) -> Result<Vec<CommandStats>>
Command families where compression is barely helping: meaningful volume, under 25% reduction, ranked by tokens that still reached the model. This is the formatter backlog, computed from real history instead of guesses. Dedup rows are excluded (a ref is already the best possible outcome).
Sourcepub fn regret_by_command(&self, limit: u32) -> Result<Vec<(String, u32)>>
pub fn regret_by_command(&self, limit: u32) -> Result<Vec<(String, u32)>>
Rerun-regret counts grouped by command, most regretted first.
Sourcepub fn compression_stats(&self) -> Result<CompressionStats>
pub fn compression_stats(&self) -> Result<CompressionStats>
Get cumulative compression stats from the log.
Sourcepub fn inflated_rows(&self) -> Result<(u32, u64)>
pub fn inflated_rows(&self) -> Result<(u32, u64)>
Rows from the MCP read tools that record their output as larger than their input. Those tools serve content verbatim, so this can’t be real: sqz-mcp before 1.8.0 counted the input with chars/4 and the output with the BPE tokenizer. The output count is the accurate one. Returns (rows, tokens by which they understate the saved total).
Sourcepub fn backup_to(&self, dest: &Path) -> Result<()>
pub fn backup_to(&self, dest: &Path) -> Result<()>
Write a consistent copy of the database to dest. Unlike copying the
file, this includes transactions still sitting in the WAL. Fails if
dest already exists.
Sourcepub fn clamp_inflated_rows(&self) -> Result<usize>
pub fn clamp_inflated_rows(&self) -> Result<usize>
Correct the rows inflated_rows reports, in
place: raise the input count to the output count. The call keeps its
real volume and is recorded as saving nothing, which is what a
verbatim read saves.
Returns the number of rows changed.
Sourcepub fn daily_gains(&self, days: u32) -> Result<Vec<DailyGain>>
pub fn daily_gains(&self, days: u32) -> Result<Vec<DailyGain>>
Get daily compression gains for the last N days.
Sourcepub fn compression_stats_for_project(
&self,
project_dir: &str,
) -> Result<CompressionStats>
pub fn compression_stats_for_project( &self, project_dir: &str, ) -> Result<CompressionStats>
Get cumulative compression stats for a specific project directory.
Sourcepub fn daily_gains_for_project(
&self,
days: u32,
project_dir: &str,
) -> Result<Vec<DailyGain>>
pub fn daily_gains_for_project( &self, days: u32, project_dir: &str, ) -> Result<Vec<DailyGain>>
Get daily compression gains for a specific project directory.
Sourcepub fn list_projects(&self) -> Result<Vec<(String, u32, u64)>>
pub fn list_projects(&self) -> Result<Vec<(String, u32, u64)>>
List distinct project directories that have compression data.
Sourcepub fn command_breakdown(&self, limit: u32) -> Result<Vec<CommandStats>>
pub fn command_breakdown(&self, limit: u32) -> Result<Vec<CommandStats>>
Per-command breakdown of token usage. Returns top N commands by
total tokens consumed, with compression stats for each.
Used by sqz stats --breakdown to show where tokens are going.
Sourcepub fn command_breakdown_for_project(
&self,
limit: u32,
project_dir: &str,
) -> Result<Vec<CommandStats>>
pub fn command_breakdown_for_project( &self, limit: u32, project_dir: &str, ) -> Result<Vec<CommandStats>>
Per-command breakdown filtered to a specific project.
Sourcepub fn session_pressure(&self, since_minutes: u32) -> Result<u64>
pub fn session_pressure(&self, since_minutes: u32) -> Result<u64>
Get the total tokens injected in the current session (since last compaction or start). Used by the adaptive pressure system to decide whether to escalate compression intensity.
Sourcepub fn add_known_file(&self, path: &str) -> Result<()>
pub fn add_known_file(&self, path: &str) -> Result<()>
Record a file path as “known” (its content is in the dedup cache). Used by cross-command context refs to annotate error messages.
Sourcepub fn known_files(&self) -> Result<Vec<String>>
pub fn known_files(&self) -> Result<Vec<String>>
Load all known file paths from the persistent store.
Sourcepub fn clear_known_files(&self) -> Result<()>
pub fn clear_known_files(&self) -> Result<()>
Clear all known files (e.g. on session reset).
Sourcepub fn cache_entry_count(&self) -> Result<u64>
pub fn cache_entry_count(&self) -> Result<u64>
Number of entries currently in the dedup cache.
Sourcepub fn record_cache_hit(&self) -> Result<()>
pub fn record_cache_hit(&self) -> Result<()>
Increment the cache-hit counter (persisted in metadata).
Sourcepub fn record_cache_miss(&self) -> Result<()>
pub fn record_cache_miss(&self) -> Result<()>
Increment the cache-miss counter (persisted in metadata).
Sourcepub fn cache_hit_miss_counts(&self) -> Result<(u64, u64)>
pub fn cache_hit_miss_counts(&self) -> Result<(u64, u64)>
Return (cache_hits, cache_misses) from metadata counters.
Sourcepub fn clear_cache(&self) -> Result<u64>
pub fn clear_cache(&self) -> Result<u64>
Clear the dedup cache. After this, all future reads will be treated as cache misses and compressed fresh. Does NOT clear compression stats or session history.
Sourcepub fn clear_stats(&self) -> Result<u64>
pub fn clear_stats(&self) -> Result<u64>
Clear compression stats (the compression_log table). After this,
sqz stats and sqz gain will show zero until new compressions
happen.
Sourcepub fn clear_stats_for_project(&self, project_dir: &str) -> Result<u64>
pub fn clear_stats_for_project(&self, project_dir: &str) -> Result<u64>
Clear compression stats for a specific project directory only.
Sourcepub fn reset_all(&self) -> Result<()>
pub fn reset_all(&self) -> Result<()>
Full reset: clear cache, stats, sessions, known files, and metadata. Equivalent to deleting sessions.db and letting sqz recreate it.
Sourcepub fn list_sessions(&self, limit: u32) -> Result<Vec<SessionSummary>>
pub fn list_sessions(&self, limit: u32) -> Result<Vec<SessionSummary>>
Return all sessions ordered by most recently updated, limited to limit.