Skip to main content

Db

Struct Db 

Source
pub struct Db { /* private fields */ }

Implementations§

Source§

impl Db

Source

pub fn open(path: &Path) -> Result<Self>

Source

pub fn default_space_id(&self) -> Result<String>

The default space’s id (always present after migrate).

Source

pub fn create_space(&self, name: &str) -> Result<Space>

Source

pub fn list_spaces(&self) -> Result<Vec<Space>>

Spaces oldest-first (default was inserted first, so it naturally leads).

Source

pub fn rename_space(&self, id: &str, name: &str) -> Result<()>

Source

pub fn delete_space(&self, id: &str) -> Result<()>

Delete a space, reassigning its sessions to default rather than deleting them — only the space’s own memory/instructions are lost. The reassignment bumps every moved session’s version (a mutation, sync-wise); the space itself is tombstoned.

Source

pub fn count_sessions(&self, space_id: &str) -> Result<u64>

Number of sessions currently in a space (shown in the space picker).

Source

pub fn last_message_preview(&self, session_id: &str) -> Option<String>

The most recent user/assistant message of a session — the session picker’s preview strip, so you can see what a session is about before opening it.

Source

pub fn setting_is_local(key: &str) -> bool

Whether an app_settings key is device-local rather than syncable. Local keys describe this device’s capabilities or per-device state (search endpoints, secrets, the OCR stack, ui state); everything else is a user preference that should follow the user. New keys must be classified here — the default is sync, so a forgotten local key would silently sync to other devices.

Source

pub fn set_setting(&self, key: &str, value: &str) -> Result<()>

Source

pub fn load_settings(&self) -> Result<Vec<(String, String)>>

Source

pub fn update_check_due(&self) -> bool

Daily throttle for the startup update check: returns true (and records today as the check date) when no check has run today yet, false when one already has. The check is a courtesy, not a service — one tiny index fetch per day is plenty.

Source

pub fn set_reasoning(&self, model_id: &str, effort: Option<&str>) -> Result<()>

Set (or clear, with None) a model’s reasoning effort.

Source

pub fn toggle_favorite(&self, model_id: &str) -> Result<bool>

Flip a model’s favorite flag; returns the new state.

Source

pub fn mark_model_used(&self, model_id: &str) -> Result<()>

Record a model as just used (for the recents ordering).

Source

pub fn load_model_prefs(&self) -> Result<Vec<ModelPref>>

All stored prefs: (model id, favorite, last used, reasoning effort).

Source

pub fn create_session( &self, title: &str, model: &str, space_id: &str, kind: &str, ) -> Result<Session>

Source

pub fn get_session(&self, id: &str) -> Result<Option<Session>>

A single session by id, or None if it doesn’t exist (e.g. deleted out from under a watch).

Source

pub fn list_sessions(&self, space_id: &str) -> Result<Vec<Session>>

Sessions in space_id, most-recently-updated first.

Source

pub fn latest_session(&self) -> Result<Option<(String, Session)>>

Return the most recently updated session across all spaces, together with its owning space id. Used by the nexus --continue launcher.

Source

pub fn set_compaction( &self, session_id: &str, summary: &str, through: i64, ) -> Result<()>

Store an auto-compaction result: the digest plus how many raw messages it now covers.

Source

pub fn set_session_web_mode(&self, session_id: &str, on: bool) -> Result<()>

Persist a session’s /web answer-mode toggle.

Source

pub fn set_session_swarm_mode(&self, session_id: &str, on: bool) -> Result<()>

Persist a session’s /swarm mode toggle.

Source

pub fn list_swarm_personas(&self, session_id: &str) -> Result<Vec<Persona>>

A session’s /swarm roster, in display order.

Source

pub fn save_swarm_personas( &self, session_id: &str, personas: &[Persona], ) -> Result<()>

Replace a session’s whole /swarm roster with personas, in order. The roster has no per-row LWW — saving is DELETE-all + INSERT — so the collection is versioned by bumping the owning session, and each removed slot is tombstoned for the merge engine.

Source

pub fn set_research_parent(&self, id: &str, parent_id: &str) -> Result<()>

Set a session’s research_parent_id after creation (e.g. when a regular chat is promoted to research and the original session is created first).

Source

pub fn set_session_title( &self, id: &str, title: &str, slug: Option<&str>, ) -> Result<()>

Set a session’s title and (optionally) its generated slug.

Source

pub fn delete_message(&self, id: &str) -> Result<()>

Delete a single message row by id — used to roll back a persisted gate_reply whose channel delivery failed, so a retry can’t duplicate it in the transcript. Tombstoned for sync.

Source

pub fn delete_session(&self, id: &str) -> Result<()>

Delete a session and all its messages and swarm personas. Every removed row is tombstoned — append-only children and roster slots must not survive as orphaned durable state on this device.

Source

pub fn load_messages(&self, session_id: &str) -> Result<Vec<Message>>

Source

pub fn add_user_message( &self, session_id: &str, content: &str, ) -> Result<String>

Insert a user message (no model/reasoning/stats). Returns its id.

Source

pub fn add_gate_reply_message( &self, session_id: &str, content: &str, ) -> Result<String>

A user’s reply to a survey/approval gate: rendered in the transcript like a user message but never replayed to the model (gate_reply role) — the survey/plan rows it answers are excluded from model history too, so bare answers (“the second option”, “drop Q2”) must not reach the model without their context.

Source

pub fn add_tool_call_message( &self, session_id: &str, content: &str, ) -> Result<String>

Insert a tool-call transcript block: content is JSON containing the provider call id, optional reasoning/content, name, arguments, and result. It is never sent back to the model verbatim; App::build_history rebuilds the assistant/tool wire messages.

Source

pub fn add_error_message( &self, session_id: &str, content: &str, ) -> Result<String>

Insert a failed-response line. It remains visible in the transcript after the status bar changes, but is never replayed to the model.

Source

pub fn add_research_stage_message( &self, session_id: &str, content: &str, ) -> Result<String>

Insert a background-research stage/progress line: plain text, shown in the transcript but never sent back to the model (unlike tool_call rows, never replayed into build_history either — this is the job’s own scratch work, not something the chat model did).

Source

pub fn add_research_plan_message( &self, session_id: &str, content: &str, ) -> Result<String>

A research pipeline’s plan-approval prompt: rendered like a stage row but actionable, and (like research_stage) never replayed to the model.

Source

pub fn add_survey_message( &self, session_id: &str, content: &str, ) -> Result<String>

A research pipeline’s clarifying-survey section: the scoping agent’s questions awaiting a chat answer. Rendered like a stage row but actionable, and never replayed to the model.

Source

pub fn upsert_research_stage_message( &self, session_id: &str, label: &str, detail: &str, ) -> Result<()>

Update the most recent research_stage row for session_id whose content starts with label, or insert one on the stage’s first occurrence — keeps one transcript row per named stage instead of appending on every progress tick (e.g. every searcher finishing).

Source

pub fn set_source_flag( &self, session_id: &str, url_norm: &str, flag: Option<&str>, ) -> Result<()>

Pin (Some("pinned")), discard (Some("discarded")), or clear (None) a session source’s flag. url_norm must already exist in session_sources for this session (a no-op UPDATE otherwise — the row is created by add_session_sources when a source is first cited, not here). Bumps the row’s version — flag changes sync.

Source

pub fn add_assistant_message( &self, session_id: &str, content: &str, model: Option<&str>, reasoning: Option<&str>, tokens: Option<i64>, secs: Option<f64>, cost: Option<f64>, phrase: Option<&str>, ) -> Result<String>

Insert an assistant reply with its model, reasoning trace, and stats. cost is the provider-reported USD total or a cache-aware catalog estimate (None when neither is available). Args mirror the messages table columns; ~25 call sites pass inline Nones for unused fields, so a struct would churn all of them.

Source

pub fn add_persona_message( &self, session_id: &str, content: &str, persona_name: &str, model: &str, ) -> Result<String>

Insert a /swarm persona’s round reply: an assistant message tagged with which persona (and its own model) produced it.

Source

pub fn message_created_at( &self, session_id: &str, index: usize, ) -> Result<Option<String>>

created_at of the message at index (0-based, transcript order) — used to anchor a compaction row at the boundary without loading the whole session (e.g. when the job finishes after the user switched sessions). None when the session has fewer than index + 1 messages.

Source

pub fn add_compaction_message( &self, session_id: &str, content: &str, at: &str, ) -> Result<String>

Insert a compaction-digest row at the exact created_at position — the timestamp of the last message the digest covers, so reloads keep the digest at the compaction boundary (right after the raw messages it summarizes) instead of at the end of the transcript. Unlike insert_message, this does not bump the session’s updated_at: compacting is bookkeeping, not new activity.

Source

pub fn update_compaction_message( &self, session_id: &str, content: &str, ) -> Result<usize>

Replace the session’s compaction row’s content in place — a later compaction folds new messages into the same digest, so there is exactly one row per session. Returns the number of rows updated (0 = the session has no compaction row yet).

Source

pub fn set_session_model(&self, session_id: &str, model: &str) -> Result<()>

Source

pub fn upsert_file( &self, space_id: &str, name: &str, hash: &str, size: i64, status: &str, ) -> Result<String>

Insert or replace a file row (unique per space+name). Returns the row id; an existing row keeps its id, so its chunks can be replaced by file_id. The durable files row keeps only identity + content stats; status is this device’s derived index state and lives in cache.file_index_state (a cold cache shows “not indexed” until the next rescan re-derives it).

Source

pub fn list_files(&self, space_id: &str) -> Result<Vec<FileRow>>

Source

pub fn file_indexed(&self, file_id: &str) -> Result<bool>

Whether a file has a file_index_state row — i.e. this device has derived index state for it. A missing row means a cold cache (fresh restore, deleted cache.db): the rescan must re-extract rather than trust the stat skip.

Source

pub fn file_has_chunks(&self, file_id: &str) -> Result<bool>

Whether a file has extracted/indexable chunks on this device. This is separate from file_indexed: older cache versions could have a status row without ever writing chunks.

Source

pub fn delete_file(&self, file_id: &str) -> Result<()>

Source

pub fn set_file_mtime(&self, file_id: &str, mtime: i64) -> Result<()>

Record the disk mtime a file was indexed at (see FileRow::mtime), in cache.file_index_state. A missing row (cold cache) is created with the current status.

Source

pub fn set_file_status(&self, file_id: &str, status: &str) -> Result<()>

Update a file’s derived status (e.g. “ok”, “ocr…”, or an error message) in cache.file_index_state. A missing row (cold cache) is created with the current mtime.

Source

pub fn rename_file(&self, file_id: &str, new_name: &str) -> Result<()>

Source

pub fn replace_file_ref_in_messages( &self, space_id: &str, old_name: &str, new_name: &str, ) -> Result<()>

Replace all occurrences of old_name with new_name in message content within the given space. Used when OCR renames a pasted image to a descriptive filename — updates ![alt](old_name)![alt](new_name).

Source

pub fn set_file_chunks( &self, file_id: &str, chunks: &[(String, String)], ) -> Result<()>

Replace a file’s indexed chunks. chunks are (location, text) in order. Any stored embeddings are dropped too — they described the old chunk texts, and the embedder backfills the new ones. All of this is device-local derived state in cache.db.

Source

pub fn integrity_check(&self) -> Result<String>

PRAGMA integrity_check — the db’s own self-test. Returns "ok" when the file is sound, or a list of problems otherwise. Used by nexus doctor.

Source

pub fn file_chunk_texts(&self, file_id: &str) -> Result<Vec<(i64, String)>>

A file’s chunk texts as (seq, text), in order — the embedder’s input.

Source

pub fn files_missing_embeddings(&self, space_id: &str) -> Result<Vec<String>>

See the free function of the same name.

Source

pub fn add_citations( &self, space_id: &str, report_file: &str, citations: &[(String, Option<String>)], ) -> Result<()>

Record a research report’s cited sources for the citation index. Each row gets a UUID sync_id — the AUTOINCREMENT id is only a device-local cursor.

Source

pub fn search_citations( &self, space_id: &str, query: Option<&str>, ) -> Result<Vec<(String, String, String)>>

See the free function of the same name. Most production code reads citations through the toolbox’s own connection (the free function), but this handle is also used directly by the watch diff-section lookup (previous_citations_for_watch_session), plus tests.

Source

pub fn set_chunk_embeddings( &self, file_id: &str, vecs: &[(i64, Vec<f32>)], ) -> Result<()>

Store embedding vectors for a file’s chunks as (seq, vector) pairs.

Source

pub fn clear_chunk_embeddings(&self) -> Result<()>

Drop all device-local vectors. Embeddings are model-specific; this is used when the configured embedding model changes so semantic search does not silently rank chunks with vectors from the old model.

Source

pub fn create_watch( &self, space_id: &str, topic: &str, interval_hours: i64, session_id: &str, ) -> Result<String>

Source

pub fn list_watches(&self, space_id: &str) -> Result<Vec<Watch>>

Source

pub fn list_all_watches(&self) -> Result<Vec<Watch>>

Every watch across all spaces — used by the startup due-check, which runs before any space is necessarily “active”.

Source

pub fn touch_watch(&self, id: &str, now_rfc3339: &str) -> Result<()>

Source

pub fn set_watch_session(&self, id: &str, session_id: &str) -> Result<()>

Repoint a watch at the session its most recent re-run actually used, so the next due-check’s diff-section lookup (previous_citations_for_watch_session) can match against it.

Source

pub fn delete_watch(&self, id: &str) -> Result<()>

Source§

impl Db

Source

pub fn log_usage( &self, backend: &str, model: &str, prompt_tokens: u64, completion_tokens: u64, cache_read_tokens: u64, cache_creation_tokens: u64, cost: Option<f64>, cost_is_provider: bool, session_id: Option<&str>, space_id: Option<&str>, ) -> Result<i64>

Record one completed API request’s usage. Content-free — only backend/model/tokens — so it never leaks conversation text.

Source

pub fn update_usage( &self, row_id: i64, prompt_tokens: u64, completion_tokens: u64, cache_read_tokens: u64, cache_creation_tokens: u64, cost: Option<f64>, cost_is_provider: bool, ) -> Result<()>

Update a usage row written earlier in the same request’s lifecycle. OpenCode Zen splits accounting across two streamed events (real usage, then the provider-reported cost); the second event updates the row the first created instead of inserting a duplicate.

Source

pub fn request_cost( &self, model: &str, prompt_tokens: u64, completion_tokens: u64, cache_read_tokens: u64, cache_creation_tokens: u64, ) -> Option<f64>

Estimated cost of one completed request in USD at current catalog prices (None when no price is known). Cache reads and writes use the catalog’s separate rates when present. Non-OpenRouter models fall back to the matching OpenRouter catalog entry (see model_price).

Source

pub fn backfill_usage_costs(&mut self) -> Result<usize>

Reconcile estimated request costs with the current model_prices catalog. Rows logged before pricing existed are filled, and stale estimates (legacy unit bug, price changes, or ignored cache discounts) are recomputed. Provider-reported costs are exact and never overwritten. Non-OpenRouter models are priced through their OpenRouter vendor/name twin, like model_price. Existing costs for models with no current catalog entry are left untouched.

Idempotent — unchanged rows are not rewritten — so it can run after every catalog refresh and whenever the /usage popup opens. Returns how many rows were visited.

Source

pub fn upsert_model_prices( &mut self, prices: &[(String, String, ModelPricing)], ) -> Result<()>

Batch save/refresh catalog prices in one transaction. The OpenRouter catalog is hundreds of models; per-row autocommits (each an fsync on the UI task) made the post-load pause noticeable. The WHERE clause also skips rows whose price didn’t move, so re-fetches write nothing.

Source

pub fn model_price(&self, model: &str) -> Option<ModelPricing>

Catalog prices for a model in USD per 1M tokens. Tries the exact model_prices row first (OpenRouter ids match directly); if there is none, falls back to the OpenRouter catalog entry for the same model — backend prefixes and the catalog’s vendor/ part are stripped. Other backends expose no pricing, so the matching OpenRouter list price is the best available estimate.

Source

pub fn usage_totals(&self, since: Option<&str>) -> Result<UsageTotals>

Totals across logged requests, optionally limited to requests logged at or after since (RFC3339; None = all time). created_at is stored as fixed-width UTC RFC3339, so lexicographic comparison is a correct time filter.

Source

pub fn usage_by_backend( &self, since: Option<&str>, ) -> Result<Vec<UsageByBackend>>

Per-backend aggregates, most-used first. since filters the window (RFC3339 cutoff; None = all time).

Source

pub fn usage_by_model( &self, limit: u64, since: Option<&str>, ) -> Result<Vec<UsageByModel>>

Per-model aggregates, most-used first. since filters the window (RFC3339 cutoff; None = all time).

Source

pub fn usage_recent( &self, limit: u64, since: Option<&str>, ) -> Result<Vec<UsageRow>>

The most recent logged requests, newest first. since filters the window (RFC3339 cutoff; None = all time).

Source

pub fn usage_by_day( &self, limit: u64, since: Option<&str>, ) -> Result<Vec<UsageDay>>

Per-day aggregates (created_at is RFC 3339, so its first 10 chars are the date), newest day first — the CLI’s usage --by-day.

Source§

impl Db

Sync identity + cursor bookkeeping for the Phase 3 merge engine.

Source

pub fn device_id(&self) -> Result<String>

This device’s stable id, created on first use. Sync identity for everything this device writes (tombstones, LWW tie-breaks on updated_at + device_id in Phase 3).

Source

pub fn set_sync_state( &self, peer_id: &str, table_name: &str, pull_cursor: Option<&str>, push_cursor: Option<&str>, ) -> Result<()>

Store (or update) a peer’s cursors for one table, stamping last_synced_at. None leaves an existing cursor untouched.

Source

pub fn load_sync_state(&self) -> Result<Vec<SyncState>>

Auto Trait Implementations§

§

impl !Freeze for Db

§

impl !RefUnwindSafe for Db

§

impl !Sync for Db

§

impl !UnwindSafe for Db

§

impl Send for Db

§

impl Unpin for Db

§

impl UnsafeUnpin for Db

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more