1use crate::core::event::{Event, SessionRecord};
4use crate::store::SpanNode;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, Default, Serialize, Deserialize)]
8pub struct VisualizationReport {
9 pub generated_at_ms: u64,
10 pub workspace: String,
11 pub totals: VisualizationTotals,
12 pub activity: ActivityReport,
13 pub sessions: Vec<TraceSummary>,
14 pub selected: Option<TraceDetail>,
15 pub quality: DataQuality,
16}
17
18#[derive(Clone, Debug, Default, Serialize, Deserialize)]
19pub struct VisualizationTotals {
20 pub session_count: u64,
21 pub running_count: u64,
22 pub event_count: u64,
23 pub error_count: u64,
24 pub tool_call_count: u64,
25 pub cost_usd_e6: i64,
26 pub tokens: TokenTotals,
27}
28
29#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
30pub struct TokenTotals {
31 pub input: u64,
32 pub output: u64,
33 pub reasoning: u64,
34 pub cache_read: u64,
35 pub cache_create: u64,
36 pub total: u64,
37}
38
39#[derive(Clone, Debug, Default, Serialize, Deserialize)]
40pub struct ActivityReport {
41 pub metric: ActivityMetric,
42 pub day_bins: Vec<ActivityBin>,
43 pub week_bins: Vec<ActivityBin>,
44}
45
46#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
47#[serde(rename_all = "snake_case")]
48pub enum ActivityMetric {
49 #[default]
50 Events,
51 Sessions,
52 Tokens,
53 Cost,
54}
55
56#[derive(Clone, Debug, Default, Serialize, Deserialize)]
57pub struct ActivityBin {
58 pub start_ms: u64,
59 pub end_ms: u64,
60 pub event_count: u64,
61 pub session_count: u64,
62 pub token_total: u64,
63 pub cost_usd_e6: i64,
64 pub active_by_agent: Vec<(String, u64)>,
65 pub dominant_agent: Option<String>,
66 pub dominant_kind: Option<String>,
67 pub heat: f64,
68 pub is_break: bool,
69}
70
71#[derive(Clone, Debug, Serialize, Deserialize)]
72pub struct TraceSummary {
73 pub id: String,
74 pub agent: String,
75 pub model: Option<String>,
76 pub status: DerivedStatus,
77 pub status_reason: String,
78 pub started_at_ms: u64,
79 pub ended_at_ms: Option<u64>,
80 pub last_event_ms: Option<u64>,
81 pub event_count: u64,
82 pub error_count: u64,
83 pub tool_call_count: u64,
84 pub cost_usd_e6: i64,
85 pub tokens: TokenTotals,
86 pub top_tools: Vec<(String, u64)>,
87}
88
89#[derive(Clone, Debug, Serialize, Deserialize)]
90pub struct TraceDetail {
91 pub session: SessionRecord,
92 #[serde(default)]
93 pub prompt: Option<String>,
94 pub events: Vec<Event>,
95 pub spans: Vec<SpanNode>,
96 pub files: Vec<String>,
97}
98
99#[derive(Clone, Debug, Default, Serialize, Deserialize)]
100pub struct DataQuality {
101 pub token_coverage_pct: f64,
102 pub cost_coverage_pct: f64,
103 pub partial_cost_sessions: u64,
104 pub adapter_errors: Vec<String>,
105 pub stale_scan: bool,
106 pub warnings: Vec<String>,
107}
108
109#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
110#[serde(rename_all = "snake_case")]
111pub enum DerivedStatus {
112 Active,
113 WaitingOnTool,
114 Idle,
115 Done,
116 Errored,
117 Orphaned,
118}