Skip to main content

wire/
message_hosted.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Local projections retained after hosted protocol mapping.
3
4use 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    #[serde(default)]
97    pub tool_name: Option<String>,
98    #[serde(default)]
99    pub detail: Option<String>,
100    #[serde(default)]
101    pub captured_revision: Option<String>,
102    pub recorded_at: String,
103}
104
105#[derive(Debug, Clone, Default, Serialize, Deserialize)]
106pub struct TranscriptAttachmentRef {
107    pub attachment_id: String,
108    #[serde(default)]
109    pub kind: Option<String>,
110    #[serde(default)]
111    pub summary: Option<String>,
112}
113
114#[derive(Debug, Clone, Default, Serialize, Deserialize)]
115pub struct SessionDiffSummary {
116    #[serde(default)]
117    pub changed_file_count: u32,
118    #[serde(default)]
119    pub added_files: u32,
120    #[serde(default)]
121    pub modified_files: u32,
122    #[serde(default)]
123    pub deleted_files: u32,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct WorktreeChangeBaseline {
128    pub path: String,
129    pub kind: String,
130}
131
132#[cfg(test)]
133mod tests {
134    use super::HostedSpoolKind;
135
136    #[test]
137    fn spool_kind_does_not_determine_repository_capability() {
138        let kind = HostedSpoolKind::Spool;
139        let encoded = rmp_serde::to_vec(&kind).expect("encode spool kind");
140        assert_eq!(
141            rmp_serde::from_slice::<HostedSpoolKind>(&encoded).expect("decode spool kind"),
142            kind
143        );
144        for is_repo in [false, true] {
145            let spool = super::HostedSpoolInfo {
146                spool_id: "id".into(),
147                full_path: "spool/alice/notes".into(),
148                kind: "spool".into(),
149                is_repo,
150                display_name: None,
151            };
152            let bytes = rmp_serde::to_vec(&spool).expect("encode spool");
153            let decoded: super::HostedSpoolInfo =
154                rmp_serde::from_slice(&bytes).expect("decode spool");
155            assert_eq!(decoded.is_repo, is_repo);
156            assert_eq!(decoded.kind, "spool");
157        }
158    }
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct SessionReportEnvelope {
163    pub version: u32,
164    pub heddle_session_id: String,
165    #[serde(default)]
166    pub heddle_segment_id: Option<String>,
167    #[serde(default)]
168    pub agent_session_id: Option<String>,
169    #[serde(default)]
170    pub client_instance_id: Option<String>,
171    #[serde(default)]
172    pub native_actor_key: Option<String>,
173    #[serde(default)]
174    pub native_parent_actor_key: Option<String>,
175    #[serde(default)]
176    pub native_instance_key: Option<String>,
177    pub repo_root: String,
178    #[serde(default)]
179    pub thread: Option<String>,
180    #[serde(default)]
181    pub thread_id: Option<String>,
182    #[serde(default)]
183    pub task: Option<String>,
184    #[serde(default)]
185    pub summary: Option<String>,
186    pub opened_at: String,
187    #[serde(default)]
188    pub closed_at: Option<String>,
189    #[serde(default)]
190    pub base_state_at_open: Option<String>,
191    #[serde(default)]
192    pub worktree_changes_at_open: Vec<WorktreeChangeBaseline>,
193    #[serde(default)]
194    pub head_state_at_close: Option<String>,
195    pub transport_mode: String,
196    pub transcript_mode: String,
197    #[serde(default)]
198    pub outcome: Option<String>,
199    #[serde(default)]
200    pub owns_session: bool,
201    pub harness: HarnessIdentity,
202    #[serde(default)]
203    pub progress: Vec<ProgressCheckpoint>,
204    #[serde(default)]
205    pub usage: UsageTotals,
206    #[serde(default)]
207    pub touched_paths: Vec<String>,
208    #[serde(default)]
209    pub changed_paths: Vec<String>,
210    #[serde(default)]
211    pub diff_summary: Option<SessionDiffSummary>,
212    #[serde(default)]
213    pub transcript_refs: Vec<TranscriptAttachmentRef>,
214    #[serde(default)]
215    pub last_progress_at: Option<String>,
216    #[serde(default)]
217    pub report_flush_state: Option<String>,
218    #[serde(default)]
219    pub attach_reason: Option<String>,
220    #[serde(default)]
221    pub attach_precedence: Vec<String>,
222    #[serde(default)]
223    pub winning_attach_rule: Option<String>,
224    #[serde(default)]
225    pub probe_source: Option<String>,
226    #[serde(default)]
227    pub probe_confidence: Option<f32>,
228    #[serde(default)]
229    pub pending_flush: bool,
230    #[serde(default)]
231    pub last_flushed_at: Option<String>,
232}