1use std::path::PathBuf;
5
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum HostedSpoolKind {
11 Org,
12 Project,
13}
14
15impl HostedSpoolKind {
16 pub fn is_repo(self) -> bool {
18 matches!(self, Self::Project)
19 }
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct HostedSpoolInfo {
24 pub spool_id: String,
25 pub full_path: String,
26 pub kind: String,
27 pub is_repo: bool,
28 pub display_name: Option<String>,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct HostedNamespaceInfo {
33 pub namespace_id: String,
34 pub kind: String,
35 pub slug: String,
36 pub parent_id: Option<String>,
37 pub display_name: Option<String>,
38 pub full_path: String,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct HostedRepositoryInfo {
43 pub repo_id: String,
44 pub namespace_id: String,
45 pub slug: String,
46 pub path: PathBuf,
47 pub full_path: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct HostedGrantInfo {
52 pub subject: String,
53 pub role: String,
54 #[serde(default)]
55 pub namespace_path: Option<String>,
56 #[serde(default)]
57 pub repo_path: Option<String>,
58}
59
60#[derive(Debug, Clone, Default, Serialize, Deserialize)]
61pub struct HarnessIdentity {
62 #[serde(default)]
63 pub harness: Option<String>,
64 #[serde(default)]
65 pub provider: Option<String>,
66 #[serde(default)]
67 pub model: Option<String>,
68 #[serde(default)]
69 pub thinking_level: Option<String>,
70 #[serde(default)]
71 pub policy: Option<String>,
72}
73
74#[derive(Debug, Clone, Default, Serialize, Deserialize)]
75pub struct UsageTotals {
76 #[serde(default)]
77 pub input_tokens: Option<u64>,
78 #[serde(default)]
79 pub output_tokens: Option<u64>,
80 #[serde(default)]
81 pub reasoning_tokens: Option<u64>,
82 #[serde(default)]
83 pub cache_creation_tokens: Option<u64>,
84 #[serde(default)]
85 pub cache_read_tokens: Option<u64>,
86 #[serde(default)]
87 pub tool_calls: Option<u32>,
88 #[serde(default)]
89 pub cost_micros_usd: Option<u64>,
90}
91
92#[derive(Debug, Clone, Default, Serialize, Deserialize)]
93pub struct ProgressCheckpoint {
94 #[serde(default)]
95 pub status: Option<String>,
96 #[serde(default)]
97 pub message: Option<String>,
98 #[serde(default)]
99 pub completed_steps: Option<u32>,
100 #[serde(default)]
101 pub total_steps: Option<u32>,
102 #[serde(default)]
103 pub touched_paths: Vec<String>,
104 pub recorded_at: String,
105}
106
107#[derive(Debug, Clone, Default, Serialize, Deserialize)]
108pub struct TranscriptAttachmentRef {
109 pub attachment_id: String,
110 #[serde(default)]
111 pub kind: Option<String>,
112 #[serde(default)]
113 pub summary: Option<String>,
114}
115
116#[derive(Debug, Clone, Default, Serialize, Deserialize)]
117pub struct SessionDiffSummary {
118 #[serde(default)]
119 pub changed_file_count: u32,
120 #[serde(default)]
121 pub added_files: u32,
122 #[serde(default)]
123 pub modified_files: u32,
124 #[serde(default)]
125 pub deleted_files: u32,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct WorktreeChangeBaseline {
130 pub path: String,
131 pub kind: String,
132}
133
134#[cfg(test)]
135mod tests {
136 use super::HostedSpoolKind;
137
138 #[test]
139 fn hosted_spool_kinds_map_org_and_project_capabilities() {
140 assert!(!HostedSpoolKind::Org.is_repo());
141 assert!(HostedSpoolKind::Project.is_repo());
142 }
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct SessionReportEnvelope {
147 pub version: u32,
148 pub heddle_session_id: String,
149 #[serde(default)]
150 pub heddle_segment_id: Option<String>,
151 #[serde(default)]
152 pub agent_session_id: Option<String>,
153 #[serde(default)]
154 pub client_instance_id: Option<String>,
155 #[serde(default)]
156 pub native_actor_key: Option<String>,
157 #[serde(default)]
158 pub native_parent_actor_key: Option<String>,
159 #[serde(default)]
160 pub native_instance_key: Option<String>,
161 pub repo_root: String,
162 #[serde(default)]
163 pub thread: Option<String>,
164 #[serde(default)]
165 pub thread_id: Option<String>,
166 #[serde(default)]
167 pub task: Option<String>,
168 #[serde(default)]
169 pub summary: Option<String>,
170 pub opened_at: String,
171 #[serde(default)]
172 pub closed_at: Option<String>,
173 #[serde(default)]
174 pub base_state_at_open: Option<String>,
175 #[serde(default)]
176 pub worktree_changes_at_open: Vec<WorktreeChangeBaseline>,
177 #[serde(default)]
178 pub head_state_at_close: Option<String>,
179 pub transport_mode: String,
180 pub transcript_mode: String,
181 #[serde(default)]
182 pub outcome: Option<String>,
183 #[serde(default)]
184 pub owns_session: bool,
185 pub harness: HarnessIdentity,
186 #[serde(default)]
187 pub progress: Vec<ProgressCheckpoint>,
188 #[serde(default)]
189 pub usage: UsageTotals,
190 #[serde(default)]
191 pub touched_paths: Vec<String>,
192 #[serde(default)]
193 pub changed_paths: Vec<String>,
194 #[serde(default)]
195 pub diff_summary: Option<SessionDiffSummary>,
196 #[serde(default)]
197 pub transcript_refs: Vec<TranscriptAttachmentRef>,
198 #[serde(default)]
199 pub last_progress_at: Option<String>,
200 #[serde(default)]
201 pub report_flush_state: Option<String>,
202 #[serde(default)]
203 pub attach_reason: Option<String>,
204 #[serde(default)]
205 pub attach_precedence: Vec<String>,
206 #[serde(default)]
207 pub winning_attach_rule: Option<String>,
208 #[serde(default)]
209 pub probe_source: Option<String>,
210 #[serde(default)]
211 pub probe_confidence: Option<f32>,
212 #[serde(default)]
213 pub pending_flush: bool,
214 #[serde(default)]
215 pub last_flushed_at: Option<String>,
216}