Skip to main content

remem/db/
models.rs

1use serde::{Deserialize, Serialize};
2
3pub const OBSERVATION_TYPES: &[&str] = &[
4    "bugfix",
5    "feature",
6    "refactor",
7    "discovery",
8    "decision",
9    "change",
10];
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Observation {
14    pub id: i64,
15    pub memory_session_id: String,
16    pub r#type: String,
17    pub title: Option<String>,
18    pub subtitle: Option<String>,
19    pub narrative: Option<String>,
20    pub facts: Option<String>,
21    pub concepts: Option<String>,
22    pub files_read: Option<String>,
23    pub files_modified: Option<String>,
24    pub discovery_tokens: Option<i64>,
25    pub created_at: String,
26    pub created_at_epoch: i64,
27    pub project: Option<String>,
28    pub status: String,
29    pub last_accessed_epoch: Option<i64>,
30    /// Original Claude Code session ID (for `claude --resume`).
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub content_session_id: Option<String>,
33    /// Git branch name at the time of observation.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub branch: Option<String>,
36    /// Git short commit SHA at the time of observation.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub commit_sha: Option<String>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
42pub struct CompressedObservationSource {
43    pub compressed_observation_id: i64,
44    pub source_observation_id: i64,
45    pub source_hash: String,
46    #[serde(skip_serializing)]
47    pub source_snapshot_json: String,
48    pub source_created_at_epoch: i64,
49    pub compression_session_id: String,
50    pub created_at_epoch: i64,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct SessionSummary {
55    pub id: i64,
56    pub memory_session_id: String,
57    pub request: Option<String>,
58    pub completed: Option<String>,
59    pub decisions: Option<String>,
60    pub learned: Option<String>,
61    pub next_steps: Option<String>,
62    pub preferences: Option<String>,
63    pub created_at: String,
64    pub created_at_epoch: i64,
65    pub project: Option<String>,
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub enum JobType {
70    Observation,
71    Summary,
72    Compress,
73    Dream,
74    CompileRules,
75    Cleanup,
76}
77
78impl JobType {
79    pub fn as_str(self) -> &'static str {
80        match self {
81            Self::Observation => "observation",
82            Self::Summary => "summary",
83            Self::Compress => "compress",
84            Self::Dream => "dream",
85            Self::CompileRules => "compile_rules",
86            Self::Cleanup => "cleanup",
87        }
88    }
89
90    pub fn from_db(raw: &str) -> anyhow::Result<Self> {
91        match raw {
92            "observation" => Ok(Self::Observation),
93            "summary" => Ok(Self::Summary),
94            "compress" => Ok(Self::Compress),
95            "dream" => Ok(Self::Dream),
96            "compile_rules" => Ok(Self::CompileRules),
97            "cleanup" => Ok(Self::Cleanup),
98            _ => anyhow::bail!("unknown job_type: {}", raw),
99        }
100    }
101}
102
103#[derive(Debug, Clone)]
104pub struct Job {
105    pub id: i64,
106    pub host: String,
107    pub job_type: JobType,
108    pub project: String,
109    pub session_id: Option<String>,
110    pub payload_json: String,
111    pub attempt_count: i64,
112    pub max_attempts: i64,
113}
114
115#[derive(Debug, Clone, PartialEq)]
116pub struct AiUsageEvent {
117    pub created_at: String,
118    pub project: Option<String>,
119    pub session_id: Option<String>,
120    pub operation: String,
121    pub executor: String,
122    pub model: Option<String>,
123    pub input_tokens: i64,
124    pub output_tokens: i64,
125    pub reasoning_tokens: i64,
126    pub cache_creation_tokens: i64,
127    pub cache_read_tokens: i64,
128    pub raw_input_tokens: i64,
129    pub raw_output_tokens: i64,
130    pub total_tokens: i64,
131    pub estimated_cost_usd: f64,
132    pub usage_source: String,
133    pub pricing_source: String,
134}
135
136#[derive(Debug, Clone, PartialEq)]
137pub struct DailyAiUsage {
138    pub day: String,
139    pub calls: i64,
140    pub input_tokens: i64,
141    pub output_tokens: i64,
142    pub reasoning_tokens: i64,
143    pub cache_creation_tokens: i64,
144    pub cache_read_tokens: i64,
145    pub total_tokens: i64,
146    pub estimated_cost_usd: f64,
147}
148
149#[derive(Debug, Clone, PartialEq)]
150pub struct WeeklyAiUsage {
151    pub week: String,
152    pub calls: i64,
153    pub input_tokens: i64,
154    pub output_tokens: i64,
155    pub reasoning_tokens: i64,
156    pub cache_creation_tokens: i64,
157    pub cache_read_tokens: i64,
158    pub total_tokens: i64,
159    pub estimated_cost_usd: f64,
160}
161
162#[derive(Debug, Clone, PartialEq)]
163pub struct AiUsageTotals {
164    pub calls: i64,
165    pub input_tokens: i64,
166    pub output_tokens: i64,
167    pub reasoning_tokens: i64,
168    pub cache_creation_tokens: i64,
169    pub cache_read_tokens: i64,
170    pub total_tokens: i64,
171    pub estimated_cost_usd: f64,
172}
173
174#[derive(Debug, Clone, PartialEq)]
175pub struct AiUsageSourceTotals {
176    pub usage_source: String,
177    pub pricing_source: String,
178    pub calls: i64,
179    pub total_tokens: i64,
180    pub estimated_cost_usd: f64,
181}
182
183#[derive(Debug, Clone, PartialEq)]
184pub struct AiUsageBreakdown {
185    pub project: Option<String>,
186    pub executor: String,
187    pub usage_source: String,
188    pub pricing_source: String,
189    pub calls: i64,
190    pub total_tokens: i64,
191    pub estimated_cost_usd: f64,
192}