Skip to main content

codex_state/
audit.rs

1//! Read-only state database queries for diagnostics.
2
3use anyhow::Result;
4use codex_utils_absolute_path::AbsolutePathBuf;
5use sqlx::Row;
6use std::path::Path;
7use std::path::PathBuf;
8
9/// Minimal thread metadata used by read-only state database audits.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct ThreadStateAuditRow {
12    pub id: String,
13    pub rollout_path: PathBuf,
14    pub archived: bool,
15    pub source: String,
16    pub model_provider: String,
17}
18
19/// Read persisted thread rows from a state DB without creating, migrating, or repairing it.
20pub async fn read_thread_state_audit_rows(path: &Path) -> Result<Vec<ThreadStateAuditRow>> {
21    let sqlite = crate::SqliteConfig::from_sqlite_home(AbsolutePathBuf::try_from(
22        path.parent().unwrap_or(path),
23    )?);
24    let pool = sqlite.open_read_only_pool(path).await?;
25    let rows = sqlx::query(
26        r#"
27SELECT id, rollout_path, archived, source, model_provider
28FROM threads
29        "#,
30    )
31    .fetch_all(&pool)
32    .await?;
33    pool.close().await;
34
35    rows.into_iter()
36        .map(|row| {
37            let archived: i64 = row.try_get("archived")?;
38            Ok(ThreadStateAuditRow {
39                id: row.try_get("id")?,
40                rollout_path: PathBuf::from(row.try_get::<String, _>("rollout_path")?),
41                archived: archived != 0,
42                source: row.try_get("source")?,
43                model_provider: row.try_get("model_provider")?,
44            })
45        })
46        .collect()
47}