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