1use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct SessionNewParams {
13 pub cwd: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub mcp_servers: Option<Vec<Value>>,
16 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
17 pub meta: Option<Value>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct SessionLoadParams {
24 pub cwd: String,
25 pub session_id: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub mcp_servers: Option<Vec<Value>>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct SessionResult {
34 pub session_id: String,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub modes: Option<ModesInfo>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub models: Option<ModelsInfo>,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct ModesInfo {
45 pub available_modes: Vec<ModeEntry>,
46 pub current_mode_id: String,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct ModeEntry {
53 pub id: String,
54 pub name: String,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub description: Option<String>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct ModelsInfo {
63 pub available_models: Vec<ModelEntry>,
64 pub current_model_id: String,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(rename_all = "camelCase")]
70pub struct ModelEntry {
71 pub model_id: String,
72 pub name: String,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub description: Option<String>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79#[serde(rename_all = "camelCase")]
80pub struct SessionPromptParams {
81 pub session_id: String,
82 pub prompt: Vec<super::content::ContentBlock>,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct SessionPromptResult {
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub stop_reason: Option<String>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct SessionUpdateParams {
97 pub session_id: String,
98 pub update: Value,
99}
100
101#[derive(Debug, Clone)]
104pub enum SessionUpdate {
105 AgentMessageChunk { text: String },
107 AgentThoughtChunk { text: String },
109 UserMessageChunk { text: String },
111 ToolCall(ToolCallInfo),
113 ToolCallUpdate(ToolCallUpdateInfo),
115 Plan(PlanInfo),
117 AvailableCommandsUpdate(Vec<AgentCommand>),
119 CurrentModeUpdate { mode_id: String },
121 Unknown(Value),
123}
124
125impl SessionUpdate {
126 pub fn from_value(value: &Value) -> Self {
131 let update_type = value
132 .get("sessionUpdate")
133 .and_then(|v| v.as_str())
134 .unwrap_or("");
135
136 match update_type {
137 "agent_message_chunk" => {
138 let text = value
139 .get("content")
140 .and_then(|c| c.get("text"))
141 .and_then(|t| t.as_str())
142 .unwrap_or("")
143 .to_string();
144 Self::AgentMessageChunk { text }
145 }
146 "agent_thought_chunk" => {
147 let text = value
148 .get("content")
149 .and_then(|c| c.get("text"))
150 .and_then(|t| t.as_str())
151 .unwrap_or("")
152 .to_string();
153 Self::AgentThoughtChunk { text }
154 }
155 "user_message_chunk" => {
156 let text = value
157 .get("content")
158 .and_then(|c| c.get("text"))
159 .and_then(|t| t.as_str())
160 .unwrap_or("")
161 .to_string();
162 Self::UserMessageChunk { text }
163 }
164 "tool_call" => {
165 let tool_call_id = value
166 .get("toolCallId")
167 .and_then(|v| v.as_str())
168 .unwrap_or("")
169 .to_string();
170 let title = value
171 .get("title")
172 .and_then(|v| v.as_str())
173 .unwrap_or("")
174 .to_string();
175 let kind = value
176 .get("kind")
177 .and_then(|v| v.as_str())
178 .unwrap_or("")
179 .to_string();
180 let status = value
181 .get("status")
182 .and_then(|v| v.as_str())
183 .unwrap_or("")
184 .to_string();
185 let content = value.get("content").cloned();
186 Self::ToolCall(ToolCallInfo {
187 tool_call_id,
188 title,
189 kind,
190 status,
191 content,
192 })
193 }
194 "tool_call_update" => {
195 let tool_call_id = value
196 .get("toolCallId")
197 .and_then(|v| v.as_str())
198 .unwrap_or("")
199 .to_string();
200 let status = value
201 .get("status")
202 .and_then(|v| v.as_str())
203 .map(String::from);
204 let title = value
205 .get("title")
206 .and_then(|v| v.as_str())
207 .map(String::from);
208 let content = value.get("content").cloned();
209 Self::ToolCallUpdate(ToolCallUpdateInfo {
210 tool_call_id,
211 status,
212 title,
213 content,
214 })
215 }
216 "plan" => {
217 let entries = value
218 .get("entries")
219 .and_then(|v| v.as_array())
220 .map(|arr| {
221 arr.iter()
222 .map(|entry| PlanEntry {
223 content: entry
224 .get("content")
225 .and_then(|v| v.as_str())
226 .unwrap_or("")
227 .to_string(),
228 status: entry
229 .get("status")
230 .and_then(|v| v.as_str())
231 .unwrap_or("")
232 .to_string(),
233 })
234 .collect()
235 })
236 .unwrap_or_default();
237 Self::Plan(PlanInfo { entries })
238 }
239 "available_commands_update" => {
240 let commands = value
241 .get("commands")
242 .and_then(|v| v.as_array())
243 .map(|arr| {
244 arr.iter()
245 .map(|cmd| AgentCommand {
246 name: cmd
247 .get("name")
248 .and_then(|v| v.as_str())
249 .unwrap_or("")
250 .to_string(),
251 description: cmd
252 .get("description")
253 .and_then(|v| v.as_str())
254 .map(String::from),
255 })
256 .collect()
257 })
258 .unwrap_or_default();
259 Self::AvailableCommandsUpdate(commands)
260 }
261 "current_mode_update" => {
262 let mode_id = value
263 .get("modeId")
264 .and_then(|v| v.as_str())
265 .unwrap_or("")
266 .to_string();
267 Self::CurrentModeUpdate { mode_id }
268 }
269 _ => Self::Unknown(value.clone()),
270 }
271 }
272}
273
274#[derive(Debug, Clone)]
276pub struct ToolCallInfo {
277 pub tool_call_id: String,
278 pub title: String,
279 pub kind: String,
280 pub status: String,
281 pub content: Option<Value>,
282}
283
284#[derive(Debug, Clone)]
286pub struct ToolCallUpdateInfo {
287 pub tool_call_id: String,
288 pub status: Option<String>,
289 pub title: Option<String>,
290 pub content: Option<Value>,
291}
292
293#[derive(Debug, Clone)]
295pub struct PlanInfo {
296 pub entries: Vec<PlanEntry>,
297}
298
299#[derive(Debug, Clone)]
301pub struct PlanEntry {
302 pub content: String,
303 pub status: String,
304}
305
306#[derive(Debug, Clone)]
308pub struct AgentCommand {
309 pub name: String,
310 pub description: Option<String>,
311}