1use serde::{Deserialize, Serialize};
8use std::fmt;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub enum WsMessageType {
15 #[serde(rename = "tool_call")]
18 ToolCall,
19 #[serde(rename = "tool_result")]
21 ToolResult,
22 #[serde(rename = "approval_required")]
24 ApprovalRequired,
25 #[serde(rename = "approval_resolved")]
27 ApprovalResolved,
28 #[serde(rename = "ask_user_required")]
30 AskUserRequired,
31 #[serde(rename = "ask_user_resolved")]
33 AskUserResolved,
34 #[serde(rename = "plan_content")]
36 PlanContent,
37 #[serde(rename = "plan_approval_required")]
39 PlanApprovalRequired,
40 #[serde(rename = "plan_approval_resolved")]
42 PlanApprovalResolved,
43 #[serde(rename = "status_update")]
45 StatusUpdate,
46 #[serde(rename = "task_completed")]
48 TaskCompleted,
49 #[serde(rename = "subagent_start")]
51 SubagentStart,
52 #[serde(rename = "subagent_complete")]
54 SubagentComplete,
55 #[serde(rename = "parallel_agents_start")]
57 ParallelAgentsStart,
58 #[serde(rename = "parallel_agents_done")]
60 ParallelAgentsDone,
61 #[serde(rename = "thinking_block")]
63 ThinkingBlock,
64 #[serde(rename = "progress")]
66 Progress,
67 #[serde(rename = "nested_tool_call")]
69 NestedToolCall,
70 #[serde(rename = "nested_tool_result")]
72 NestedToolResult,
73 #[serde(rename = "message_chunk")]
75 MessageChunk,
76 #[serde(rename = "message_start")]
78 MessageStart,
79 #[serde(rename = "message_complete")]
81 MessageComplete,
82 #[serde(rename = "session_activity")]
84 SessionActivity,
85 #[serde(rename = "user_message")]
87 UserMessage,
88 #[serde(rename = "mcp:status_changed")]
90 McpStatusChanged,
91 #[serde(rename = "mcp:servers_updated")]
93 McpServersUpdated,
94 #[serde(rename = "error")]
96 Error,
97 #[serde(rename = "pong")]
99 Pong,
100
101 #[serde(rename = "query")]
104 Query,
105 #[serde(rename = "approve")]
107 Approve,
108 #[serde(rename = "ask_user_response")]
110 AskUserResponse,
111 #[serde(rename = "plan_approval_response")]
113 PlanApprovalResponse,
114 #[serde(rename = "ping")]
116 Ping,
117 #[serde(rename = "interrupt")]
119 Interrupt,
120}
121
122impl WsMessageType {
123 pub fn as_str(&self) -> &'static str {
125 match self {
126 Self::ToolCall => "tool_call",
128 Self::ToolResult => "tool_result",
129 Self::ApprovalRequired => "approval_required",
130 Self::ApprovalResolved => "approval_resolved",
131 Self::AskUserRequired => "ask_user_required",
132 Self::AskUserResolved => "ask_user_resolved",
133 Self::PlanContent => "plan_content",
134 Self::PlanApprovalRequired => "plan_approval_required",
135 Self::PlanApprovalResolved => "plan_approval_resolved",
136 Self::StatusUpdate => "status_update",
137 Self::TaskCompleted => "task_completed",
138 Self::SubagentStart => "subagent_start",
139 Self::SubagentComplete => "subagent_complete",
140 Self::ParallelAgentsStart => "parallel_agents_start",
141 Self::ParallelAgentsDone => "parallel_agents_done",
142 Self::ThinkingBlock => "thinking_block",
143 Self::Progress => "progress",
144 Self::NestedToolCall => "nested_tool_call",
145 Self::NestedToolResult => "nested_tool_result",
146 Self::MessageChunk => "message_chunk",
147 Self::MessageStart => "message_start",
148 Self::MessageComplete => "message_complete",
149 Self::SessionActivity => "session_activity",
150 Self::UserMessage => "user_message",
151 Self::McpStatusChanged => "mcp:status_changed",
152 Self::McpServersUpdated => "mcp:servers_updated",
153 Self::Error => "error",
154 Self::Pong => "pong",
155 Self::Query => "query",
157 Self::Approve => "approve",
158 Self::AskUserResponse => "ask_user_response",
159 Self::PlanApprovalResponse => "plan_approval_response",
160 Self::Ping => "ping",
161 Self::Interrupt => "interrupt",
162 }
163 }
164
165 pub fn from_str_opt(s: &str) -> Option<Self> {
167 match s {
168 "tool_call" => Some(Self::ToolCall),
169 "tool_result" => Some(Self::ToolResult),
170 "approval_required" => Some(Self::ApprovalRequired),
171 "approval_resolved" => Some(Self::ApprovalResolved),
172 "ask_user_required" => Some(Self::AskUserRequired),
173 "ask_user_resolved" => Some(Self::AskUserResolved),
174 "plan_content" => Some(Self::PlanContent),
175 "plan_approval_required" => Some(Self::PlanApprovalRequired),
176 "plan_approval_resolved" => Some(Self::PlanApprovalResolved),
177 "status_update" => Some(Self::StatusUpdate),
178 "task_completed" => Some(Self::TaskCompleted),
179 "subagent_start" => Some(Self::SubagentStart),
180 "subagent_complete" => Some(Self::SubagentComplete),
181 "parallel_agents_start" => Some(Self::ParallelAgentsStart),
182 "parallel_agents_done" => Some(Self::ParallelAgentsDone),
183 "thinking_block" => Some(Self::ThinkingBlock),
184 "progress" => Some(Self::Progress),
185 "nested_tool_call" => Some(Self::NestedToolCall),
186 "nested_tool_result" => Some(Self::NestedToolResult),
187 "message_chunk" => Some(Self::MessageChunk),
188 "message_start" => Some(Self::MessageStart),
189 "message_complete" => Some(Self::MessageComplete),
190 "session_activity" => Some(Self::SessionActivity),
191 "user_message" => Some(Self::UserMessage),
192 "mcp:status_changed" => Some(Self::McpStatusChanged),
193 "mcp:servers_updated" => Some(Self::McpServersUpdated),
194 "error" => Some(Self::Error),
195 "pong" => Some(Self::Pong),
196 "query" => Some(Self::Query),
197 "approve" => Some(Self::Approve),
198 "ask_user_response" => Some(Self::AskUserResponse),
199 "plan_approval_response" => Some(Self::PlanApprovalResponse),
200 "ping" => Some(Self::Ping),
201 "interrupt" => Some(Self::Interrupt),
202 _ => None,
203 }
204 }
205}
206
207impl fmt::Display for WsMessageType {
208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209 f.write_str(self.as_str())
210 }
211}
212
213pub fn ws_message(msg_type: WsMessageType, data: serde_json::Value) -> serde_json::Value {
215 serde_json::json!({
216 "type": msg_type.as_str(),
217 "data": data,
218 })
219}
220
221#[cfg(test)]
222#[path = "protocol_tests.rs"]
223mod tests;