1use crate::v2::schema as v2;
4use crate::{JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, UntypedMessage};
5
6macro_rules! impl_v2_jsonrpc_request {
7 ($req:ty, $resp:ty, $method:literal) => {
8 impl JsonRpcMessage for $req {
9 fn matches_method(method: &str) -> bool {
10 method == $method
11 }
12
13 fn method(&self) -> &str {
14 $method
15 }
16
17 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
18 UntypedMessage::new($method, self)
19 }
20
21 fn parse_message(
22 method: &str,
23 params: &serde_json::Value,
24 ) -> Result<Self, crate::Error> {
25 if method != $method {
26 return Err(crate::Error::method_not_found());
27 }
28 crate::util::json_cast_params(params)
29 }
30 }
31
32 impl JsonRpcRequest for $req {
33 type Response = $resp;
34 }
35
36 impl JsonRpcResponse for $resp {
37 fn into_json(self, _method: &str) -> Result<serde_json::Value, crate::Error> {
38 serde_json::to_value(self).map_err(crate::Error::into_internal_error)
39 }
40
41 fn from_json(_method: &str, value: serde_json::Value) -> Result<Self, crate::Error> {
42 crate::util::json_cast(value)
43 }
44 }
45 };
46}
47
48macro_rules! impl_v2_jsonrpc_notification {
49 ($notif:ty, $method:literal) => {
50 impl JsonRpcMessage for $notif {
51 fn matches_method(method: &str) -> bool {
52 method == $method
53 }
54
55 fn method(&self) -> &str {
56 $method
57 }
58
59 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
60 UntypedMessage::new($method, self)
61 }
62
63 fn parse_message(
64 method: &str,
65 params: &serde_json::Value,
66 ) -> Result<Self, crate::Error> {
67 if method != $method {
68 return Err(crate::Error::method_not_found());
69 }
70 crate::util::json_cast_params(params)
71 }
72 }
73
74 impl JsonRpcNotification for $notif {}
75 };
76}
77
78macro_rules! impl_v2_jsonrpc_request_enum {
79 ($enum:ty {
80 $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
81 [ext] $ext_variant:ident,
82 }) => {
83 impl JsonRpcMessage for $enum {
84 fn matches_method(_method: &str) -> bool {
85 true
86 }
87
88 fn method(&self) -> &str {
89 <$enum>::method(self)
93 }
94
95 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
96 UntypedMessage::new(self.method(), self)
97 }
98
99 fn parse_message(
100 method: &str,
101 params: &serde_json::Value,
102 ) -> Result<Self, crate::Error> {
103 match method {
104 $( $(#[$meta])* $method => crate::util::json_cast_params(params).map(Self::$variant), )*
105 _ => {
106 if method.starts_with('_') {
107 crate::util::json_cast_params(params).map(
108 |ext_req: v2::ExtRequest| {
109 Self::$ext_variant(Box::new(v2::ExtRequest::new(
110 method.to_string(),
111 ext_req.params,
112 )))
113 },
114 )
115 } else {
116 Err(crate::Error::method_not_found())
117 }
118 }
119 }
120 }
121 }
122
123 impl JsonRpcRequest for $enum {
124 type Response = serde_json::Value;
125 }
126 };
127}
128
129macro_rules! impl_v2_jsonrpc_notification_enum {
130 ($enum:ty {
131 $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
132 [ext] $ext_variant:ident,
133 }) => {
134 impl JsonRpcMessage for $enum {
135 fn matches_method(_method: &str) -> bool {
136 true
137 }
138
139 fn method(&self) -> &str {
140 <$enum>::method(self)
144 }
145
146 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
147 UntypedMessage::new(self.method(), self)
148 }
149
150 fn parse_message(
151 method: &str,
152 params: &serde_json::Value,
153 ) -> Result<Self, crate::Error> {
154 match method {
155 $( $(#[$meta])* $method => crate::util::json_cast_params(params).map(Self::$variant), )*
156 _ => {
157 if method.starts_with('_') {
158 crate::util::json_cast_params(params).map(
159 |ext_notif: v2::ExtNotification| {
160 Self::$ext_variant(Box::new(v2::ExtNotification::new(
161 method.to_string(),
162 ext_notif.params,
163 )))
164 },
165 )
166 } else {
167 Err(crate::Error::method_not_found())
168 }
169 }
170 }
171 }
172 }
173
174 impl JsonRpcNotification for $enum {}
175 };
176}
177
178macro_rules! impl_v2_jsonrpc_response_enum {
179 ($enum:ty {
180 $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
181 [ext] $ext_variant:ident,
182 }) => {
183 impl JsonRpcResponse for $enum {
184 fn into_json(
185 self,
186 _method: &str,
187 ) -> Result<serde_json::Value, crate::Error> {
188 serde_json::to_value(self).map_err(crate::Error::into_internal_error)
189 }
190
191 fn from_json(
192 method: &str,
193 value: serde_json::Value,
194 ) -> Result<Self, crate::Error> {
195 match method {
196 $( $(#[$meta])* $method => crate::util::json_cast(value).map(Self::$variant), )*
197 _ => {
198 if method.starts_with('_') {
199 crate::util::json_cast(value).map(Self::$ext_variant)
200 } else {
201 Err(crate::Error::method_not_found())
202 }
203 }
204 }
205 }
206 }
207 };
208}
209
210impl_v2_jsonrpc_request!(v2::InitializeRequest, v2::InitializeResponse, "initialize");
211impl_v2_jsonrpc_request!(v2::LoginAuthRequest, v2::LoginAuthResponse, "auth/login");
212impl_v2_jsonrpc_request!(v2::LogoutAuthRequest, v2::LogoutAuthResponse, "auth/logout");
213#[cfg(feature = "unstable_auth_status")]
214impl_v2_jsonrpc_request!(v2::AuthStatusRequest, v2::AuthStatusResponse, "auth/status");
215#[cfg(feature = "unstable_llm_providers")]
216impl_v2_jsonrpc_request!(
217 v2::ListProvidersRequest,
218 v2::ListProvidersResponse,
219 "providers/list"
220);
221#[cfg(feature = "unstable_llm_providers")]
222impl_v2_jsonrpc_request!(
223 v2::SetProviderRequest,
224 v2::SetProviderResponse,
225 "providers/set"
226);
227#[cfg(feature = "unstable_llm_providers")]
228impl_v2_jsonrpc_request!(
229 v2::DisableProviderRequest,
230 v2::DisableProviderResponse,
231 "providers/disable"
232);
233impl_v2_jsonrpc_request!(v2::NewSessionRequest, v2::NewSessionResponse, "session/new");
234impl_v2_jsonrpc_request!(
235 v2::ListSessionsRequest,
236 v2::ListSessionsResponse,
237 "session/list"
238);
239impl_v2_jsonrpc_request!(
240 v2::DeleteSessionRequest,
241 v2::DeleteSessionResponse,
242 "session/delete"
243);
244#[cfg(feature = "unstable_session_fork")]
245impl_v2_jsonrpc_request!(
246 v2::ForkSessionRequest,
247 v2::ForkSessionResponse,
248 "session/fork"
249);
250#[cfg(feature = "unstable_session_archive")]
251impl_v2_jsonrpc_request!(
252 v2::ArchiveSessionRequest,
253 v2::ArchiveSessionResponse,
254 "session/archive"
255);
256#[cfg(feature = "unstable_session_archive")]
257impl_v2_jsonrpc_request!(
258 v2::UnarchiveSessionRequest,
259 v2::UnarchiveSessionResponse,
260 "session/unarchive"
261);
262#[cfg(feature = "unstable_session_status")]
263impl_v2_jsonrpc_request!(
264 v2::SessionStatusRequest,
265 v2::SessionStatusResponse,
266 "session/status"
267);
268#[cfg(feature = "unstable_session_set_title")]
269impl_v2_jsonrpc_request!(
270 v2::SetSessionTitleRequest,
271 v2::SetSessionTitleResponse,
272 "session/set_title"
273);
274impl_v2_jsonrpc_request!(
275 v2::ResumeSessionRequest,
276 v2::ResumeSessionResponse,
277 "session/resume"
278);
279impl_v2_jsonrpc_request!(
280 v2::CloseSessionRequest,
281 v2::CloseSessionResponse,
282 "session/close"
283);
284impl_v2_jsonrpc_request!(
285 v2::SetSessionConfigOptionRequest,
286 v2::SetSessionConfigOptionResponse,
287 "session/set_config_option"
288);
289impl_v2_jsonrpc_request!(
290 v2::CancelToolCallRequest,
291 v2::CancelToolCallResponse,
292 "tool_call/cancel"
293);
294impl_v2_jsonrpc_request!(
295 v2::CancelTerminalRequest,
296 v2::CancelTerminalResponse,
297 "terminal/cancel"
298);
299impl_v2_jsonrpc_request!(v2::PromptRequest, v2::PromptResponse, "session/prompt");
300#[cfg(feature = "unstable_mcp_over_acp")]
301impl_v2_jsonrpc_request!(v2::MessageMcpRequest, v2::MessageMcpResponse, "mcp/message");
302
303impl_v2_jsonrpc_notification!(v2::CancelRequestNotification, "$/cancel_request");
304impl_v2_jsonrpc_notification!(v2::CancelSessionNotification, "session/cancel");
305#[cfg(feature = "unstable_mcp_over_acp")]
306impl_v2_jsonrpc_notification!(v2::MessageMcpNotification, "mcp/message");
307
308impl_v2_jsonrpc_request!(
309 v2::RequestPermissionRequest,
310 v2::RequestPermissionResponse,
311 "session/request_permission"
312);
313impl_v2_jsonrpc_request!(
314 v2::CreateElicitationRequest,
315 v2::CreateElicitationResponse,
316 "elicitation/create"
317);
318
319impl_v2_jsonrpc_notification!(v2::UpdateSessionNotification, "session/update");
320impl_v2_jsonrpc_notification!(v2::CompleteElicitationNotification, "elicitation/complete");
321#[cfg(feature = "unstable_auth_status")]
322impl_v2_jsonrpc_notification!(v2::AuthStatusUpdateNotification, "auth/status_update");
323
324impl_jsonrpc_protocol_level_notification_enum!(v2::ProtocolLevelNotification {
325 CancelRequestNotification => "$/cancel_request",
326});
327
328impl_v2_jsonrpc_request_enum!(v2::ClientRequest {
329 InitializeRequest => "initialize",
330 LoginAuthRequest => "auth/login",
331 LogoutAuthRequest => "auth/logout",
332 #[cfg(feature = "unstable_auth_status")]
333 AuthStatusRequest => "auth/status",
334 #[cfg(feature = "unstable_llm_providers")]
335 ListProvidersRequest => "providers/list",
336 #[cfg(feature = "unstable_llm_providers")]
337 SetProviderRequest => "providers/set",
338 #[cfg(feature = "unstable_llm_providers")]
339 DisableProviderRequest => "providers/disable",
340 NewSessionRequest => "session/new",
341 ListSessionsRequest => "session/list",
342 DeleteSessionRequest => "session/delete",
343 #[cfg(feature = "unstable_session_fork")]
344 ForkSessionRequest => "session/fork",
345 #[cfg(feature = "unstable_session_archive")]
346 ArchiveSessionRequest => "session/archive",
347 #[cfg(feature = "unstable_session_archive")]
348 UnarchiveSessionRequest => "session/unarchive",
349 #[cfg(feature = "unstable_session_status")]
350 SessionStatusRequest => "session/status",
351 #[cfg(feature = "unstable_session_set_title")]
352 SetSessionTitleRequest => "session/set_title",
353 ResumeSessionRequest => "session/resume",
354 CloseSessionRequest => "session/close",
355 CancelToolCallRequest => "tool_call/cancel",
356 CancelTerminalRequest => "terminal/cancel",
357 SetSessionConfigOptionRequest => "session/set_config_option",
358 PromptRequest => "session/prompt",
359 [ext] ExtMethodRequest,
360});
361
362impl_v2_jsonrpc_response_enum!(v2::AgentResponse {
363 InitializeResponse => "initialize",
364 LoginAuthResponse => "auth/login",
365 LogoutAuthResponse => "auth/logout",
366 #[cfg(feature = "unstable_auth_status")]
367 AuthStatusResponse => "auth/status",
368 #[cfg(feature = "unstable_llm_providers")]
369 ListProvidersResponse => "providers/list",
370 #[cfg(feature = "unstable_llm_providers")]
371 SetProviderResponse => "providers/set",
372 #[cfg(feature = "unstable_llm_providers")]
373 DisableProviderResponse => "providers/disable",
374 NewSessionResponse => "session/new",
375 ListSessionsResponse => "session/list",
376 DeleteSessionResponse => "session/delete",
377 #[cfg(feature = "unstable_session_fork")]
378 ForkSessionResponse => "session/fork",
379 #[cfg(feature = "unstable_session_archive")]
380 ArchiveSessionResponse => "session/archive",
381 #[cfg(feature = "unstable_session_archive")]
382 UnarchiveSessionResponse => "session/unarchive",
383 #[cfg(feature = "unstable_session_status")]
384 SessionStatusResponse => "session/status",
385 #[cfg(feature = "unstable_session_set_title")]
386 SetSessionTitleResponse => "session/set_title",
387 ResumeSessionResponse => "session/resume",
388 CloseSessionResponse => "session/close",
389 CancelToolCallResponse => "tool_call/cancel",
390 CancelTerminalResponse => "terminal/cancel",
391 SetSessionConfigOptionResponse => "session/set_config_option",
392 PromptResponse => "session/prompt",
393 [ext] ExtMethodResponse,
394});
395
396impl_v2_jsonrpc_notification_enum!(v2::ClientNotification {
397 CancelSessionNotification => "session/cancel",
398 #[cfg(feature = "unstable_mcp_over_acp")]
399 MessageMcpNotification => "mcp/message",
400 [ext] ExtNotification,
401});
402
403impl_v2_jsonrpc_request_enum!(v2::AgentRequest {
404 RequestPermissionRequest => "session/request_permission",
405 CreateElicitationRequest => "elicitation/create",
406 #[cfg(feature = "unstable_mcp_over_acp")]
407 MessageMcpRequest => "mcp/message",
408 [ext] ExtMethodRequest,
409});
410
411impl_v2_jsonrpc_response_enum!(v2::ClientResponse {
412 RequestPermissionResponse => "session/request_permission",
413 CreateElicitationResponse => "elicitation/create",
414 #[cfg(feature = "unstable_mcp_over_acp")]
415 MessageMcpResponse => "mcp/message",
416 [ext] ExtMethodResponse,
417});
418
419impl_v2_jsonrpc_notification_enum!(v2::AgentNotification {
420 UpdateSessionNotification => "session/update",
421 CompleteElicitationNotification => "elicitation/complete",
422 #[cfg(feature = "unstable_auth_status")]
423 AuthStatusUpdateNotification => "auth/status_update",
424 [ext] ExtNotification,
425});