Skip to main content

magic_coder_types/protocol/
types.rs

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    /// Tool must be executed by a connected client (TUI/VS Code).
21    ClientLocal,
22    /// Tool is executed server-side (agents/MCP/etc). Clients must not provide outputs.
23    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, Serialize, Deserialize)]
36pub struct ToolCallOutput {
37    /// Tool call id
38    pub id: String,
39
40    pub is_error: bool,
41    pub output: String,
42    #[serde(default, skip_serializing_if = "Option::is_none")]
43    pub duration_seconds: Option<i32>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub enum ClientMessage {
48    HelloMath {
49        /// Random per-client-instance id (generated on client startup).
50        ///
51        /// Used for multi-client tool-call claiming/coordination. Not derived from auth token.
52        client_instance_id: String,
53        /// Client version.
54        version: String,
55        /// Minimum supported server version (the client can work with any server >= this).
56        min_supported_version: String,
57    },
58    /// Send a user message.
59    ///
60    /// If `thread_id` is `None`, the server creates a new thread and returns it in `SendMessageAck`.
61    /// `request_id` is a client-generated correlation id for 1:1 request↔response mapping.
62    SendMessage {
63        request_id: Uuid,
64        thread_id: Option<Uuid>,
65        text: String,
66    },
67    /// Update/refresh auth token without reconnecting the WebSocket.
68    UpdateAuthToken {
69        token: String,
70    },
71    /// Update the client's workspace roots / default root (used for prompt context + validations).
72    ///
73    /// Sent separately from `HelloMath` so roots can be updated without reconnecting.
74    UpdateWorkspaceRoots {
75        default_root: String,
76        workspace_roots: Vec<String>,
77    },
78    /// Set runtime mode for a thread.
79    SetRuntimeMode {
80        thread_id: Uuid,
81        mode: RuntimeMode,
82    },
83    RejectToolCall {
84        id: String,
85        #[serde(default, skip_serializing_if = "Option::is_none")]
86        reason: Option<String>,
87    },
88    AcceptToolCall {
89        id: String,
90    },
91    ToolCallOutputs {
92        outputs: Vec<ToolCallOutput>,
93    },
94    /// Cancel the current in-progress generation for a specific assistant message.
95    CancelGeneration {
96        message_id: Uuid,
97    },
98}
99
100#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
101pub struct Usage {
102    pub input_tokens: i32,
103    pub output_tokens: i32,
104    #[serde(default)]
105    pub cache_read_input_tokens: i32,
106    #[serde(default)]
107    pub cache_creation_input_tokens: i32,
108    #[serde(default)]
109    pub cache_creation_input_tokens_5m: i32,
110    #[serde(default)]
111    pub cache_creation_input_tokens_1h: i32,
112}
113
114#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
115pub enum MessageStatus {
116    Completed,
117    /// The agent is waiting for the client/user to provide more input (e.g. tool outputs / approvals)
118    /// before it can continue generation.
119    WaitingForUser,
120    Failed,
121    Cancelled,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub enum ServerMessage {
126    HelloMagic {
127        version: String,
128        min_supported_version: String,
129    },
130    VersionMismatch {
131        server_version: String,
132        server_min_supported_version: String,
133    },
134    Goodbye {
135        reconnect: bool,
136    },
137    SendMessageAck {
138        request_id: Uuid,
139        thread_id: Uuid,
140        user_message_id: Uuid,
141    },
142    AuthUpdated,
143    RuntimeModeUpdated {
144        thread_id: Uuid,
145        mode: RuntimeMode,
146        #[serde(default, skip_serializing_if = "Option::is_none")]
147        changed_by_client_instance_id: Option<String>,
148    },
149    MessageHeader {
150        message_id: Uuid,
151        thread_id: Uuid,
152        role: Role,
153        #[serde(default, skip_serializing_if = "Option::is_none")]
154        request_id: Option<Uuid>,
155    },
156    ReasoningDelta {
157        message_id: Uuid,
158        content: String,
159    },
160    TextDelta {
161        message_id: Uuid,
162        content: String,
163    },
164    ToolCallHeader {
165        message_id: Uuid,
166        tool_call_id: String,
167        name: String,
168        execution_target: ToolExecutionTarget,
169        approval: ToolCallApproval,
170    },
171    ToolCallArgumentsDelta {
172        message_id: Uuid,
173        tool_call_id: String,
174        delta: String,
175    },
176    ToolCall {
177        message_id: Uuid,
178        tool_call_id: String,
179        args: Value,
180    },
181    ToolCallClaimed {
182        message_id: Uuid,
183        tool_call_id: String,
184        claimed_by_client_instance_id: String,
185    },
186    ToolCallApprovalUpdated {
187        message_id: Uuid,
188        tool_call_id: String,
189        approval: ToolCallApproval,
190    },
191    MessageDone {
192        message_id: Uuid,
193        #[serde(default, skip_serializing_if = "Option::is_none")]
194        usage: Option<Usage>,
195        status: MessageStatus,
196    },
197    Error {
198        #[serde(default, skip_serializing_if = "Option::is_none")]
199        request_id: Option<Uuid>,
200        #[serde(default, skip_serializing_if = "Option::is_none")]
201        message_id: Option<Uuid>,
202        code: String,
203        message: String,
204    },
205}