Skip to main content

toolhub_core/
usage.rs

1//! Usage tracking domain types — Phase 4.
2//!
3//! `UsageEvent` rows are produced by replaying Claude Code session JSONL
4//! (`crates/ingestion/src/session_jsonl.rs`) and persisted by
5//! `crates/storage/src/usage.rs`. `Outcome` is the heuristic verdict assigned
6//! per tool invocation; it serialises to lowercase to match the `outcome`
7//! TEXT column on `usage_events`.
8
9use chrono::{DateTime, Utc};
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "lowercase")]
14pub enum Outcome {
15    Success,
16    Failure,
17    Abandoned,
18    Unknown,
19}
20
21impl Outcome {
22    pub fn as_str(self) -> &'static str {
23        match self {
24            Outcome::Success => "success",
25            Outcome::Failure => "failure",
26            Outcome::Abandoned => "abandoned",
27            Outcome::Unknown => "unknown",
28        }
29    }
30
31    pub fn parse(s: &str) -> Option<Self> {
32        Some(match s {
33            "success" => Outcome::Success,
34            "failure" => Outcome::Failure,
35            "abandoned" => Outcome::Abandoned,
36            "unknown" => Outcome::Unknown,
37            _ => return None,
38        })
39    }
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct UsageEvent {
44    /// Mirrors assistant `tool_use.id` from JSONL. UNIQUE — drives idempotent replay.
45    pub uuid: Option<String>,
46    pub tool_id: String,
47    pub session_id: Option<String>,
48    pub project: Option<String>,
49    pub task_text: Option<String>,
50    pub outcome: Outcome,
51    pub duration_ms: Option<i64>,
52    pub cost_usd: Option<f64>,
53    pub occurred_at: DateTime<Utc>,
54}