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, Serialize, Deserialize)]
12pub struct ToolCallOutput {
13    /// Tool call id
14    pub id: String,
15
16    pub is_error: bool,
17    pub output: String,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub enum ClientMessage {
22    HelloMath {
23        /// Random per-client-instance id (generated on client startup).
24        ///
25        /// Used for multi-client tool-call claiming/coordination. Not derived from auth token.
26        client_instance_id: String,
27        /// Client version.
28        version: String,
29        /// Minimum supported server version (the client can work with any server >= this).
30        min_supported_version: String,
31    },
32    /// Send a user message.
33    ///
34    /// If `thread_id` is `None`, the server creates a new thread and returns it in `SendMessageAck`.
35    /// `request_id` is a client-generated correlation id for 1:1 request↔response mapping.
36    SendMessage {
37        request_id: Uuid,
38        thread_id: Option<Uuid>,
39        text: String,
40    },
41    /// Update/refresh auth token without reconnecting the WebSocket.
42    UpdateAuthToken {
43        token: String,
44    },
45    /// Update the client's workspace roots / default root (used for prompt context + validations).
46    ///
47    /// Sent separately from `HelloMath` so roots can be updated without reconnecting.
48    UpdateWorkspaceRoots {
49        default_root: String,
50        workspace_roots: Vec<String>,
51    },
52    RejectToolCall {
53        id: String,
54        #[serde(default, skip_serializing_if = "Option::is_none")]
55        reason: Option<String>,
56    },
57    AcceptToolCall {
58        id: String,
59    },
60    ToolCallOutputs {
61        outputs: Vec<ToolCallOutput>,
62    },
63}
64
65#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
66pub struct Usage {
67    pub input_tokens: i32,
68    pub output_tokens: i32,
69}
70
71#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
72pub enum MessageStatus {
73    Completed,
74    /// The agent is waiting for the client/user to provide more input (e.g. tool outputs / approvals)
75    /// before it can continue generation.
76    WaitingForUser,
77    Failed,
78    Cancelled,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub enum ServerMessage {
83    HelloMagic {
84        version: String,
85        min_supported_version: String,
86    },
87    VersionMismatch {
88        server_version: String,
89        server_min_supported_version: String,
90    },
91    Goodbye {
92        reconnect: bool,
93    },
94    SendMessageAck {
95        request_id: Uuid,
96        thread_id: Uuid,
97        user_message_id: Uuid,
98    },
99    AuthUpdated,
100    MessageHeader {
101        message_id: Uuid,
102        thread_id: Uuid,
103        role: Role,
104        #[serde(default, skip_serializing_if = "Option::is_none")]
105        request_id: Option<Uuid>,
106    },
107    ReasoningDelta {
108        message_id: Uuid,
109        content: String,
110    },
111    TextDelta {
112        message_id: Uuid,
113        content: String,
114    },
115    ToolCallHeader {
116        message_id: Uuid,
117        tool_call_id: String,
118        name: String,
119        requires_approval: bool,
120    },
121    ToolCallArgumentsDelta {
122        message_id: Uuid,
123        tool_call_id: String,
124        delta: String,
125    },
126    ToolCall {
127        message_id: Uuid,
128        tool_call_id: String,
129        args: Value,
130    },
131    ToolCallClaimed {
132        message_id: Uuid,
133        tool_call_id: String,
134        claimed_by_client_instance_id: String,
135    },
136    MessageDone {
137        message_id: Uuid,
138        #[serde(default, skip_serializing_if = "Option::is_none")]
139        usage: Option<Usage>,
140        status: MessageStatus,
141    },
142    Error {
143        #[serde(default, skip_serializing_if = "Option::is_none")]
144        request_id: Option<Uuid>,
145        #[serde(default, skip_serializing_if = "Option::is_none")]
146        message_id: Option<Uuid>,
147        code: String,
148        message: String,
149    },
150}
151