1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
4#[serde(rename_all = "camelCase")]
5#[serde(default)]
6pub struct StatusSurfaceState {
7 pub kind: String,
8 pub header: String,
9 pub details: Option<String>,
10 pub inline_message: Option<String>,
11 pub interrupt_visible: bool,
12 pub revision: i64,
13}
14
15#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
16#[serde(rename_all = "camelCase")]
17#[serde(default)]
18pub struct RenderPlanStep {
19 pub step: String,
20 pub status: String,
21}
22
23#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
24#[serde(rename_all = "camelCase")]
25#[serde(default)]
26pub struct ExecCommandLine {
27 pub label: String,
28 pub text: String,
29}
30
31#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
32#[serde(rename_all = "camelCase")]
33#[serde(default)]
34pub struct FileChangeLine {
35 pub path: String,
36 pub summary: String,
37 pub diff: Option<String>,
38}
39
40#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
41#[serde(rename_all = "camelCase")]
42#[serde(default)]
43pub struct ThreadRenderSnapshot {
44 pub runtime_id: String,
45 pub thread_id: String,
46 pub revision: i64,
47 pub status_surface: Option<StatusSurfaceState>,
48 #[serde(default)]
49 pub nodes: Vec<ThreadRenderNode>,
50}
51
52#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
53#[serde(rename_all = "camelCase")]
54#[serde(default)]
55pub struct ThreadRenderPatch {
56 pub runtime_id: String,
57 pub thread_id: String,
58 pub snapshot: ThreadRenderSnapshot,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
62#[serde(tag = "type", rename_all = "snake_case")]
63pub enum ThreadRenderNode {
64 UserMessage {
65 id: String,
66 turn_id: Option<String>,
67 item_id: Option<String>,
68 text: String,
69 },
70 AssistantMarkdown {
71 id: String,
72 turn_id: Option<String>,
73 item_id: Option<String>,
74 text: String,
75 phase: Option<String>,
76 streaming: bool,
77 },
78 FinalSeparator {
79 id: String,
80 turn_id: Option<String>,
81 },
82 ReasoningSummary {
83 id: String,
84 turn_id: Option<String>,
85 item_id: Option<String>,
86 title: String,
87 text: String,
88 },
89 PlanUpdate {
90 id: String,
91 turn_id: Option<String>,
92 item_id: Option<String>,
93 title: String,
94 explanation: Option<String>,
95 #[serde(default)]
96 steps: Vec<RenderPlanStep>,
97 streaming: bool,
98 },
99 ProposedPlan {
100 id: String,
101 turn_id: Option<String>,
102 item_id: Option<String>,
103 title: String,
104 text: String,
105 },
106 ExecGroup {
107 id: String,
108 turn_id: Option<String>,
109 item_id: Option<String>,
110 title: String,
111 #[serde(default)]
112 kind: String,
113 state: String,
114 #[serde(default)]
115 commands: Vec<ExecCommandLine>,
116 output_text: Option<String>,
117 exit_code: Option<i64>,
118 },
119 FileChange {
120 id: String,
121 turn_id: Option<String>,
122 item_id: Option<String>,
123 title: String,
124 state: String,
125 #[serde(default)]
126 changes: Vec<FileChangeLine>,
127 },
128 McpToolCall {
129 id: String,
130 turn_id: Option<String>,
131 item_id: Option<String>,
132 title: String,
133 state: String,
134 subtitle: String,
135 detail: Option<String>,
136 },
137 DynamicToolCall {
138 id: String,
139 turn_id: Option<String>,
140 item_id: Option<String>,
141 title: String,
142 state: String,
143 subtitle: String,
144 detail: Option<String>,
145 },
146 WebSearch {
147 id: String,
148 turn_id: Option<String>,
149 item_id: Option<String>,
150 title: String,
151 state: String,
152 detail: Option<String>,
153 },
154 CollabEvent {
155 id: String,
156 turn_id: Option<String>,
157 item_id: Option<String>,
158 title: String,
159 #[serde(default)]
160 detail_lines: Vec<String>,
161 },
162 InfoNotice {
163 id: String,
164 turn_id: Option<String>,
165 item_id: Option<String>,
166 title: String,
167 detail: Option<String>,
168 },
169 ViewImage {
170 id: String,
171 turn_id: Option<String>,
172 item_id: Option<String>,
173 title: String,
174 path: String,
175 },
176 ImageGeneration {
177 id: String,
178 turn_id: Option<String>,
179 item_id: Option<String>,
180 title: String,
181 state: String,
182 prompt: Option<String>,
183 result: String,
184 saved_path: Option<String>,
185 },
186}
187
188impl Default for ThreadRenderNode {
189 fn default() -> Self {
190 Self::InfoNotice {
191 id: String::new(),
192 turn_id: None,
193 item_id: None,
194 title: String::new(),
195 detail: None,
196 }
197 }
198}