Skip to main content

kaizen/store/sqlite/
visualization.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3use super::*;
4
5mod activity;
6mod aggregates;
7mod sessions;
8
9#[derive(Clone, Copy, Debug, Default)]
10pub(crate) struct TokenRead {
11    pub(crate) input: u64,
12    pub(crate) output: u64,
13    pub(crate) reasoning: u64,
14    pub(crate) cache_read: u64,
15    pub(crate) cache_create: u64,
16}
17
18#[derive(Clone, Debug, Default)]
19pub(crate) struct ReportTotalsRead {
20    pub(crate) session_count: u64,
21    pub(crate) running_count: u64,
22    pub(crate) event_count: u64,
23    pub(crate) error_count: u64,
24    pub(crate) tool_call_count: u64,
25    pub(crate) cost_usd_e6: i64,
26    pub(crate) tokens: TokenRead,
27    pub(crate) token_event_count: u64,
28    pub(crate) cost_event_count: u64,
29    pub(crate) cost_session_count: u64,
30}
31
32#[derive(Clone, Debug)]
33pub(crate) struct SessionSummaryRead {
34    pub(crate) session: SessionRecord,
35    pub(crate) last_event_ms: Option<u64>,
36    pub(crate) event_count: u64,
37    pub(crate) error_count: u64,
38    pub(crate) tool_call_count: u64,
39    pub(crate) cost_usd_e6: i64,
40    pub(crate) tokens: TokenRead,
41    pub(crate) top_tools: Vec<(String, u64)>,
42}
43
44#[derive(Clone, Copy, Debug)]
45pub(crate) struct ActivityWindow {
46    pub(crate) start_ms: u64,
47    pub(crate) end_ms: u64,
48    pub(crate) width_ms: u64,
49}
50
51#[derive(Clone, Debug, Default)]
52pub(crate) struct ActivityTotalRead {
53    pub(crate) bin: usize,
54    pub(crate) event_count: u64,
55    pub(crate) session_count: u64,
56    pub(crate) token_total: u64,
57    pub(crate) cost_usd_e6: i64,
58}
59
60#[derive(Clone, Debug)]
61pub(crate) struct ActivityCountRead {
62    pub(crate) bin: usize,
63    pub(crate) name: String,
64    pub(crate) count: u64,
65}
66
67#[derive(Clone, Debug, Default)]
68pub(crate) struct ActivityRead {
69    pub(crate) totals: Vec<ActivityTotalRead>,
70    pub(crate) agents: Vec<ActivityCountRead>,
71    pub(crate) kinds: Vec<ActivityCountRead>,
72}
73
74impl Store {
75    pub fn files_for_session(&self, session_id: &str) -> Result<Vec<String>> {
76        self.limited_files_for_session(session_id, usize::MAX)
77    }
78
79    pub(crate) fn limited_files_for_session(
80        &self,
81        session_id: &str,
82        limit: usize,
83    ) -> Result<Vec<String>> {
84        let mut stmt = self.conn.prepare(
85            "SELECT path FROM files_touched
86             WHERE session_id = ?1 ORDER BY path ASC LIMIT ?2",
87        )?;
88        let rows = stmt.query_map(params![session_id, sql_limit(limit)], |row| row.get(0))?;
89        rows.map(|row| row.map_err(Into::into)).collect()
90    }
91}
92
93fn sql_limit(limit: usize) -> i64 {
94    limit.min(i64::MAX as usize) as i64
95}