pub struct Database { /* private fields */ }Expand description
Wrapper around the SQLite connection pool.
Implementations§
Source§impl Database
impl Database
Sourcepub async fn init(koda_config_dir: &Path) -> Result<Self>
pub async fn init(koda_config_dir: &Path) -> Result<Self>
Initialize the database, run migrations, and enable WAL mode.
koda_config_dir is the koda configuration directory (e.g. ~/.config/koda).
The database lives in <koda_config_dir>/db/koda.db.
Production callers should pass db::config_dir()?; tests pass a temp dir.
Trait Implementations§
Source§impl Persistence for Database
impl Persistence for Database
Source§fn create_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
agent_name: &'life1 str,
project_root: &'life2 Path,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn create_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
agent_name: &'life1 str,
project_root: &'life2 Path,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Create a new session, returning the generated session ID.
Source§fn insert_message<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
role: &'life2 Role,
content: Option<&'life3 str>,
tool_calls: Option<&'life4 str>,
tool_call_id: Option<&'life5 str>,
usage: Option<&'life6 TokenUsage>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
fn insert_message<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
role: &'life2 Role,
content: Option<&'life3 str>,
tool_calls: Option<&'life4 str>,
tool_call_id: Option<&'life5 str>,
usage: Option<&'life6 TokenUsage>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
Insert a message into the conversation log.
Source§fn insert_message_with_agent<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'life7, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
role: &'life2 Role,
content: Option<&'life3 str>,
tool_calls: Option<&'life4 str>,
tool_call_id: Option<&'life5 str>,
usage: Option<&'life6 TokenUsage>,
agent_name: Option<&'life7 str>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
'life7: 'async_trait,
fn insert_message_with_agent<'life0, 'life1, 'life2, 'life3, 'life4, 'life5, 'life6, 'life7, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
role: &'life2 Role,
content: Option<&'life3 str>,
tool_calls: Option<&'life4 str>,
tool_call_id: Option<&'life5 str>,
usage: Option<&'life6 TokenUsage>,
agent_name: Option<&'life7 str>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
'life5: 'async_trait,
'life6: 'async_trait,
'life7: 'async_trait,
Insert a message with an optional agent name for cost tracking.
Source§fn load_context<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn load_context<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Load active (non-compacted) messages for a session.
Returns messages in chronological order. Compacted messages
(archived by /compact) are excluded — their summary replaces them.
Mismatched tool_use/tool_result pairs are pruned (#428).
Source§fn load_all_messages<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn load_all_messages<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<Message>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Load ALL messages for a session (for RecallContext search). Returns messages in chronological order, no truncation.
Source§fn recent_user_messages<'life0, 'async_trait>(
&'life0 self,
limit: i64,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn recent_user_messages<'life0, 'async_trait>(
&'life0 self,
limit: i64,
) -> Pin<Box<dyn Future<Output = Result<Vec<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Load recent user messages across all sessions (for the startup banner).
Returns up to limit messages, newest first.
Source§fn session_token_usage<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<SessionUsage>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn session_token_usage<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<SessionUsage>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get token usage totals for a session.
Source§fn session_usage_by_agent<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, SessionUsage)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn session_usage_by_agent<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, SessionUsage)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get token usage broken down by agent name.
Source§fn list_sessions<'life0, 'life1, 'async_trait>(
&'life0 self,
limit: i64,
project_root: &'life1 Path,
) -> Pin<Box<dyn Future<Output = Result<Vec<SessionInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_sessions<'life0, 'life1, 'async_trait>(
&'life0 self,
limit: i64,
project_root: &'life1 Path,
) -> Pin<Box<dyn Future<Output = Result<Vec<SessionInfo>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
List recent sessions for a specific project.
Source§fn last_assistant_message<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn last_assistant_message<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get the last assistant text response for a session (for headless JSON output).
Source§fn last_user_message<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn last_user_message<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get the last user message in a session.
Source§fn delete_session<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_session<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Delete a session and all its messages/metadata atomically.
Source§fn compact_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
summary: &'life2 str,
preserve_count: usize,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn compact_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
summary: &'life2 str,
preserve_count: usize,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Compact a session: summarize old messages while preserving the most recent ones.
Keeps the last preserve_count messages intact, deletes the rest, and
inserts a summary (as a system message) plus a continuation hint
(as an assistant message) before the preserved tail.
Returns the number of messages that were deleted/replaced.
Source§fn has_pending_tool_calls<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn has_pending_tool_calls<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Check if the last message in a session is a tool call awaiting a response. Used to defer compaction during active tool execution.
Source§fn compacted_stats<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<CompactedStats>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn compacted_stats<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Result<CompactedStats>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Stats about compacted (archived) messages across all sessions.
Source§fn purge_compacted<'life0, 'async_trait>(
&'life0 self,
min_age_days: u32,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn purge_compacted<'life0, 'async_trait>(
&'life0 self,
min_age_days: u32,
) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Permanently delete compacted messages older than min_age_days.
Pass 0 to delete all compacted messages regardless of age.
Source§fn get_metadata<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
key: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_metadata<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
key: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Get a session metadata value by key.
Source§fn set_metadata<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
key: &'life2 str,
value: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn set_metadata<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
key: &'life2 str,
value: &'life3 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Set a session metadata value (upsert).
Source§fn get_todo<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_todo<'life0, 'life1, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Option<String>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Get the todo list for a session (convenience wrapper).
Source§fn set_todo<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn set_todo<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
session_id: &'life1 str,
content: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Set the todo list for a session (convenience wrapper).
Auto Trait Implementations§
impl Freeze for Database
impl !RefUnwindSafe for Database
impl Send for Database
impl Sync for Database
impl Unpin for Database
impl UnsafeUnpin for Database
impl !UnwindSafe for Database
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more