use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WsMessageType {
#[serde(rename = "tool_call")]
ToolCall,
#[serde(rename = "tool_result")]
ToolResult,
#[serde(rename = "approval_required")]
ApprovalRequired,
#[serde(rename = "approval_resolved")]
ApprovalResolved,
#[serde(rename = "ask_user_required")]
AskUserRequired,
#[serde(rename = "ask_user_resolved")]
AskUserResolved,
#[serde(rename = "plan_content")]
PlanContent,
#[serde(rename = "plan_approval_required")]
PlanApprovalRequired,
#[serde(rename = "plan_approval_resolved")]
PlanApprovalResolved,
#[serde(rename = "status_update")]
StatusUpdate,
#[serde(rename = "task_completed")]
TaskCompleted,
#[serde(rename = "subagent_start")]
SubagentStart,
#[serde(rename = "subagent_complete")]
SubagentComplete,
#[serde(rename = "parallel_agents_start")]
ParallelAgentsStart,
#[serde(rename = "parallel_agents_done")]
ParallelAgentsDone,
#[serde(rename = "thinking_block")]
ThinkingBlock,
#[serde(rename = "progress")]
Progress,
#[serde(rename = "nested_tool_call")]
NestedToolCall,
#[serde(rename = "nested_tool_result")]
NestedToolResult,
#[serde(rename = "message_chunk")]
MessageChunk,
#[serde(rename = "message_start")]
MessageStart,
#[serde(rename = "message_complete")]
MessageComplete,
#[serde(rename = "session_activity")]
SessionActivity,
#[serde(rename = "user_message")]
UserMessage,
#[serde(rename = "mcp:status_changed")]
McpStatusChanged,
#[serde(rename = "mcp:servers_updated")]
McpServersUpdated,
#[serde(rename = "error")]
Error,
#[serde(rename = "pong")]
Pong,
#[serde(rename = "query")]
Query,
#[serde(rename = "approve")]
Approve,
#[serde(rename = "ask_user_response")]
AskUserResponse,
#[serde(rename = "plan_approval_response")]
PlanApprovalResponse,
#[serde(rename = "ping")]
Ping,
#[serde(rename = "interrupt")]
Interrupt,
}
impl WsMessageType {
pub fn as_str(&self) -> &'static str {
match self {
Self::ToolCall => "tool_call",
Self::ToolResult => "tool_result",
Self::ApprovalRequired => "approval_required",
Self::ApprovalResolved => "approval_resolved",
Self::AskUserRequired => "ask_user_required",
Self::AskUserResolved => "ask_user_resolved",
Self::PlanContent => "plan_content",
Self::PlanApprovalRequired => "plan_approval_required",
Self::PlanApprovalResolved => "plan_approval_resolved",
Self::StatusUpdate => "status_update",
Self::TaskCompleted => "task_completed",
Self::SubagentStart => "subagent_start",
Self::SubagentComplete => "subagent_complete",
Self::ParallelAgentsStart => "parallel_agents_start",
Self::ParallelAgentsDone => "parallel_agents_done",
Self::ThinkingBlock => "thinking_block",
Self::Progress => "progress",
Self::NestedToolCall => "nested_tool_call",
Self::NestedToolResult => "nested_tool_result",
Self::MessageChunk => "message_chunk",
Self::MessageStart => "message_start",
Self::MessageComplete => "message_complete",
Self::SessionActivity => "session_activity",
Self::UserMessage => "user_message",
Self::McpStatusChanged => "mcp:status_changed",
Self::McpServersUpdated => "mcp:servers_updated",
Self::Error => "error",
Self::Pong => "pong",
Self::Query => "query",
Self::Approve => "approve",
Self::AskUserResponse => "ask_user_response",
Self::PlanApprovalResponse => "plan_approval_response",
Self::Ping => "ping",
Self::Interrupt => "interrupt",
}
}
pub fn from_str_opt(s: &str) -> Option<Self> {
match s {
"tool_call" => Some(Self::ToolCall),
"tool_result" => Some(Self::ToolResult),
"approval_required" => Some(Self::ApprovalRequired),
"approval_resolved" => Some(Self::ApprovalResolved),
"ask_user_required" => Some(Self::AskUserRequired),
"ask_user_resolved" => Some(Self::AskUserResolved),
"plan_content" => Some(Self::PlanContent),
"plan_approval_required" => Some(Self::PlanApprovalRequired),
"plan_approval_resolved" => Some(Self::PlanApprovalResolved),
"status_update" => Some(Self::StatusUpdate),
"task_completed" => Some(Self::TaskCompleted),
"subagent_start" => Some(Self::SubagentStart),
"subagent_complete" => Some(Self::SubagentComplete),
"parallel_agents_start" => Some(Self::ParallelAgentsStart),
"parallel_agents_done" => Some(Self::ParallelAgentsDone),
"thinking_block" => Some(Self::ThinkingBlock),
"progress" => Some(Self::Progress),
"nested_tool_call" => Some(Self::NestedToolCall),
"nested_tool_result" => Some(Self::NestedToolResult),
"message_chunk" => Some(Self::MessageChunk),
"message_start" => Some(Self::MessageStart),
"message_complete" => Some(Self::MessageComplete),
"session_activity" => Some(Self::SessionActivity),
"user_message" => Some(Self::UserMessage),
"mcp:status_changed" => Some(Self::McpStatusChanged),
"mcp:servers_updated" => Some(Self::McpServersUpdated),
"error" => Some(Self::Error),
"pong" => Some(Self::Pong),
"query" => Some(Self::Query),
"approve" => Some(Self::Approve),
"ask_user_response" => Some(Self::AskUserResponse),
"plan_approval_response" => Some(Self::PlanApprovalResponse),
"ping" => Some(Self::Ping),
"interrupt" => Some(Self::Interrupt),
_ => None,
}
}
}
impl fmt::Display for WsMessageType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
pub fn ws_message(msg_type: WsMessageType, data: serde_json::Value) -> serde_json::Value {
serde_json::json!({
"type": msg_type.as_str(),
"data": data,
})
}
#[cfg(test)]
#[path = "protocol_tests.rs"]
mod tests;