claude_codes/
messages.rs

1//! Message types for the Claude Code protocol
2
3use crate::types::*;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7/// Base message trait for all protocol messages
8pub trait Message: Serialize + for<'de> Deserialize<'de> {
9    fn message_type(&self) -> &str;
10}
11
12/// Request message sent to Claude Code
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Request {
15    #[serde(rename = "type")]
16    pub message_type: String,
17
18    pub id: Id,
19
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub session_id: Option<SessionId>,
22
23    pub payload: RequestPayload,
24
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub metadata: Option<Metadata>,
27}
28
29/// Different types of request payloads
30#[derive(Debug, Clone, Serialize, Deserialize)]
31#[serde(tag = "action", rename_all = "snake_case")]
32pub enum RequestPayload {
33    Initialize(InitializeRequest),
34    Execute(ExecuteRequest),
35    Complete(CompleteRequest),
36    Cancel(CancelRequest),
37    GetStatus(GetStatusRequest),
38    Custom(Value),
39}
40
41/// Initialize a new session
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct InitializeRequest {
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub working_directory: Option<String>,
46
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub environment: Option<Vec<EnvironmentVariable>>,
49
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub capabilities: Option<Vec<Capability>>,
52}
53
54/// Environment variable
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct EnvironmentVariable {
57    pub name: String,
58    pub value: String,
59}
60
61/// Execute a command or task
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct ExecuteRequest {
64    pub command: String,
65
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub arguments: Option<Vec<String>>,
68
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub input: Option<String>,
71
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub timeout_ms: Option<u64>,
74
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub working_directory: Option<String>,
77}
78
79/// Request completion suggestions
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct CompleteRequest {
82    pub prompt: String,
83
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub context: Option<CompletionContext>,
86
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub max_suggestions: Option<usize>,
89}
90
91/// Context for completion requests
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct CompletionContext {
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub file_path: Option<String>,
96
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub cursor_position: Option<CursorPosition>,
99
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub surrounding_code: Option<String>,
102}
103
104/// Cursor position in a file
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct CursorPosition {
107    pub line: usize,
108    pub column: usize,
109}
110
111/// Cancel a running operation
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct CancelRequest {
114    pub target_id: Id,
115
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub reason: Option<String>,
118}
119
120/// Get status of an operation
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct GetStatusRequest {
123    pub target_id: Id,
124
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub include_details: Option<bool>,
127}
128
129/// Response message from Claude Code
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct Response {
132    #[serde(rename = "type")]
133    pub message_type: String,
134
135    pub id: Id,
136
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub request_id: Option<Id>,
139
140    pub status: Status,
141
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub payload: Option<ResponsePayload>,
144
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub error: Option<ErrorDetail>,
147
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub metadata: Option<Metadata>,
150}
151
152/// Different types of response payloads
153#[derive(Debug, Clone, Serialize, Deserialize)]
154#[serde(tag = "result_type", rename_all = "snake_case")]
155pub enum ResponsePayload {
156    Initialize(InitializeResponse),
157    Execute(ExecuteResponse),
158    Complete(CompleteResponse),
159    Status(StatusResponse),
160    Stream(StreamResponse),
161    Custom(Value),
162}
163
164/// Response to initialization
165#[derive(Debug, Clone, Serialize, Deserialize)]
166pub struct InitializeResponse {
167    pub session_id: SessionId,
168    pub version: String,
169    pub capabilities: Vec<Capability>,
170}
171
172/// Response to execution
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ExecuteResponse {
175    #[serde(skip_serializing_if = "Option::is_none")]
176    pub output: Option<String>,
177
178    #[serde(skip_serializing_if = "Option::is_none")]
179    pub error_output: Option<String>,
180
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub exit_code: Option<i32>,
183
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub execution_time_ms: Option<u64>,
186}
187
188/// Response to completion request
189#[derive(Debug, Clone, Serialize, Deserialize)]
190pub struct CompleteResponse {
191    pub suggestions: Vec<CompletionSuggestion>,
192}
193
194/// A single completion suggestion
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct CompletionSuggestion {
197    pub text: String,
198
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub description: Option<String>,
201
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub score: Option<f32>,
204
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub metadata: Option<Value>,
207}
208
209/// Status response
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct StatusResponse {
212    pub status: Status,
213
214    #[serde(skip_serializing_if = "Option::is_none")]
215    pub progress: Option<Progress>,
216
217    #[serde(skip_serializing_if = "Option::is_none")]
218    pub details: Option<Value>,
219}
220
221/// Progress information
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct Progress {
224    pub current: usize,
225    pub total: Option<usize>,
226
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub percentage: Option<f32>,
229
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub message: Option<String>,
232}
233
234/// Streaming response
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct StreamResponse {
237    pub chunk: String,
238
239    #[serde(skip_serializing_if = "Option::is_none")]
240    pub stream_id: Option<String>,
241
242    pub is_final: bool,
243}
244
245/// Event message for notifications
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct Event {
248    #[serde(rename = "type")]
249    pub message_type: String,
250
251    pub event_type: EventType,
252
253    #[serde(skip_serializing_if = "Option::is_none")]
254    pub session_id: Option<SessionId>,
255
256    pub payload: Value,
257
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub metadata: Option<Metadata>,
260}
261
262/// Types of events
263#[derive(Debug, Clone, Serialize, Deserialize)]
264#[serde(rename_all = "snake_case")]
265pub enum EventType {
266    Log,
267    Progress,
268    StateChange,
269    Error,
270    Warning,
271    Info,
272    Debug,
273    Custom(String),
274}