pub struct StateStore { /* private fields */ }Expand description
Persistent storage for conversation threads, messages, checkpoints, and jobs.
Backed by a SQLite database and an append-only JSONL session index file.
The database schema is automatically initialized and migrated on open.
Implementations§
Source§impl StateStore
impl StateStore
Sourcepub fn open(path: Option<PathBuf>) -> Result<Self>
pub fn open(path: Option<PathBuf>) -> Result<Self>
Open (or create) a state store at the given database path.
If path is None, the default location (~/.codewhale/state.db, with
~/.deepseek/state.db as a legacy fallback) is used.
The database schema is created automatically if it does not exist.
Sourcepub fn upsert_thread(&self, thread: &ThreadMetadata) -> Result<()>
pub fn upsert_thread(&self, thread: &ThreadMetadata) -> Result<()>
Insert or update thread metadata.
This does not update current_leaf_id; use append_message
or set_current_leaf_id for that.
Sourcepub fn get_thread(&self, id: &str) -> Result<Option<ThreadMetadata>>
pub fn get_thread(&self, id: &str) -> Result<Option<ThreadMetadata>>
Retrieve a single thread by its ID.
Returns None if no thread with the given ID exists.
Sourcepub fn list_threads(
&self,
filters: ThreadListFilters,
) -> Result<Vec<ThreadMetadata>>
pub fn list_threads( &self, filters: ThreadListFilters, ) -> Result<Vec<ThreadMetadata>>
List threads ordered by most recently updated.
Use ThreadListFilters to control whether archived threads are included
and the maximum number of results returned.
Sourcepub fn mark_archived(&self, id: &str) -> Result<()>
pub fn mark_archived(&self, id: &str) -> Result<()>
Archive a thread, setting its status to ThreadStatus::Archived and
recording the current timestamp.
Sourcepub fn mark_unarchived(&self, id: &str) -> Result<()>
pub fn mark_unarchived(&self, id: &str) -> Result<()>
Unarchive a thread, removing the archived flag and clearing archived_at.
Sourcepub fn delete_thread(&self, id: &str) -> Result<()>
pub fn delete_thread(&self, id: &str) -> Result<()>
Permanently delete a thread and all of its associated data (messages, checkpoints, dynamic tools) via cascading foreign keys.
Sourcepub fn set_thread_memory_mode(&self, id: &str, mode: Option<&str>) -> Result<()>
pub fn set_thread_memory_mode(&self, id: &str, mode: Option<&str>) -> Result<()>
Set the memory mode for a thread.
Pass None to clear the memory mode.
Sourcepub fn get_thread_memory_mode(&self, id: &str) -> Result<Option<String>>
pub fn get_thread_memory_mode(&self, id: &str) -> Result<Option<String>>
Get the memory mode configured for a thread.
Returns None if the thread does not exist or has no memory mode set.
Sourcepub fn upsert_thread_goal(&self, goal: &ThreadGoalRecord) -> Result<()>
pub fn upsert_thread_goal(&self, goal: &ThreadGoalRecord) -> Result<()>
Insert or replace the persisted goal for a thread.
Sourcepub fn record_thread_goal_usage(
&self,
thread_id: &str,
token_delta: i64,
time_delta_seconds: i64,
now: i64,
) -> Result<Option<ThreadGoalRecord>>
pub fn record_thread_goal_usage( &self, thread_id: &str, token_delta: i64, time_delta_seconds: i64, now: i64, ) -> Result<Option<ThreadGoalRecord>>
Accrue additional token and wall-clock usage onto a thread’s persisted goal.
This is the durable, additive accounting path for the persistent goal loop: it
increments tokens_used and time_used_seconds in a single atomic SQL UPDATE
(col = col + ?) so concurrent accruals do not race a read-modify-write. The
goal’s updated_at is advanced to the larger of its current value and now,
keeping the timestamp monotonic even if a stale now is supplied.
token_delta and time_delta_seconds are added on the database side; callers
should pass non-negative deltas (negative values are accepted and will decrement,
which is intentionally left to the caller’s discretion).
Returns the updated ThreadGoalRecord, or Ok(None) if the thread has no
persisted goal. Unlike upsert_thread_goal this never
creates a goal row; it only accumulates onto an existing one.
Sourcepub fn record_thread_goal_continuation(
&self,
thread_id: &str,
now: i64,
) -> Result<Option<ThreadGoalRecord>>
pub fn record_thread_goal_continuation( &self, thread_id: &str, now: i64, ) -> Result<Option<ThreadGoalRecord>>
Increment the durable cross-turn continuation counter for a thread goal.
The older TUI continuation guard is scoped to one engine turn. This
counter is intentionally persisted so a resumed goal loop can feed
goal_loop::decide_continuation with the true cross-turn count.
Sourcepub fn get_thread_goal(
&self,
thread_id: &str,
) -> Result<Option<ThreadGoalRecord>>
pub fn get_thread_goal( &self, thread_id: &str, ) -> Result<Option<ThreadGoalRecord>>
Retrieve the persisted goal for a thread.
Sourcepub fn delete_thread_goal(&self, thread_id: &str) -> Result<bool>
pub fn delete_thread_goal(&self, thread_id: &str) -> Result<bool>
Delete the persisted goal for a thread.
Sourcepub fn list_leaf_messages(&self, thread_id: &str) -> Result<Vec<MessageRecord>>
pub fn list_leaf_messages(&self, thread_id: &str) -> Result<Vec<MessageRecord>>
List all leaf messages in a thread.
A leaf message is one that has no other message referencing it as a parent. In a branching conversation tree, there may be multiple leaf messages.
Sourcepub fn set_current_leaf_id(
&self,
thread_id: &str,
current_leaf_id: &str,
) -> Result<()>
pub fn set_current_leaf_id( &self, thread_id: &str, current_leaf_id: &str, ) -> Result<()>
Update the current leaf message pointer for a thread.
This controls which branch of the conversation tree is considered active
when listing messages via list_messages.
Sourcepub fn persist_dynamic_tools(
&self,
thread_id: &str,
tools: &[DynamicToolRecord],
) -> Result<()>
pub fn persist_dynamic_tools( &self, thread_id: &str, tools: &[DynamicToolRecord], ) -> Result<()>
Replace the dynamic tools for a thread.
All existing dynamic tools for the thread are deleted and replaced with the provided list. The operation is performed within a transaction.
Sourcepub fn get_dynamic_tools(
&self,
thread_id: &str,
) -> Result<Vec<DynamicToolRecord>>
pub fn get_dynamic_tools( &self, thread_id: &str, ) -> Result<Vec<DynamicToolRecord>>
Retrieve all dynamic tools registered for a thread, ordered by position.
Sourcepub fn append_message(
&self,
thread_id: &str,
role: &str,
content: &str,
item: Option<Value>,
) -> Result<i64>
pub fn append_message( &self, thread_id: &str, role: &str, content: &str, item: Option<Value>, ) -> Result<i64>
Append a new message to a thread.
The message is linked to the thread’s current leaf as its parent, and the
thread’s current_leaf_id is updated to the new message. Returns the ID
of the newly created message.
Sourcepub fn list_messages(
&self,
thread_id: &str,
limit: Option<usize>,
) -> Result<Vec<MessageRecord>>
pub fn list_messages( &self, thread_id: &str, limit: Option<usize>, ) -> Result<Vec<MessageRecord>>
List messages in the current conversation branch, walking backwards from
the thread’s current_leaf_id.
Messages are returned in chronological order (oldest first). The limit
parameter caps how many ancestor messages are traversed; it defaults to 500.
Sourcepub fn fork_at_message(
&self,
message_id: &str,
role: &str,
content: &str,
item: Option<Value>,
) -> Result<i64>
pub fn fork_at_message( &self, message_id: &str, role: &str, content: &str, item: Option<Value>, ) -> Result<i64>
Fork the conversation at a specific message.
Creates a new message whose parent is message_id and updates the thread’s
current_leaf_id to the new message. Returns the ID of the new message.
This enables branching conversations from any point in the history.
Sourcepub fn clear_messages(&self, thread_id: &str) -> Result<usize>
pub fn clear_messages(&self, thread_id: &str) -> Result<usize>
Delete all messages belonging to a thread and reset its current_leaf_id.
Returns the number of messages deleted.
Sourcepub fn save_checkpoint(
&self,
thread_id: &str,
checkpoint_id: &str,
state: &Value,
) -> Result<()>
pub fn save_checkpoint( &self, thread_id: &str, checkpoint_id: &str, state: &Value, ) -> Result<()>
Save (or update) a named checkpoint for a thread.
If a checkpoint with the same thread_id and checkpoint_id already exists,
its state and timestamp are overwritten.
Sourcepub fn load_checkpoint(
&self,
thread_id: &str,
checkpoint_id: Option<&str>,
) -> Result<Option<CheckpointRecord>>
pub fn load_checkpoint( &self, thread_id: &str, checkpoint_id: Option<&str>, ) -> Result<Option<CheckpointRecord>>
Load a checkpoint for a thread.
If checkpoint_id is provided, loads that specific checkpoint. Otherwise,
loads the most recently created checkpoint for the thread. Returns None
if no matching checkpoint exists.
Sourcepub fn list_checkpoints(
&self,
thread_id: &str,
limit: Option<usize>,
) -> Result<Vec<CheckpointRecord>>
pub fn list_checkpoints( &self, thread_id: &str, limit: Option<usize>, ) -> Result<Vec<CheckpointRecord>>
List checkpoints for a thread, ordered by creation time (newest first).
The limit parameter caps the number of results and defaults to 100.
Sourcepub fn delete_checkpoint(
&self,
thread_id: &str,
checkpoint_id: &str,
) -> Result<()>
pub fn delete_checkpoint( &self, thread_id: &str, checkpoint_id: &str, ) -> Result<()>
Delete a specific checkpoint from a thread.
Sourcepub fn upsert_job(&self, job: &JobStateRecord) -> Result<()>
pub fn upsert_job(&self, job: &JobStateRecord) -> Result<()>
Insert or update a background job record.
Sourcepub fn get_job(&self, id: &str) -> Result<Option<JobStateRecord>>
pub fn get_job(&self, id: &str) -> Result<Option<JobStateRecord>>
Retrieve a single job by its ID.
Returns None if no job with the given ID exists.
Sourcepub fn list_jobs(&self, limit: Option<usize>) -> Result<Vec<JobStateRecord>>
pub fn list_jobs(&self, limit: Option<usize>) -> Result<Vec<JobStateRecord>>
List jobs ordered by most recently updated.
The limit parameter caps the number of results and defaults to 100.
Sourcepub fn delete_job(&self, id: &str) -> Result<()>
pub fn delete_job(&self, id: &str) -> Result<()>
Permanently delete a job record.
Sourcepub fn find_rollout_path_by_id(&self, id: &str) -> Result<Option<PathBuf>>
pub fn find_rollout_path_by_id(&self, id: &str) -> Result<Option<PathBuf>>
Look up the rollout file path for a thread by its ID.
Sourcepub fn append_thread_name(
&self,
thread_id: &str,
thread_name: Option<String>,
updated_at: i64,
rollout_path: Option<PathBuf>,
) -> Result<()>
pub fn append_thread_name( &self, thread_id: &str, thread_name: Option<String>, updated_at: i64, rollout_path: Option<PathBuf>, ) -> Result<()>
Append an entry to the JSONL session index file.
The session index is an append-only log that maps thread IDs to their names, update timestamps, and rollout paths. It is used for fast name-based lookups without opening the SQLite database.
Sourcepub fn find_thread_name_by_id(&self, thread_id: &str) -> Result<Option<String>>
pub fn find_thread_name_by_id(&self, thread_id: &str) -> Result<Option<String>>
Find the display name for a thread by its ID, using the session index.
Returns None if the thread is not in the index or has no name.
Trait Implementations§
Source§impl Clone for StateStore
impl Clone for StateStore
Source§fn clone(&self) -> StateStore
fn clone(&self) -> StateStore
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more