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 #[serde(default)]
15 pub session_page: SessionPageMeta,
16 pub selected: Option<TraceDetail>,
17 pub quality: DataQuality,
18}
19
20#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
21pub struct SessionSearchInput {
22 pub q: String,
23 pub offset: usize,
24}
25
26#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
27pub struct SessionPageMeta {
28 pub filtered_total: usize,
29 pub offset: usize,
30 pub limit: usize,
31 pub next_offset: Option<usize>,
32}
33
34#[derive(Clone, Debug, Default, Serialize, Deserialize)]
35pub struct VisualizationTotals {
36 pub session_count: u64,
37 pub running_count: u64,
38 pub event_count: u64,
39 pub error_count: u64,
40 pub tool_call_count: u64,
41 pub cost_usd_e6: i64,
42 pub tokens: TokenTotals,
43}
44
45#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
46pub struct TokenTotals {
47 pub input: u64,
48 pub output: u64,
49 pub reasoning: u64,
50 pub cache_read: u64,
51 pub cache_create: u64,
52 pub total: u64,
53}
54
55#[derive(Clone, Debug, Default, Serialize, Deserialize)]
56pub struct ActivityReport {
57 pub metric: ActivityMetric,
58 pub day_bins: Vec<ActivityBin>,
59 pub week_bins: Vec<ActivityBin>,
60}
61
62#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
63#[serde(rename_all = "snake_case")]
64pub enum ActivityMetric {
65 #[default]
66 Events,
67 Sessions,
68 Tokens,
69 Cost,
70}
71
72#[derive(Clone, Debug, Default, Serialize, Deserialize)]
73pub struct ActivityBin {
74 pub start_ms: u64,
75 pub end_ms: u64,
76 pub event_count: u64,
77 pub session_count: u64,
78 pub token_total: u64,
79 pub cost_usd_e6: i64,
80 pub active_by_agent: Vec<(String, u64)>,
81 pub dominant_agent: Option<String>,
82 pub dominant_kind: Option<String>,
83 pub heat: f64,
84 pub is_break: bool,
85}
86
87#[derive(Clone, Debug, Serialize, Deserialize)]
88pub struct TraceSummary {
89 pub id: String,
90 pub agent: String,
91 pub model: Option<String>,
92 pub status: DerivedStatus,
93 pub status_reason: String,
94 pub started_at_ms: u64,
95 pub ended_at_ms: Option<u64>,
96 pub last_event_ms: Option<u64>,
97 pub event_count: u64,
98 pub error_count: u64,
99 pub tool_call_count: u64,
100 pub cost_usd_e6: i64,
101 pub tokens: TokenTotals,
102 pub top_tools: Vec<(String, u64)>,
103}
104
105#[derive(Clone, Debug, Serialize, Deserialize)]
106pub struct TraceDetail {
107 pub session: SessionRecord,
108 #[serde(default)]
109 pub prompt: Option<String>,
110 pub events: Vec<Event>,
111 pub spans: Vec<SpanNode>,
112 pub files: Vec<String>,
113}
114
115#[derive(Clone, Debug, Default, Serialize, Deserialize)]
116pub struct DataQuality {
117 pub token_coverage_pct: f64,
118 pub cost_coverage_pct: f64,
119 pub partial_cost_sessions: u64,
120 pub adapter_errors: Vec<String>,
121 pub stale_scan: bool,
122 pub warnings: Vec<String>,
123}
124
125#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
126#[serde(rename_all = "snake_case")]
127pub enum DerivedStatus {
128 Active,
129 WaitingOnTool,
130 Idle,
131 Done,
132 Errored,
133 Orphaned,
134}