1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use uuid::Uuid;
4
5#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
6pub enum Role {
7 Assistant,
8 User,
9}
10
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
12pub enum RuntimeMode {
13 Agent,
14 Plan,
15}
16
17#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
18pub enum ToolExecutionTarget {
19 Unspecified,
20 ClientLocal,
22 ServerAgents,
24}
25
26#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
27pub enum ToolCallApproval {
28 Unspecified,
29 Pending,
30 Approved,
31 AutoApproved,
32 Rejected,
33}
34
35#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
36pub struct ModelConfig {
37 #[serde(default, skip_serializing_if = "Option::is_none")]
38 pub temperature: Option<f32>,
39 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub top_p: Option<f32>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub presence_penalty: Option<f32>,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
44 pub frequency_penalty: Option<f32>,
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub max_tokens: Option<i32>,
47 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub reasoning_effort: Option<String>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
52pub struct ThreadModelOverride {
53 pub model_id: Uuid,
54 pub model_config: ModelConfig,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct ToolCallOutput {
59 pub id: String,
61
62 pub is_error: bool,
63 pub output: String,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 pub duration_seconds: Option<i32>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub enum ClientMessage {
70 HelloMath {
71 client_instance_id: String,
75 version: String,
77 min_supported_version: String,
79 },
80 SendMessage {
85 request_id: Uuid,
86 thread_id: Option<Uuid>,
87 text: String,
88 },
89 UpdateAuthToken {
91 token: String,
92 },
93 UpdateWorkspaceRoots {
97 default_root: String,
98 workspace_roots: Vec<String>,
99 },
100 SetRuntimeMode {
102 thread_id: Uuid,
103 mode: RuntimeMode,
104 },
105 SetThreadModel {
107 thread_id: Uuid,
108 #[serde(default, skip_serializing_if = "Option::is_none")]
109 model_override: Option<ThreadModelOverride>,
110 },
111 RejectToolCall {
112 id: String,
113 #[serde(default, skip_serializing_if = "Option::is_none")]
114 reason: Option<String>,
115 },
116 AcceptToolCall {
117 id: String,
118 },
119 ToolCallOutputs {
120 outputs: Vec<ToolCallOutput>,
121 },
122 CancelGeneration {
124 message_id: Uuid,
125 },
126}
127
128#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
129pub struct Usage {
130 pub input_tokens: i32,
131 pub output_tokens: i32,
132 #[serde(default)]
133 pub cache_read_input_tokens: i32,
134 #[serde(default)]
135 pub cache_creation_input_tokens: i32,
136 #[serde(default)]
137 pub cache_creation_input_tokens_5m: i32,
138 #[serde(default)]
139 pub cache_creation_input_tokens_1h: i32,
140}
141
142#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
143pub enum MessageStatus {
144 Completed,
145 WaitingForUser,
148 Failed,
149 Cancelled,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub enum ServerMessage {
154 HelloMagic {
155 version: String,
156 min_supported_version: String,
157 },
158 VersionMismatch {
159 server_version: String,
160 server_min_supported_version: String,
161 },
162 Goodbye {
163 reconnect: bool,
164 },
165 SendMessageAck {
166 request_id: Uuid,
167 thread_id: Uuid,
168 user_message_id: Uuid,
169 },
170 AuthUpdated,
171 RuntimeModeUpdated {
172 thread_id: Uuid,
173 mode: RuntimeMode,
174 #[serde(default, skip_serializing_if = "Option::is_none")]
175 changed_by_client_instance_id: Option<String>,
176 },
177 ThreadModelUpdated {
178 thread_id: Uuid,
179 #[serde(default, skip_serializing_if = "Option::is_none")]
180 model_override: Option<ThreadModelOverride>,
181 #[serde(default, skip_serializing_if = "Option::is_none")]
182 changed_by_client_instance_id: Option<String>,
183 },
184 MessageHeader {
185 message_id: Uuid,
186 thread_id: Uuid,
187 role: Role,
188 #[serde(default, skip_serializing_if = "Option::is_none")]
189 request_id: Option<Uuid>,
190 },
191 ReasoningDelta {
192 message_id: Uuid,
193 content: String,
194 },
195 TextDelta {
196 message_id: Uuid,
197 content: String,
198 },
199 ToolCallHeader {
200 message_id: Uuid,
201 tool_call_id: String,
202 name: String,
203 execution_target: ToolExecutionTarget,
204 approval: ToolCallApproval,
205 },
206 ToolCallArgumentsDelta {
207 message_id: Uuid,
208 tool_call_id: String,
209 delta: String,
210 },
211 ToolCall {
212 message_id: Uuid,
213 tool_call_id: String,
214 args: Value,
215 },
216 ToolCallResult {
217 message_id: Uuid,
218 tool_call_id: String,
219 is_error: bool,
220 output: String,
221 #[serde(default, skip_serializing_if = "Option::is_none")]
222 duration_seconds: Option<i32>,
223 },
224 ToolCallClaimed {
225 message_id: Uuid,
226 tool_call_id: String,
227 claimed_by_client_instance_id: String,
228 },
229 ToolCallApprovalUpdated {
230 message_id: Uuid,
231 tool_call_id: String,
232 approval: ToolCallApproval,
233 },
234 MessageDone {
235 message_id: Uuid,
236 #[serde(default, skip_serializing_if = "Option::is_none")]
237 usage: Option<Usage>,
238 status: MessageStatus,
239 },
240 Error {
241 #[serde(default, skip_serializing_if = "Option::is_none")]
242 request_id: Option<Uuid>,
243 #[serde(default, skip_serializing_if = "Option::is_none")]
244 message_id: Option<Uuid>,
245 code: String,
246 message: String,
247 },
248}