agent_client_protocol/schema/
v2_impls.rs1use crate::schema::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: &impl serde::Serialize,
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_value(_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: &impl serde::Serialize,
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 match self {
90 $( $(#[$meta])* Self::$variant(_) => $method, )*
91 Self::$ext_variant(ext) => &ext.method,
92 _ => "_unknown",
93 }
94 }
95
96 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
97 UntypedMessage::new(self.method(), self)
98 }
99
100 fn parse_message(
101 method: &str,
102 params: &impl serde::Serialize,
103 ) -> Result<Self, crate::Error> {
104 match method {
105 $( $(#[$meta])* $method => crate::util::json_cast_params(params).map(Self::$variant), )*
106 _ => {
107 if method.starts_with('_') {
108 crate::util::json_cast_params(params).map(
109 |ext_req: v2::ExtRequest| {
110 Self::$ext_variant(Box::new(v2::ExtRequest::new(
111 method.to_string(),
112 ext_req.params,
113 )))
114 },
115 )
116 } else {
117 Err(crate::Error::method_not_found())
118 }
119 }
120 }
121 }
122 }
123
124 impl JsonRpcRequest for $enum {
125 type Response = serde_json::Value;
126 }
127 };
128}
129
130macro_rules! impl_v2_jsonrpc_notification_enum {
131 ($enum:ty {
132 $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
133 [ext] $ext_variant:ident,
134 }) => {
135 impl JsonRpcMessage for $enum {
136 fn matches_method(_method: &str) -> bool {
137 true
138 }
139
140 fn method(&self) -> &str {
141 match self {
142 $( $(#[$meta])* Self::$variant(_) => $method, )*
143 Self::$ext_variant(ext) => &ext.method,
144 _ => "_unknown",
145 }
146 }
147
148 fn to_untyped_message(&self) -> Result<UntypedMessage, crate::Error> {
149 UntypedMessage::new(self.method(), self)
150 }
151
152 fn parse_message(
153 method: &str,
154 params: &impl serde::Serialize,
155 ) -> Result<Self, crate::Error> {
156 match method {
157 $( $(#[$meta])* $method => crate::util::json_cast_params(params).map(Self::$variant), )*
158 _ => {
159 if method.starts_with('_') {
160 crate::util::json_cast_params(params).map(
161 |ext_notif: v2::ExtNotification| {
162 Self::$ext_variant(Box::new(v2::ExtNotification::new(
163 method.to_string(),
164 ext_notif.params,
165 )))
166 },
167 )
168 } else {
169 Err(crate::Error::method_not_found())
170 }
171 }
172 }
173 }
174 }
175
176 impl JsonRpcNotification for $enum {}
177 };
178}
179
180macro_rules! impl_v2_jsonrpc_response_enum {
181 ($enum:ty {
182 $( $(#[$meta:meta])* $variant:ident => $method:literal, )*
183 [ext] $ext_variant:ident,
184 }) => {
185 impl JsonRpcResponse for $enum {
186 fn into_json(
187 self,
188 _method: &str,
189 ) -> Result<serde_json::Value, crate::Error> {
190 serde_json::to_value(self).map_err(crate::Error::into_internal_error)
191 }
192
193 fn from_value(
194 method: &str,
195 value: serde_json::Value,
196 ) -> Result<Self, crate::Error> {
197 match method {
198 $( $(#[$meta])* $method => crate::util::json_cast(value).map(Self::$variant), )*
199 _ => {
200 if method.starts_with('_') {
201 crate::util::json_cast(value).map(Self::$ext_variant)
202 } else {
203 Err(crate::Error::method_not_found())
204 }
205 }
206 }
207 }
208 }
209 };
210}
211
212impl_v2_jsonrpc_request!(v2::InitializeRequest, v2::InitializeResponse, "initialize");
213impl_v2_jsonrpc_request!(v2::LoginAuthRequest, v2::LoginAuthResponse, "auth/login");
214impl_v2_jsonrpc_request!(v2::LogoutAuthRequest, v2::LogoutAuthResponse, "auth/logout");
215impl_v2_jsonrpc_request!(v2::NewSessionRequest, v2::NewSessionResponse, "session/new");
216impl_v2_jsonrpc_request!(
217 v2::ListSessionsRequest,
218 v2::ListSessionsResponse,
219 "session/list"
220);
221impl_v2_jsonrpc_request!(
222 v2::DeleteSessionRequest,
223 v2::DeleteSessionResponse,
224 "session/delete"
225);
226#[cfg(feature = "unstable_session_fork")]
227impl_v2_jsonrpc_request!(
228 v2::ForkSessionRequest,
229 v2::ForkSessionResponse,
230 "session/fork"
231);
232impl_v2_jsonrpc_request!(
233 v2::ResumeSessionRequest,
234 v2::ResumeSessionResponse,
235 "session/resume"
236);
237impl_v2_jsonrpc_request!(
238 v2::CloseSessionRequest,
239 v2::CloseSessionResponse,
240 "session/close"
241);
242impl_v2_jsonrpc_request!(
243 v2::SetSessionConfigOptionRequest,
244 v2::SetSessionConfigOptionResponse,
245 "session/set_config_option"
246);
247impl_v2_jsonrpc_request!(v2::PromptRequest, v2::PromptResponse, "session/prompt");
248#[cfg(feature = "unstable_mcp_over_acp")]
249impl_v2_jsonrpc_request!(v2::MessageMcpRequest, v2::MessageMcpResponse, "mcp/message");
250
251impl_v2_jsonrpc_notification!(v2::CancelRequestNotification, "$/cancel_request");
252impl_v2_jsonrpc_notification!(v2::CancelSessionNotification, "session/cancel");
253#[cfg(feature = "unstable_mcp_over_acp")]
254impl_v2_jsonrpc_notification!(v2::MessageMcpNotification, "mcp/message");
255
256impl_v2_jsonrpc_request!(
257 v2::RequestPermissionRequest,
258 v2::RequestPermissionResponse,
259 "session/request_permission"
260);
261#[cfg(feature = "unstable_elicitation")]
262impl_v2_jsonrpc_request!(
263 v2::CreateElicitationRequest,
264 v2::CreateElicitationResponse,
265 "elicitation/create"
266);
267#[cfg(feature = "unstable_mcp_over_acp")]
268impl_v2_jsonrpc_request!(v2::ConnectMcpRequest, v2::ConnectMcpResponse, "mcp/connect");
269#[cfg(feature = "unstable_mcp_over_acp")]
270impl_v2_jsonrpc_request!(
271 v2::DisconnectMcpRequest,
272 v2::DisconnectMcpResponse,
273 "mcp/disconnect"
274);
275
276impl_v2_jsonrpc_notification!(v2::UpdateSessionNotification, "session/update");
277#[cfg(feature = "unstable_elicitation")]
278impl_v2_jsonrpc_notification!(v2::CompleteElicitationNotification, "elicitation/complete");
279
280impl_jsonrpc_protocol_level_notification_enum!(v2::ProtocolLevelNotification {
281 CancelRequestNotification => "$/cancel_request",
282});
283
284impl_v2_jsonrpc_request_enum!(v2::ClientRequest {
285 InitializeRequest => "initialize",
286 LoginAuthRequest => "auth/login",
287 LogoutAuthRequest => "auth/logout",
288 NewSessionRequest => "session/new",
289 ListSessionsRequest => "session/list",
290 DeleteSessionRequest => "session/delete",
291 #[cfg(feature = "unstable_session_fork")]
292 ForkSessionRequest => "session/fork",
293 ResumeSessionRequest => "session/resume",
294 CloseSessionRequest => "session/close",
295 SetSessionConfigOptionRequest => "session/set_config_option",
296 PromptRequest => "session/prompt",
297 #[cfg(feature = "unstable_mcp_over_acp")]
298 MessageMcpRequest => "mcp/message",
299 [ext] ExtMethodRequest,
300});
301
302impl_v2_jsonrpc_response_enum!(v2::AgentResponse {
303 InitializeResponse => "initialize",
304 LoginAuthResponse => "auth/login",
305 LogoutAuthResponse => "auth/logout",
306 NewSessionResponse => "session/new",
307 ListSessionsResponse => "session/list",
308 DeleteSessionResponse => "session/delete",
309 #[cfg(feature = "unstable_session_fork")]
310 ForkSessionResponse => "session/fork",
311 ResumeSessionResponse => "session/resume",
312 CloseSessionResponse => "session/close",
313 SetSessionConfigOptionResponse => "session/set_config_option",
314 PromptResponse => "session/prompt",
315 #[cfg(feature = "unstable_mcp_over_acp")]
316 MessageMcpResponse => "mcp/message",
317 [ext] ExtMethodResponse,
318});
319
320impl_v2_jsonrpc_notification_enum!(v2::ClientNotification {
321 CancelSessionNotification => "session/cancel",
322 #[cfg(feature = "unstable_mcp_over_acp")]
323 MessageMcpNotification => "mcp/message",
324 [ext] ExtNotification,
325});
326
327impl_v2_jsonrpc_request_enum!(v2::AgentRequest {
328 RequestPermissionRequest => "session/request_permission",
329 #[cfg(feature = "unstable_elicitation")]
330 CreateElicitationRequest => "elicitation/create",
331 #[cfg(feature = "unstable_mcp_over_acp")]
332 ConnectMcpRequest => "mcp/connect",
333 #[cfg(feature = "unstable_mcp_over_acp")]
334 MessageMcpRequest => "mcp/message",
335 #[cfg(feature = "unstable_mcp_over_acp")]
336 DisconnectMcpRequest => "mcp/disconnect",
337 [ext] ExtMethodRequest,
338});
339
340impl_v2_jsonrpc_response_enum!(v2::ClientResponse {
341 RequestPermissionResponse => "session/request_permission",
342 #[cfg(feature = "unstable_elicitation")]
343 CreateElicitationResponse => "elicitation/create",
344 #[cfg(feature = "unstable_mcp_over_acp")]
345 ConnectMcpResponse => "mcp/connect",
346 #[cfg(feature = "unstable_mcp_over_acp")]
347 MessageMcpResponse => "mcp/message",
348 #[cfg(feature = "unstable_mcp_over_acp")]
349 DisconnectMcpResponse => "mcp/disconnect",
350 [ext] ExtMethodResponse,
351});
352
353impl_v2_jsonrpc_notification_enum!(v2::AgentNotification {
354 UpdateSessionNotification => "session/update",
355 #[cfg(feature = "unstable_elicitation")]
356 CompleteElicitationNotification => "elicitation/complete",
357 #[cfg(feature = "unstable_mcp_over_acp")]
358 MessageMcpNotification => "mcp/message",
359 [ext] ExtNotification,
360});