feat: phase 2 — coûts par session (stats --costs) + am monitor TUI (closes #49 #50)

This commit is contained in:
2026-08-18 11:23:50 -04:00
parent 63dc36660b
commit 1b3fe09074
22 changed files with 978 additions and 23 deletions
+33 -2
View File
@@ -42,6 +42,10 @@ pub enum EventKind {
Rollback,
/// Derived index pruned (sessions retention, issue #53).
Prune,
/// Session usage recorded: tokens + estimated cost (issue #49).
Cost,
/// Threshold alert from 'am monitor' (issue #50).
Alert,
}
impl EventKind {
@@ -64,6 +68,8 @@ impl EventKind {
EventKind::Backup => "backup",
EventKind::Rollback => "rollback",
EventKind::Prune => "prune",
EventKind::Cost => "cost",
EventKind::Alert => "alert",
}
}
}
@@ -95,6 +101,15 @@ pub struct Event {
pub exit_code: Option<i32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub duration_s: Option<u64>,
/// Input tokens billed for the session (issue #49).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tokens_in: Option<u64>,
/// Output tokens billed for the session (issue #49).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tokens_out: Option<u64>,
/// Estimated cost in USD (issue #49).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cost_usd: Option<f64>,
}
impl Event {
@@ -113,6 +128,9 @@ impl Event {
env_keys: Vec::new(),
exit_code: None,
duration_s: None,
tokens_in: None,
tokens_out: None,
cost_usd: None,
}
}
@@ -161,8 +179,21 @@ impl Event {
self
}
pub fn with_duration(mut self, secs: u64) -> Self {
self.duration_s = Some(secs);
pub fn with_duration(mut self, d: u64) -> Self {
self.duration_s = Some(d);
self
}
/// Record token usage (issue #49).
pub fn with_usage(mut self, tokens_in: u64, tokens_out: u64) -> Self {
self.tokens_in = Some(tokens_in);
self.tokens_out = Some(tokens_out);
self
}
/// Record the estimated cost in USD (issue #49).
pub fn with_cost(mut self, usd: f64) -> Self {
self.cost_usd = Some(usd);
self
}
}