agent_client_protocol_schema/v2/agent.rs
1//! Methods and notifications the agent handles/receives.
2//!
3//! This module defines the Agent trait and all associated types for implementing
4//! an AI coding agent that follows the Agent Client Protocol (ACP).
5
6use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
7
8#[cfg(any(feature = "unstable_auth_methods", feature = "unstable_llm_providers"))]
9use std::collections::HashMap;
10
11use derive_more::{Display, From};
12use schemars::{JsonSchema, Schema};
13use serde::{Deserialize, Serialize};
14use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
15
16use super::{
17 ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, Meta, SessionId,
18};
19use crate::{IntoOption, ProtocolVersion, SkipListener};
20
21#[cfg(feature = "unstable_mcp_over_acp")]
22use super::mcp::{
23 MCP_MESSAGE_METHOD_NAME, MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
24};
25
26#[cfg(feature = "unstable_nes")]
27use super::{
28 AcceptNesNotification, CloseNesRequest, CloseNesResponse, DidChangeDocumentNotification,
29 DidCloseDocumentNotification, DidFocusDocumentNotification, DidOpenDocumentNotification,
30 DidSaveDocumentNotification, NesCapabilities, PositionEncodingKind, RejectNesNotification,
31 StartNesRequest, StartNesResponse, SuggestNesRequest, SuggestNesResponse,
32};
33
34#[cfg(feature = "unstable_nes")]
35use super::{
36 DOCUMENT_DID_CHANGE_METHOD_NAME, DOCUMENT_DID_CLOSE_METHOD_NAME,
37 DOCUMENT_DID_FOCUS_METHOD_NAME, DOCUMENT_DID_OPEN_METHOD_NAME, DOCUMENT_DID_SAVE_METHOD_NAME,
38 NES_ACCEPT_METHOD_NAME, NES_CLOSE_METHOD_NAME, NES_REJECT_METHOD_NAME, NES_START_METHOD_NAME,
39 NES_SUGGEST_METHOD_NAME,
40};
41
42// Initialize
43
44/// Request parameters for the initialize method.
45///
46/// Sent by the client to establish connection and negotiate capabilities.
47///
48/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
49#[serde_as]
50#[skip_serializing_none]
51#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
52#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
53#[serde(rename_all = "camelCase")]
54#[non_exhaustive]
55pub struct InitializeRequest {
56 /// The latest protocol version supported by the client.
57 pub protocol_version: ProtocolVersion,
58 /// Capabilities supported by the client.
59 #[serde(default)]
60 pub capabilities: ClientCapabilities,
61 /// Information about the Client name and version sent to the Agent.
62 ///
63 /// Note: in future versions of the protocol, this will be required.
64 #[serde_as(deserialize_as = "DefaultOnError")]
65 #[schemars(extend("x-deserialize-default-on-error" = true))]
66 #[serde(default)]
67 pub client_info: Option<Implementation>,
68 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
69 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
70 /// these keys.
71 ///
72 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
73 #[serde(rename = "_meta")]
74 pub meta: Option<Meta>,
75}
76
77impl InitializeRequest {
78 /// Builds [`InitializeRequest`] with the required request fields set; optional fields start unset or empty.
79 #[must_use]
80 pub fn new(protocol_version: ProtocolVersion) -> Self {
81 Self {
82 protocol_version,
83 capabilities: ClientCapabilities::default(),
84 client_info: None,
85 meta: None,
86 }
87 }
88
89 /// Capabilities supported by the client.
90 #[must_use]
91 pub fn capabilities(mut self, capabilities: ClientCapabilities) -> Self {
92 self.capabilities = capabilities;
93 self
94 }
95
96 /// Information about the Client name and version sent to the Agent.
97 #[must_use]
98 pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
99 self.client_info = client_info.into_option();
100 self
101 }
102
103 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
104 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
105 /// these keys.
106 ///
107 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
108 #[must_use]
109 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
110 self.meta = meta.into_option();
111 self
112 }
113}
114
115/// Response to the `initialize` method.
116///
117/// Contains the negotiated protocol version and agent capabilities.
118///
119/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
120#[serde_as]
121#[skip_serializing_none]
122#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
123#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
124#[serde(rename_all = "camelCase")]
125#[non_exhaustive]
126pub struct InitializeResponse {
127 /// The protocol version the client specified if supported by the agent,
128 /// or the latest protocol version supported by the agent.
129 ///
130 /// The client should disconnect, if it doesn't support this version.
131 pub protocol_version: ProtocolVersion,
132 /// Capabilities supported by the agent.
133 #[serde(default)]
134 pub capabilities: AgentCapabilities,
135 /// Authentication methods supported by the agent.
136 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
137 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
138 #[serde(default)]
139 pub auth_methods: Vec<AuthMethod>,
140 /// Information about the Agent name and version sent to the Client.
141 ///
142 /// Note: in future versions of the protocol, this will be required.
143 #[serde_as(deserialize_as = "DefaultOnError")]
144 #[schemars(extend("x-deserialize-default-on-error" = true))]
145 #[serde(default)]
146 pub agent_info: Option<Implementation>,
147 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
148 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
149 /// these keys.
150 ///
151 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
152 #[serde(rename = "_meta")]
153 pub meta: Option<Meta>,
154}
155
156impl InitializeResponse {
157 /// Builds [`InitializeResponse`] with the required response fields set; optional fields start unset or empty.
158 #[must_use]
159 pub fn new(protocol_version: ProtocolVersion) -> Self {
160 Self {
161 protocol_version,
162 capabilities: AgentCapabilities::default(),
163 auth_methods: vec![],
164 agent_info: None,
165 meta: None,
166 }
167 }
168
169 /// Capabilities supported by the agent.
170 #[must_use]
171 pub fn capabilities(mut self, capabilities: AgentCapabilities) -> Self {
172 self.capabilities = capabilities;
173 self
174 }
175
176 /// Authentication methods supported by the agent.
177 #[must_use]
178 pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
179 self.auth_methods = auth_methods;
180 self
181 }
182
183 /// Information about the Agent name and version sent to the Client.
184 #[must_use]
185 pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
186 self.agent_info = agent_info.into_option();
187 self
188 }
189
190 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
191 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
192 /// these keys.
193 ///
194 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
195 #[must_use]
196 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
197 self.meta = meta.into_option();
198 self
199 }
200}
201
202/// Metadata about the implementation of the client or agent.
203/// Describes the name and version of an MCP implementation, with an optional
204/// title for UI representation.
205#[skip_serializing_none]
206#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
207#[serde(rename_all = "camelCase")]
208#[non_exhaustive]
209pub struct Implementation {
210 /// Intended for programmatic or logical use, but can be used as a display
211 /// name fallback if title isn’t present.
212 pub name: String,
213 /// Intended for UI and end-user contexts — optimized to be human-readable
214 /// and easily understood.
215 ///
216 /// If not provided, the name should be used for display.
217 pub title: Option<String>,
218 /// Version of the implementation. Can be displayed to the user or used
219 /// for debugging or metrics purposes. (e.g. "1.0.0").
220 pub version: String,
221 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
222 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
223 /// these keys.
224 ///
225 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
226 #[serde(rename = "_meta")]
227 pub meta: Option<Meta>,
228}
229
230impl Implementation {
231 /// Builds [`Implementation`] with the required fields set; optional fields start unset or empty.
232 #[must_use]
233 pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
234 Self {
235 name: name.into(),
236 title: None,
237 version: version.into(),
238 meta: None,
239 }
240 }
241
242 /// Intended for UI and end-user contexts — optimized to be human-readable
243 /// and easily understood.
244 ///
245 /// If not provided, the name should be used for display.
246 #[must_use]
247 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
248 self.title = title.into_option();
249 self
250 }
251
252 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
253 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
254 /// these keys.
255 ///
256 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
257 #[must_use]
258 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
259 self.meta = meta.into_option();
260 self
261 }
262}
263
264// Authentication
265
266/// Request parameters for the authenticate method.
267///
268/// Specifies which authentication method to use.
269#[skip_serializing_none]
270#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
271#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
272#[serde(rename_all = "camelCase")]
273#[non_exhaustive]
274pub struct AuthenticateRequest {
275 /// The ID of the authentication method to use.
276 /// Must be one of the methods advertised in the initialize response.
277 pub method_id: AuthMethodId,
278 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
279 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
280 /// these keys.
281 ///
282 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
283 #[serde(rename = "_meta")]
284 pub meta: Option<Meta>,
285}
286
287impl AuthenticateRequest {
288 /// Builds [`AuthenticateRequest`] with the required request fields set; optional fields start unset or empty.
289 #[must_use]
290 pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
291 Self {
292 method_id: method_id.into(),
293 meta: None,
294 }
295 }
296
297 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
298 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
299 /// these keys.
300 ///
301 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
302 #[must_use]
303 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
304 self.meta = meta.into_option();
305 self
306 }
307}
308
309/// Response to the `authenticate` method.
310#[skip_serializing_none]
311#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
312#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
313#[serde(rename_all = "camelCase")]
314#[non_exhaustive]
315pub struct AuthenticateResponse {
316 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
317 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
318 /// these keys.
319 ///
320 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
321 #[serde(rename = "_meta")]
322 pub meta: Option<Meta>,
323}
324
325impl AuthenticateResponse {
326 /// Builds [`AuthenticateResponse`] with the required response fields set; optional fields start unset or empty.
327 #[must_use]
328 pub fn new() -> Self {
329 Self::default()
330 }
331
332 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
333 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
334 /// these keys.
335 ///
336 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
337 #[must_use]
338 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
339 self.meta = meta.into_option();
340 self
341 }
342}
343
344// Logout
345
346/// Request parameters for the logout method.
347///
348/// Terminates the current authenticated session.
349#[skip_serializing_none]
350#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
351#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
352#[serde(rename_all = "camelCase")]
353#[non_exhaustive]
354pub struct LogoutRequest {
355 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
356 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
357 /// these keys.
358 ///
359 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
360 #[serde(rename = "_meta")]
361 pub meta: Option<Meta>,
362}
363
364impl LogoutRequest {
365 /// Builds [`LogoutRequest`] with the required request fields set; optional fields start unset or empty.
366 #[must_use]
367 pub fn new() -> Self {
368 Self::default()
369 }
370
371 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
372 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
373 /// these keys.
374 ///
375 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
376 #[must_use]
377 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
378 self.meta = meta.into_option();
379 self
380 }
381}
382
383/// Response to the `logout` method.
384#[skip_serializing_none]
385#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
386#[schemars(extend("x-side" = "agent", "x-method" = LOGOUT_METHOD_NAME))]
387#[serde(rename_all = "camelCase")]
388#[non_exhaustive]
389pub struct LogoutResponse {
390 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
391 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
392 /// these keys.
393 ///
394 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
395 #[serde(rename = "_meta")]
396 pub meta: Option<Meta>,
397}
398
399impl LogoutResponse {
400 /// Builds [`LogoutResponse`] with the required response fields set; optional fields start unset or empty.
401 #[must_use]
402 pub fn new() -> Self {
403 Self::default()
404 }
405
406 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
407 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
408 /// these keys.
409 ///
410 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
411 #[must_use]
412 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
413 self.meta = meta.into_option();
414 self
415 }
416}
417
418/// Authentication-related capabilities supported by the agent.
419#[serde_as]
420#[skip_serializing_none]
421#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
422#[serde(rename_all = "camelCase")]
423#[non_exhaustive]
424pub struct AgentAuthCapabilities {
425 /// Whether the agent supports the logout method.
426 ///
427 /// By supplying `{}` it means that the agent supports the logout method.
428 #[serde_as(deserialize_as = "DefaultOnError")]
429 #[schemars(extend("x-deserialize-default-on-error" = true))]
430 #[serde(default)]
431 pub logout: Option<LogoutCapabilities>,
432 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
433 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
434 /// these keys.
435 ///
436 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
437 #[serde(rename = "_meta")]
438 pub meta: Option<Meta>,
439}
440
441impl AgentAuthCapabilities {
442 /// Builds an empty [`AgentAuthCapabilities`]; use builder methods to advertise supported sub-capabilities.
443 #[must_use]
444 pub fn new() -> Self {
445 Self::default()
446 }
447
448 /// Whether the agent supports the logout method.
449 #[must_use]
450 pub fn logout(mut self, logout: impl IntoOption<LogoutCapabilities>) -> Self {
451 self.logout = logout.into_option();
452 self
453 }
454
455 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
456 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
457 /// these keys.
458 ///
459 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
460 #[must_use]
461 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
462 self.meta = meta.into_option();
463 self
464 }
465}
466
467/// Logout capabilities supported by the agent.
468///
469/// By supplying `{}` it means that the agent supports the logout method.
470#[skip_serializing_none]
471#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
472#[non_exhaustive]
473pub struct LogoutCapabilities {
474 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
475 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
476 /// these keys.
477 ///
478 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
479 #[serde(rename = "_meta")]
480 pub meta: Option<Meta>,
481}
482
483impl LogoutCapabilities {
484 /// Builds an empty [`LogoutCapabilities`]; use builder methods to advertise supported sub-capabilities.
485 #[must_use]
486 pub fn new() -> Self {
487 Self::default()
488 }
489
490 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
491 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
492 /// these keys.
493 ///
494 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
495 #[must_use]
496 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
497 self.meta = meta.into_option();
498 self
499 }
500}
501
502/// Typed identifier used for auth method values on the wire.
503#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
504#[serde(transparent)]
505#[from(Arc<str>, String, &'static str)]
506#[non_exhaustive]
507pub struct AuthMethodId(pub Arc<str>);
508
509impl AuthMethodId {
510 /// Wraps a protocol string as a typed [`AuthMethodId`].
511 #[must_use]
512 pub fn new(id: impl Into<Arc<str>>) -> Self {
513 Self(id.into())
514 }
515}
516
517/// Describes an available authentication method.
518///
519/// The `type` field acts as the discriminator in the serialized JSON form.
520#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
521#[serde(tag = "type", rename_all = "snake_case")]
522#[non_exhaustive]
523pub enum AuthMethod {
524 /// **UNSTABLE**
525 ///
526 /// This capability is not part of the spec yet, and may be removed or changed at any point.
527 ///
528 /// User provides a key that the client passes to the agent as an environment variable.
529 #[cfg(feature = "unstable_auth_methods")]
530 EnvVar(AuthMethodEnvVar),
531 /// **UNSTABLE**
532 ///
533 /// This capability is not part of the spec yet, and may be removed or changed at any point.
534 ///
535 /// Client runs an interactive terminal for the user to authenticate via a TUI.
536 #[cfg(feature = "unstable_auth_methods")]
537 Terminal(AuthMethodTerminal),
538 /// Agent handles authentication itself.
539 ///
540 /// The `type` discriminator value is `agent`.
541 Agent(AuthMethodAgent),
542 /// Custom or future authentication method.
543 ///
544 /// Values beginning with `_` are reserved for implementation-specific
545 /// extensions. Unknown values that do not begin with `_` are reserved for
546 /// future ACP variants.
547 ///
548 /// Clients that do not understand this method type should preserve the raw
549 /// payload when storing, replaying, proxying, or forwarding initialization
550 /// data, and otherwise ignore the method or display it generically.
551 #[serde(untagged)]
552 Other(OtherAuthMethod),
553}
554
555impl AuthMethod {
556 /// The unique identifier for this authentication method.
557 #[must_use]
558 pub fn id(&self) -> &AuthMethodId {
559 match self {
560 Self::Agent(a) => &a.id,
561 Self::Other(a) => &a.id,
562 #[cfg(feature = "unstable_auth_methods")]
563 Self::EnvVar(e) => &e.id,
564 #[cfg(feature = "unstable_auth_methods")]
565 Self::Terminal(t) => &t.id,
566 }
567 }
568
569 /// The human-readable name of this authentication method.
570 #[must_use]
571 pub fn name(&self) -> &str {
572 match self {
573 Self::Agent(a) => &a.name,
574 Self::Other(a) => &a.name,
575 #[cfg(feature = "unstable_auth_methods")]
576 Self::EnvVar(e) => &e.name,
577 #[cfg(feature = "unstable_auth_methods")]
578 Self::Terminal(t) => &t.name,
579 }
580 }
581
582 /// Optional description providing more details about this authentication method.
583 #[must_use]
584 pub fn description(&self) -> Option<&str> {
585 match self {
586 Self::Agent(a) => a.description.as_deref(),
587 Self::Other(a) => a.description.as_deref(),
588 #[cfg(feature = "unstable_auth_methods")]
589 Self::EnvVar(e) => e.description.as_deref(),
590 #[cfg(feature = "unstable_auth_methods")]
591 Self::Terminal(t) => t.description.as_deref(),
592 }
593 }
594
595 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
596 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
597 /// these keys.
598 ///
599 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
600 #[must_use]
601 pub fn meta(&self) -> Option<&Meta> {
602 match self {
603 Self::Agent(a) => a.meta.as_ref(),
604 Self::Other(a) => a.meta.as_ref(),
605 #[cfg(feature = "unstable_auth_methods")]
606 Self::EnvVar(e) => e.meta.as_ref(),
607 #[cfg(feature = "unstable_auth_methods")]
608 Self::Terminal(t) => t.meta.as_ref(),
609 }
610 }
611}
612
613/// Custom or future authentication method payload.
614#[skip_serializing_none]
615#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
616#[schemars(inline)]
617#[schemars(transform = other_auth_method_schema)]
618#[serde(rename_all = "camelCase")]
619#[non_exhaustive]
620pub struct OtherAuthMethod {
621 /// Custom or future authentication method type.
622 ///
623 /// Values beginning with `_` are reserved for implementation-specific
624 /// extensions. Unknown values that do not begin with `_` are reserved for
625 /// future ACP variants.
626 #[serde(rename = "type")]
627 pub type_: String,
628 /// Unique identifier for this authentication method.
629 pub id: AuthMethodId,
630 /// Human-readable name of the authentication method.
631 pub name: String,
632 /// Optional description providing more details about this authentication method.
633 pub description: Option<String>,
634 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
635 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
636 /// these keys.
637 ///
638 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
639 #[serde(rename = "_meta")]
640 pub meta: Option<Meta>,
641 /// Additional fields from the unknown authentication method payload.
642 #[serde(flatten)]
643 pub fields: BTreeMap<String, serde_json::Value>,
644}
645
646impl OtherAuthMethod {
647 /// Builds [`OtherAuthMethod`] from an unknown discriminator and preserves the remaining extension fields.
648 #[must_use]
649 pub fn new(
650 type_: impl Into<String>,
651 id: impl Into<AuthMethodId>,
652 name: impl Into<String>,
653 mut fields: BTreeMap<String, serde_json::Value>,
654 ) -> Self {
655 fields.remove("type");
656 fields.remove("id");
657 fields.remove("name");
658 fields.remove("description");
659 fields.remove("_meta");
660 Self {
661 type_: type_.into(),
662 id: id.into(),
663 name: name.into(),
664 description: None,
665 meta: None,
666 fields,
667 }
668 }
669
670 /// Optional description providing more details about this authentication method.
671 #[must_use]
672 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
673 self.description = description.into_option();
674 self
675 }
676
677 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
678 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
679 /// these keys.
680 ///
681 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
682 #[must_use]
683 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
684 self.meta = meta.into_option();
685 self
686 }
687}
688
689impl<'de> Deserialize<'de> for OtherAuthMethod {
690 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
691 where
692 D: serde::Deserializer<'de>,
693 {
694 #[derive(Deserialize)]
695 #[serde(rename_all = "camelCase")]
696 struct RawOtherAuthMethod {
697 #[serde(rename = "type")]
698 type_: String,
699 id: AuthMethodId,
700 name: String,
701 description: Option<String>,
702 #[serde(rename = "_meta")]
703 meta: Option<Meta>,
704 #[serde(flatten)]
705 fields: BTreeMap<String, serde_json::Value>,
706 }
707
708 let raw = RawOtherAuthMethod::deserialize(deserializer)?;
709 if is_known_auth_method_type(&raw.type_) {
710 return Err(serde::de::Error::custom(format!(
711 "known authentication method `{}` did not match its schema",
712 raw.type_
713 )));
714 }
715
716 Ok(Self {
717 type_: raw.type_,
718 id: raw.id,
719 name: raw.name,
720 description: raw.description,
721 meta: raw.meta,
722 fields: raw.fields,
723 })
724 }
725}
726
727fn is_known_auth_method_type(type_: &str) -> bool {
728 match type_ {
729 "agent" => true,
730 #[cfg(feature = "unstable_auth_methods")]
731 "env_var" | "terminal" => true,
732 _ => false,
733 }
734}
735
736fn other_auth_method_schema(schema: &mut Schema) {
737 super::schema_util::reject_known_string_discriminators(
738 schema,
739 "type",
740 &[
741 "agent",
742 #[cfg(feature = "unstable_auth_methods")]
743 "env_var",
744 #[cfg(feature = "unstable_auth_methods")]
745 "terminal",
746 ],
747 );
748}
749
750/// Agent handles authentication itself.
751///
752/// The `type` discriminator value is `agent`.
753#[skip_serializing_none]
754#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
755#[serde(rename_all = "camelCase")]
756#[non_exhaustive]
757pub struct AuthMethodAgent {
758 /// Unique identifier for this authentication method.
759 pub id: AuthMethodId,
760 /// Human-readable name of the authentication method.
761 pub name: String,
762 /// Optional description providing more details about this authentication method.
763 pub description: Option<String>,
764 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
765 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
766 /// these keys.
767 ///
768 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
769 #[serde(rename = "_meta")]
770 pub meta: Option<Meta>,
771}
772
773impl AuthMethodAgent {
774 /// Builds [`AuthMethodAgent`] with the required fields set; optional fields start unset or empty.
775 #[must_use]
776 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
777 Self {
778 id: id.into(),
779 name: name.into(),
780 description: None,
781 meta: None,
782 }
783 }
784
785 /// Optional description providing more details about this authentication method.
786 #[must_use]
787 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
788 self.description = description.into_option();
789 self
790 }
791
792 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
793 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
794 /// these keys.
795 ///
796 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
797 #[must_use]
798 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
799 self.meta = meta.into_option();
800 self
801 }
802}
803
804/// **UNSTABLE**
805///
806/// This capability is not part of the spec yet, and may be removed or changed at any point.
807///
808/// Environment variable authentication method.
809///
810/// The user provides credentials that the client passes to the agent as environment variables.
811#[cfg(feature = "unstable_auth_methods")]
812#[skip_serializing_none]
813#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
814#[serde(rename_all = "camelCase")]
815#[non_exhaustive]
816pub struct AuthMethodEnvVar {
817 /// Unique identifier for this authentication method.
818 pub id: AuthMethodId,
819 /// Human-readable name of the authentication method.
820 pub name: String,
821 /// Optional description providing more details about this authentication method.
822 pub description: Option<String>,
823 /// The environment variables the client should set.
824 pub vars: Vec<AuthEnvVar>,
825 /// Optional link to a page where the user can obtain their credentials.
826 pub link: Option<String>,
827 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
828 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
829 /// these keys.
830 ///
831 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
832 #[serde(rename = "_meta")]
833 pub meta: Option<Meta>,
834}
835
836#[cfg(feature = "unstable_auth_methods")]
837impl AuthMethodEnvVar {
838 /// Builds [`AuthMethodEnvVar`] with the required fields set; optional fields start unset or empty.
839 #[must_use]
840 pub fn new(
841 id: impl Into<AuthMethodId>,
842 name: impl Into<String>,
843 vars: Vec<AuthEnvVar>,
844 ) -> Self {
845 Self {
846 id: id.into(),
847 name: name.into(),
848 description: None,
849 vars,
850 link: None,
851 meta: None,
852 }
853 }
854
855 /// Optional link to a page where the user can obtain their credentials.
856 #[must_use]
857 pub fn link(mut self, link: impl IntoOption<String>) -> Self {
858 self.link = link.into_option();
859 self
860 }
861
862 /// Optional description providing more details about this authentication method.
863 #[must_use]
864 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
865 self.description = description.into_option();
866 self
867 }
868
869 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
870 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
871 /// these keys.
872 ///
873 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
874 #[must_use]
875 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
876 self.meta = meta.into_option();
877 self
878 }
879}
880
881/// **UNSTABLE**
882///
883/// This capability is not part of the spec yet, and may be removed or changed at any point.
884///
885/// Describes a single environment variable for an [`AuthMethodEnvVar`] authentication method.
886#[cfg(feature = "unstable_auth_methods")]
887#[skip_serializing_none]
888#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
889#[serde(rename_all = "camelCase")]
890#[non_exhaustive]
891pub struct AuthEnvVar {
892 /// The environment variable name (e.g. `"OPENAI_API_KEY"`).
893 pub name: String,
894 /// Human-readable label for this variable, displayed in client UI.
895 pub label: Option<String>,
896 /// Whether this value is a secret (e.g. API key, token).
897 /// Clients should use a password-style input for secret vars.
898 ///
899 /// Defaults to `true`.
900 #[serde(default = "default_true", skip_serializing_if = "is_true")]
901 #[schemars(extend("default" = true))]
902 pub secret: bool,
903 /// Whether this variable is optional.
904 ///
905 /// Defaults to `false`.
906 #[serde(default, skip_serializing_if = "is_false")]
907 #[schemars(extend("default" = false))]
908 pub optional: bool,
909 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
910 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
911 /// these keys.
912 ///
913 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
914 #[serde(rename = "_meta")]
915 pub meta: Option<Meta>,
916}
917
918#[cfg(feature = "unstable_auth_methods")]
919fn default_true() -> bool {
920 true
921}
922
923#[cfg(feature = "unstable_auth_methods")]
924#[expect(clippy::trivially_copy_pass_by_ref)]
925fn is_true(v: &bool) -> bool {
926 *v
927}
928
929#[cfg(feature = "unstable_auth_methods")]
930#[expect(clippy::trivially_copy_pass_by_ref)]
931fn is_false(v: &bool) -> bool {
932 !*v
933}
934
935#[cfg(feature = "unstable_auth_methods")]
936impl AuthEnvVar {
937 /// Creates an auth environment variable prompt with `secret` enabled and `optional` disabled.
938 #[must_use]
939 pub fn new(name: impl Into<String>) -> Self {
940 Self {
941 name: name.into(),
942 label: None,
943 secret: true,
944 optional: false,
945 meta: None,
946 }
947 }
948
949 /// Human-readable label for this variable, displayed in client UI.
950 #[must_use]
951 pub fn label(mut self, label: impl IntoOption<String>) -> Self {
952 self.label = label.into_option();
953 self
954 }
955
956 /// Whether this value is a secret (e.g. API key, token).
957 /// Clients should use a password-style input for secret vars.
958 #[must_use]
959 pub fn secret(mut self, secret: bool) -> Self {
960 self.secret = secret;
961 self
962 }
963
964 /// Whether this variable is optional.
965 #[must_use]
966 pub fn optional(mut self, optional: bool) -> Self {
967 self.optional = optional;
968 self
969 }
970
971 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
972 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
973 /// these keys.
974 ///
975 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
976 #[must_use]
977 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
978 self.meta = meta.into_option();
979 self
980 }
981}
982
983/// **UNSTABLE**
984///
985/// This capability is not part of the spec yet, and may be removed or changed at any point.
986///
987/// Terminal-based authentication method.
988///
989/// The client runs an interactive terminal for the user to authenticate via a TUI.
990#[cfg(feature = "unstable_auth_methods")]
991#[skip_serializing_none]
992#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
993#[serde(rename_all = "camelCase")]
994#[non_exhaustive]
995pub struct AuthMethodTerminal {
996 /// Unique identifier for this authentication method.
997 pub id: AuthMethodId,
998 /// Human-readable name of the authentication method.
999 pub name: String,
1000 /// Optional description providing more details about this authentication method.
1001 pub description: Option<String>,
1002 /// Additional arguments to pass when running the agent binary for terminal auth.
1003 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1004 pub args: Vec<String>,
1005 /// Additional environment variables to set when running the agent binary for terminal auth.
1006 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
1007 pub env: HashMap<String, String>,
1008 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1009 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1010 /// these keys.
1011 ///
1012 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1013 #[serde(rename = "_meta")]
1014 pub meta: Option<Meta>,
1015}
1016
1017#[cfg(feature = "unstable_auth_methods")]
1018impl AuthMethodTerminal {
1019 /// Builds [`AuthMethodTerminal`] with the required fields set; optional fields start unset or empty.
1020 #[must_use]
1021 pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
1022 Self {
1023 id: id.into(),
1024 name: name.into(),
1025 description: None,
1026 args: Vec::new(),
1027 env: HashMap::new(),
1028 meta: None,
1029 }
1030 }
1031
1032 /// Additional arguments to pass when running the agent binary for terminal auth.
1033 #[must_use]
1034 pub fn args(mut self, args: Vec<String>) -> Self {
1035 self.args = args;
1036 self
1037 }
1038
1039 /// Additional environment variables to set when running the agent binary for terminal auth.
1040 #[must_use]
1041 pub fn env(mut self, env: HashMap<String, String>) -> Self {
1042 self.env = env;
1043 self
1044 }
1045
1046 /// Optional description providing more details about this authentication method.
1047 #[must_use]
1048 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1049 self.description = description.into_option();
1050 self
1051 }
1052
1053 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1054 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1055 /// these keys.
1056 ///
1057 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1058 #[must_use]
1059 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1060 self.meta = meta.into_option();
1061 self
1062 }
1063}
1064
1065// New session
1066
1067/// Request parameters for creating a new session.
1068///
1069/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
1070#[skip_serializing_none]
1071#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1072#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1073#[serde(rename_all = "camelCase")]
1074#[non_exhaustive]
1075pub struct NewSessionRequest {
1076 /// The working directory for this session. Must be an absolute path.
1077 pub cwd: PathBuf,
1078 /// Additional workspace roots for this session. Each path must be absolute.
1079 ///
1080 /// These expand the session's workspace scope without changing `cwd`, which
1081 /// remains the base for relative paths. When omitted or empty, no
1082 /// additional roots are activated for the new session.
1083 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1084 pub additional_directories: Vec<PathBuf>,
1085 /// List of MCP (Model Context Protocol) servers the agent should connect to.
1086 pub mcp_servers: Vec<McpServer>,
1087 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1088 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1089 /// these keys.
1090 ///
1091 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1092 #[serde(rename = "_meta")]
1093 pub meta: Option<Meta>,
1094}
1095
1096impl NewSessionRequest {
1097 /// Builds [`NewSessionRequest`] with the required request fields set; optional fields start unset or empty.
1098 #[must_use]
1099 pub fn new(cwd: impl Into<PathBuf>) -> Self {
1100 Self {
1101 cwd: cwd.into(),
1102 additional_directories: vec![],
1103 mcp_servers: vec![],
1104 meta: None,
1105 }
1106 }
1107
1108 /// Additional workspace roots for this session. Each path must be absolute.
1109 #[must_use]
1110 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1111 self.additional_directories = additional_directories;
1112 self
1113 }
1114
1115 /// List of MCP (Model Context Protocol) servers the agent should connect to.
1116 #[must_use]
1117 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1118 self.mcp_servers = mcp_servers;
1119 self
1120 }
1121
1122 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1123 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1124 /// these keys.
1125 ///
1126 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1127 #[must_use]
1128 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1129 self.meta = meta.into_option();
1130 self
1131 }
1132}
1133
1134/// Response from creating a new session.
1135///
1136/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
1137#[serde_as]
1138#[skip_serializing_none]
1139#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1140#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
1141#[serde(rename_all = "camelCase")]
1142#[non_exhaustive]
1143pub struct NewSessionResponse {
1144 /// Unique identifier for the created session.
1145 ///
1146 /// Used in all subsequent requests for this conversation.
1147 pub session_id: SessionId,
1148 /// Initial session configuration options if supported by the Agent.
1149 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1150 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1151 #[serde(default)]
1152 pub config_options: Option<Vec<SessionConfigOption>>,
1153 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1154 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1155 /// these keys.
1156 ///
1157 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1158 #[serde(rename = "_meta")]
1159 pub meta: Option<Meta>,
1160}
1161
1162impl NewSessionResponse {
1163 /// Builds [`NewSessionResponse`] with the required response fields set; optional fields start unset or empty.
1164 #[must_use]
1165 pub fn new(session_id: impl Into<SessionId>) -> Self {
1166 Self {
1167 session_id: session_id.into(),
1168 config_options: None,
1169 meta: None,
1170 }
1171 }
1172
1173 /// Initial session configuration options if supported by the Agent.
1174 #[must_use]
1175 pub fn config_options(
1176 mut self,
1177 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1178 ) -> Self {
1179 self.config_options = config_options.into_option();
1180 self
1181 }
1182
1183 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1184 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1185 /// these keys.
1186 ///
1187 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1188 #[must_use]
1189 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1190 self.meta = meta.into_option();
1191 self
1192 }
1193}
1194
1195// Load session
1196
1197/// Request parameters for loading an existing session.
1198///
1199/// Only available if the Agent supports the `session.load` capability.
1200///
1201/// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
1202#[skip_serializing_none]
1203#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1204#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1205#[serde(rename_all = "camelCase")]
1206#[non_exhaustive]
1207pub struct LoadSessionRequest {
1208 /// List of MCP servers to connect to for this session.
1209 pub mcp_servers: Vec<McpServer>,
1210 /// The working directory for this session.
1211 pub cwd: PathBuf,
1212 /// Additional workspace roots to activate for this session. Each path must be absolute.
1213 ///
1214 /// When omitted or empty, no additional roots are activated. When non-empty,
1215 /// this is the complete resulting additional-root list for the loaded
1216 /// session. It may differ from any previously used or reported list as long as
1217 /// the request `cwd` matches the session's `cwd`.
1218 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1219 pub additional_directories: Vec<PathBuf>,
1220 /// The ID of the session to load.
1221 pub session_id: SessionId,
1222 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1223 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1224 /// these keys.
1225 ///
1226 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1227 #[serde(rename = "_meta")]
1228 pub meta: Option<Meta>,
1229}
1230
1231impl LoadSessionRequest {
1232 /// Builds [`LoadSessionRequest`] with the required request fields set; optional fields start unset or empty.
1233 #[must_use]
1234 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1235 Self {
1236 mcp_servers: vec![],
1237 cwd: cwd.into(),
1238 additional_directories: vec![],
1239 session_id: session_id.into(),
1240 meta: None,
1241 }
1242 }
1243
1244 /// Additional workspace roots to activate for this session. Each path must be absolute.
1245 #[must_use]
1246 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1247 self.additional_directories = additional_directories;
1248 self
1249 }
1250
1251 /// List of MCP servers to connect to for this session.
1252 #[must_use]
1253 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1254 self.mcp_servers = mcp_servers;
1255 self
1256 }
1257
1258 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1259 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1260 /// these keys.
1261 ///
1262 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1263 #[must_use]
1264 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1265 self.meta = meta.into_option();
1266 self
1267 }
1268}
1269
1270/// Response from loading an existing session.
1271#[serde_as]
1272#[skip_serializing_none]
1273#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1274#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
1275#[serde(rename_all = "camelCase")]
1276#[non_exhaustive]
1277pub struct LoadSessionResponse {
1278 /// Initial session configuration options if supported by the Agent.
1279 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1280 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1281 #[serde(default)]
1282 pub config_options: Option<Vec<SessionConfigOption>>,
1283 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1284 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1285 /// these keys.
1286 ///
1287 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1288 #[serde(rename = "_meta")]
1289 pub meta: Option<Meta>,
1290}
1291
1292impl LoadSessionResponse {
1293 /// Builds [`LoadSessionResponse`] with the required response fields set; optional fields start unset or empty.
1294 #[must_use]
1295 pub fn new() -> Self {
1296 Self::default()
1297 }
1298
1299 /// Initial session configuration options if supported by the Agent.
1300 #[must_use]
1301 pub fn config_options(
1302 mut self,
1303 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1304 ) -> Self {
1305 self.config_options = config_options.into_option();
1306 self
1307 }
1308
1309 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1310 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1311 /// these keys.
1312 ///
1313 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1314 #[must_use]
1315 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1316 self.meta = meta.into_option();
1317 self
1318 }
1319}
1320
1321// Fork session
1322
1323/// **UNSTABLE**
1324///
1325/// This capability is not part of the spec yet, and may be removed or changed at any point.
1326///
1327/// Request parameters for forking an existing session.
1328///
1329/// Creates a new session based on the context of an existing one, allowing
1330/// operations like generating summaries without affecting the original session's history.
1331///
1332/// Only available if the Agent supports the `session.fork` capability.
1333#[cfg(feature = "unstable_session_fork")]
1334#[skip_serializing_none]
1335#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1336#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1337#[serde(rename_all = "camelCase")]
1338#[non_exhaustive]
1339pub struct ForkSessionRequest {
1340 /// The ID of the session to fork.
1341 pub session_id: SessionId,
1342 /// The working directory for this session.
1343 pub cwd: PathBuf,
1344 /// Additional workspace roots to activate for this session. Each path must be absolute.
1345 ///
1346 /// When omitted or empty, no additional roots are activated. When non-empty,
1347 /// this is the complete resulting additional-root list for the forked
1348 /// session.
1349 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1350 pub additional_directories: Vec<PathBuf>,
1351 /// List of MCP servers to connect to for this session.
1352 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1353 pub mcp_servers: Vec<McpServer>,
1354 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1355 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1356 /// these keys.
1357 ///
1358 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1359 #[serde(rename = "_meta")]
1360 pub meta: Option<Meta>,
1361}
1362
1363#[cfg(feature = "unstable_session_fork")]
1364impl ForkSessionRequest {
1365 /// Builds [`ForkSessionRequest`] with the required request fields set; optional fields start unset or empty.
1366 #[must_use]
1367 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1368 Self {
1369 session_id: session_id.into(),
1370 cwd: cwd.into(),
1371 additional_directories: vec![],
1372 mcp_servers: vec![],
1373 meta: None,
1374 }
1375 }
1376
1377 /// Additional workspace roots to activate for this session. Each path must be absolute.
1378 #[must_use]
1379 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1380 self.additional_directories = additional_directories;
1381 self
1382 }
1383
1384 /// List of MCP servers to connect to for this session.
1385 #[must_use]
1386 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1387 self.mcp_servers = mcp_servers;
1388 self
1389 }
1390
1391 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1392 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1393 /// these keys.
1394 ///
1395 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1396 #[must_use]
1397 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1398 self.meta = meta.into_option();
1399 self
1400 }
1401}
1402
1403/// **UNSTABLE**
1404///
1405/// This capability is not part of the spec yet, and may be removed or changed at any point.
1406///
1407/// Response from forking an existing session.
1408#[cfg(feature = "unstable_session_fork")]
1409#[serde_as]
1410#[skip_serializing_none]
1411#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1412#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1413#[serde(rename_all = "camelCase")]
1414#[non_exhaustive]
1415pub struct ForkSessionResponse {
1416 /// Unique identifier for the newly created forked session.
1417 pub session_id: SessionId,
1418 /// Initial session configuration options if supported by the Agent.
1419 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1420 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1421 #[serde(default)]
1422 pub config_options: Option<Vec<SessionConfigOption>>,
1423 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1424 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1425 /// these keys.
1426 ///
1427 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1428 #[serde(rename = "_meta")]
1429 pub meta: Option<Meta>,
1430}
1431
1432#[cfg(feature = "unstable_session_fork")]
1433impl ForkSessionResponse {
1434 /// Builds [`ForkSessionResponse`] with the required response fields set; optional fields start unset or empty.
1435 #[must_use]
1436 pub fn new(session_id: impl Into<SessionId>) -> Self {
1437 Self {
1438 session_id: session_id.into(),
1439 config_options: None,
1440 meta: None,
1441 }
1442 }
1443
1444 /// Initial session configuration options if supported by the Agent.
1445 #[must_use]
1446 pub fn config_options(
1447 mut self,
1448 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1449 ) -> Self {
1450 self.config_options = config_options.into_option();
1451 self
1452 }
1453
1454 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1455 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1456 /// these keys.
1457 ///
1458 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1459 #[must_use]
1460 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1461 self.meta = meta.into_option();
1462 self
1463 }
1464}
1465
1466// Resume session
1467
1468/// Request parameters for resuming an existing session.
1469///
1470/// Resumes an existing session without returning previous messages (unlike `session/load`).
1471/// This is useful for agents that can resume sessions but don't implement full session loading.
1472///
1473/// Only available if the Agent supports the `session.resume` capability.
1474#[skip_serializing_none]
1475#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1476#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1477#[serde(rename_all = "camelCase")]
1478#[non_exhaustive]
1479pub struct ResumeSessionRequest {
1480 /// The ID of the session to resume.
1481 pub session_id: SessionId,
1482 /// The working directory for this session.
1483 pub cwd: PathBuf,
1484 /// Additional workspace roots to activate for this session. Each path must be absolute.
1485 ///
1486 /// When omitted or empty, no additional roots are activated. When non-empty,
1487 /// this is the complete resulting additional-root list for the resumed
1488 /// session. It may differ from any previously used or reported list as long as
1489 /// the request `cwd` matches the session's `cwd`.
1490 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1491 pub additional_directories: Vec<PathBuf>,
1492 /// List of MCP servers to connect to for this session.
1493 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1494 pub mcp_servers: Vec<McpServer>,
1495 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1496 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1497 /// these keys.
1498 ///
1499 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1500 #[serde(rename = "_meta")]
1501 pub meta: Option<Meta>,
1502}
1503
1504impl ResumeSessionRequest {
1505 /// Builds [`ResumeSessionRequest`] with the required request fields set; optional fields start unset or empty.
1506 #[must_use]
1507 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1508 Self {
1509 session_id: session_id.into(),
1510 cwd: cwd.into(),
1511 additional_directories: vec![],
1512 mcp_servers: vec![],
1513 meta: None,
1514 }
1515 }
1516
1517 /// Additional workspace roots to activate for this session. Each path must be absolute.
1518 #[must_use]
1519 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1520 self.additional_directories = additional_directories;
1521 self
1522 }
1523
1524 /// List of MCP servers to connect to for this session.
1525 #[must_use]
1526 pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1527 self.mcp_servers = mcp_servers;
1528 self
1529 }
1530
1531 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1532 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1533 /// these keys.
1534 ///
1535 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1536 #[must_use]
1537 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1538 self.meta = meta.into_option();
1539 self
1540 }
1541}
1542
1543/// Response from resuming an existing session.
1544#[serde_as]
1545#[skip_serializing_none]
1546#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1547#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1548#[serde(rename_all = "camelCase")]
1549#[non_exhaustive]
1550pub struct ResumeSessionResponse {
1551 /// Initial session configuration options if supported by the Agent.
1552 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1553 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1554 #[serde(default)]
1555 pub config_options: Option<Vec<SessionConfigOption>>,
1556 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1557 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1558 /// these keys.
1559 ///
1560 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1561 #[serde(rename = "_meta")]
1562 pub meta: Option<Meta>,
1563}
1564
1565impl ResumeSessionResponse {
1566 /// Builds [`ResumeSessionResponse`] with the required response fields set; optional fields start unset or empty.
1567 #[must_use]
1568 pub fn new() -> Self {
1569 Self::default()
1570 }
1571
1572 /// Initial session configuration options if supported by the Agent.
1573 #[must_use]
1574 pub fn config_options(
1575 mut self,
1576 config_options: impl IntoOption<Vec<SessionConfigOption>>,
1577 ) -> Self {
1578 self.config_options = config_options.into_option();
1579 self
1580 }
1581
1582 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1583 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1584 /// these keys.
1585 ///
1586 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1587 #[must_use]
1588 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1589 self.meta = meta.into_option();
1590 self
1591 }
1592}
1593
1594// Close session
1595
1596/// Request parameters for closing an active session.
1597///
1598/// If supported, the agent **must** cancel any ongoing work related to the session
1599/// (treat it as if `session/cancel` was called) and then free up any resources
1600/// associated with the session.
1601///
1602/// Only available if the Agent supports the `session.close` capability.
1603#[skip_serializing_none]
1604#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1605#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1606#[serde(rename_all = "camelCase")]
1607#[non_exhaustive]
1608pub struct CloseSessionRequest {
1609 /// The ID of the session to close.
1610 pub session_id: SessionId,
1611 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1612 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1613 /// these keys.
1614 ///
1615 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1616 #[serde(rename = "_meta")]
1617 pub meta: Option<Meta>,
1618}
1619
1620impl CloseSessionRequest {
1621 /// Builds [`CloseSessionRequest`] with the required request fields set; optional fields start unset or empty.
1622 #[must_use]
1623 pub fn new(session_id: impl Into<SessionId>) -> Self {
1624 Self {
1625 session_id: session_id.into(),
1626 meta: None,
1627 }
1628 }
1629
1630 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1631 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1632 /// these keys.
1633 ///
1634 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1635 #[must_use]
1636 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1637 self.meta = meta.into_option();
1638 self
1639 }
1640}
1641
1642/// Response from closing a session.
1643#[skip_serializing_none]
1644#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1645#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CLOSE_METHOD_NAME))]
1646#[serde(rename_all = "camelCase")]
1647#[non_exhaustive]
1648pub struct CloseSessionResponse {
1649 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1650 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1651 /// these keys.
1652 ///
1653 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1654 #[serde(rename = "_meta")]
1655 pub meta: Option<Meta>,
1656}
1657
1658impl CloseSessionResponse {
1659 /// Builds [`CloseSessionResponse`] with the required response fields set; optional fields start unset or empty.
1660 #[must_use]
1661 pub fn new() -> Self {
1662 Self::default()
1663 }
1664
1665 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1666 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1667 /// these keys.
1668 ///
1669 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1670 #[must_use]
1671 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1672 self.meta = meta.into_option();
1673 self
1674 }
1675}
1676
1677// List sessions
1678
1679/// Request parameters for listing existing sessions.
1680///
1681/// Only available if the Agent supports the `session.list` capability.
1682#[skip_serializing_none]
1683#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1684#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1685#[serde(rename_all = "camelCase")]
1686#[non_exhaustive]
1687pub struct ListSessionsRequest {
1688 /// Filter sessions by working directory. Must be an absolute path.
1689 pub cwd: Option<PathBuf>,
1690 /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
1691 pub cursor: Option<String>,
1692 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1693 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1694 /// these keys.
1695 ///
1696 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1697 #[serde(rename = "_meta")]
1698 pub meta: Option<Meta>,
1699}
1700
1701impl ListSessionsRequest {
1702 /// Builds [`ListSessionsRequest`] with the required request fields set; optional fields start unset or empty.
1703 #[must_use]
1704 pub fn new() -> Self {
1705 Self::default()
1706 }
1707
1708 /// Filter sessions by working directory. Must be an absolute path.
1709 #[must_use]
1710 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1711 self.cwd = cwd.into_option();
1712 self
1713 }
1714
1715 /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
1716 #[must_use]
1717 pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1718 self.cursor = cursor.into_option();
1719 self
1720 }
1721
1722 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1723 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1724 /// these keys.
1725 ///
1726 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1727 #[must_use]
1728 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1729 self.meta = meta.into_option();
1730 self
1731 }
1732}
1733
1734/// Response from listing sessions.
1735#[serde_as]
1736#[skip_serializing_none]
1737#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1738#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1739#[serde(rename_all = "camelCase")]
1740#[non_exhaustive]
1741pub struct ListSessionsResponse {
1742 /// Array of session information objects
1743 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1744 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1745 pub sessions: Vec<SessionInfo>,
1746 /// Opaque cursor token. If present, pass this in the next request's cursor parameter
1747 /// to fetch the next page. If absent, there are no more results.
1748 pub next_cursor: Option<String>,
1749 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1750 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1751 /// these keys.
1752 ///
1753 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1754 #[serde(rename = "_meta")]
1755 pub meta: Option<Meta>,
1756}
1757
1758impl ListSessionsResponse {
1759 /// Builds [`ListSessionsResponse`] with the required response fields set; optional fields start unset or empty.
1760 #[must_use]
1761 pub fn new(sessions: Vec<SessionInfo>) -> Self {
1762 Self {
1763 sessions,
1764 next_cursor: None,
1765 meta: None,
1766 }
1767 }
1768
1769 /// Sets or clears the optional `nextCursor` field.
1770 #[must_use]
1771 pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1772 self.next_cursor = next_cursor.into_option();
1773 self
1774 }
1775
1776 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1777 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1778 /// these keys.
1779 ///
1780 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1781 #[must_use]
1782 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1783 self.meta = meta.into_option();
1784 self
1785 }
1786}
1787
1788// Delete session
1789
1790/// Request parameters for deleting an existing session from `session/list`.
1791///
1792/// Only available if the Agent supports the `session.delete` capability.
1793#[skip_serializing_none]
1794#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1795#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1796#[serde(rename_all = "camelCase")]
1797#[non_exhaustive]
1798pub struct DeleteSessionRequest {
1799 /// The ID of the session to delete.
1800 pub session_id: SessionId,
1801 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1802 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1803 /// these keys.
1804 ///
1805 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1806 #[serde(rename = "_meta")]
1807 pub meta: Option<Meta>,
1808}
1809
1810impl DeleteSessionRequest {
1811 /// Builds [`DeleteSessionRequest`] with the required request fields set; optional fields start unset or empty.
1812 #[must_use]
1813 pub fn new(session_id: impl Into<SessionId>) -> Self {
1814 Self {
1815 session_id: session_id.into(),
1816 meta: None,
1817 }
1818 }
1819
1820 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1821 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1822 /// these keys.
1823 ///
1824 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1825 #[must_use]
1826 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1827 self.meta = meta.into_option();
1828 self
1829 }
1830}
1831
1832/// Response from deleting a session.
1833#[skip_serializing_none]
1834#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1835#[schemars(extend("x-side" = "agent", "x-method" = SESSION_DELETE_METHOD_NAME))]
1836#[serde(rename_all = "camelCase")]
1837#[non_exhaustive]
1838pub struct DeleteSessionResponse {
1839 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1840 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1841 /// these keys.
1842 ///
1843 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1844 #[serde(rename = "_meta")]
1845 pub meta: Option<Meta>,
1846}
1847
1848impl DeleteSessionResponse {
1849 /// Builds [`DeleteSessionResponse`] with the required response fields set; optional fields start unset or empty.
1850 #[must_use]
1851 pub fn new() -> Self {
1852 Self::default()
1853 }
1854
1855 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1856 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1857 /// these keys.
1858 ///
1859 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1860 #[must_use]
1861 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1862 self.meta = meta.into_option();
1863 self
1864 }
1865}
1866
1867/// Information about a session returned by session/list
1868#[serde_as]
1869#[skip_serializing_none]
1870#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1871#[serde(rename_all = "camelCase")]
1872#[non_exhaustive]
1873pub struct SessionInfo {
1874 /// Unique identifier for the session
1875 pub session_id: SessionId,
1876 /// The working directory for this session. Must be an absolute path.
1877 pub cwd: PathBuf,
1878 /// Additional workspace roots reported for this session. Each path must be absolute.
1879 ///
1880 /// When present, this is the complete ordered additional-root list reported
1881 /// by the Agent. Omitted and empty values are equivalent: the response
1882 /// reports no additional roots.
1883 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1884 pub additional_directories: Vec<PathBuf>,
1885
1886 /// Human-readable title for the session
1887 #[serde_as(deserialize_as = "DefaultOnError")]
1888 #[schemars(extend("x-deserialize-default-on-error" = true))]
1889 #[serde(default)]
1890 pub title: Option<String>,
1891 /// ISO 8601 timestamp of last activity
1892 #[serde_as(deserialize_as = "DefaultOnError")]
1893 #[schemars(extend("x-deserialize-default-on-error" = true))]
1894 #[serde(default)]
1895 pub updated_at: Option<String>,
1896 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1897 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1898 /// these keys.
1899 ///
1900 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1901 #[serde(rename = "_meta")]
1902 pub meta: Option<Meta>,
1903}
1904
1905impl SessionInfo {
1906 /// Builds [`SessionInfo`] with the required fields set; optional fields start unset or empty.
1907 #[must_use]
1908 pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1909 Self {
1910 session_id: session_id.into(),
1911 cwd: cwd.into(),
1912 additional_directories: vec![],
1913 title: None,
1914 updated_at: None,
1915 meta: None,
1916 }
1917 }
1918
1919 /// Additional workspace roots reported for this session. Each path must be absolute.
1920 #[must_use]
1921 pub fn additional_directories(mut self, additional_directories: Vec<PathBuf>) -> Self {
1922 self.additional_directories = additional_directories;
1923 self
1924 }
1925
1926 /// Human-readable title for the session
1927 #[must_use]
1928 pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1929 self.title = title.into_option();
1930 self
1931 }
1932
1933 /// ISO 8601 timestamp of last activity
1934 #[must_use]
1935 pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1936 self.updated_at = updated_at.into_option();
1937 self
1938 }
1939
1940 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1941 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1942 /// these keys.
1943 ///
1944 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1945 #[must_use]
1946 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1947 self.meta = meta.into_option();
1948 self
1949 }
1950}
1951
1952// Session config options
1953
1954/// Unique identifier for a session configuration option.
1955#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1956#[serde(transparent)]
1957#[from(Arc<str>, String, &'static str)]
1958#[non_exhaustive]
1959pub struct SessionConfigId(pub Arc<str>);
1960
1961impl SessionConfigId {
1962 /// Wraps a protocol string as a typed [`SessionConfigId`].
1963 #[must_use]
1964 pub fn new(id: impl Into<Arc<str>>) -> Self {
1965 Self(id.into())
1966 }
1967}
1968
1969/// Unique identifier for a session configuration option value.
1970#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1971#[serde(transparent)]
1972#[from(Arc<str>, String, &'static str)]
1973#[non_exhaustive]
1974pub struct SessionConfigValueId(pub Arc<str>);
1975
1976impl SessionConfigValueId {
1977 /// Wraps a protocol string as a typed [`SessionConfigValueId`].
1978 #[must_use]
1979 pub fn new(id: impl Into<Arc<str>>) -> Self {
1980 Self(id.into())
1981 }
1982}
1983
1984/// Unique identifier for a session configuration option value group.
1985#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1986#[serde(transparent)]
1987#[from(Arc<str>, String, &'static str)]
1988#[non_exhaustive]
1989pub struct SessionConfigGroupId(pub Arc<str>);
1990
1991impl SessionConfigGroupId {
1992 /// Wraps a protocol string as a typed [`SessionConfigGroupId`].
1993 #[must_use]
1994 pub fn new(id: impl Into<Arc<str>>) -> Self {
1995 Self(id.into())
1996 }
1997}
1998
1999/// A possible value for a session configuration option.
2000#[skip_serializing_none]
2001#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2002#[serde(rename_all = "camelCase")]
2003#[non_exhaustive]
2004pub struct SessionConfigSelectOption {
2005 /// Unique identifier for this option value.
2006 pub value: SessionConfigValueId,
2007 /// Human-readable label for this option value.
2008 pub name: String,
2009 /// Optional description for this option value.
2010 #[serde(default)]
2011 pub description: Option<String>,
2012 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2013 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2014 /// these keys.
2015 ///
2016 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2017 #[serde(rename = "_meta")]
2018 pub meta: Option<Meta>,
2019}
2020
2021impl SessionConfigSelectOption {
2022 /// Builds [`SessionConfigSelectOption`] with the required fields set; optional fields start unset or empty.
2023 #[must_use]
2024 pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
2025 Self {
2026 value: value.into(),
2027 name: name.into(),
2028 description: None,
2029 meta: None,
2030 }
2031 }
2032
2033 /// Sets or clears the optional `description` field.
2034 #[must_use]
2035 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2036 self.description = description.into_option();
2037 self
2038 }
2039
2040 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2041 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2042 /// these keys.
2043 ///
2044 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2045 #[must_use]
2046 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2047 self.meta = meta.into_option();
2048 self
2049 }
2050}
2051
2052/// A group of possible values for a session configuration option.
2053#[skip_serializing_none]
2054#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2055#[serde(rename_all = "camelCase")]
2056#[non_exhaustive]
2057pub struct SessionConfigSelectGroup {
2058 /// Unique identifier for this group.
2059 pub group: SessionConfigGroupId,
2060 /// Human-readable label for this group.
2061 pub name: String,
2062 /// The set of option values in this group.
2063 pub options: Vec<SessionConfigSelectOption>,
2064 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2065 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2066 /// these keys.
2067 ///
2068 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2069 #[serde(rename = "_meta")]
2070 pub meta: Option<Meta>,
2071}
2072
2073impl SessionConfigSelectGroup {
2074 /// Builds [`SessionConfigSelectGroup`] with the required fields set; optional fields start unset or empty.
2075 #[must_use]
2076 pub fn new(
2077 group: impl Into<SessionConfigGroupId>,
2078 name: impl Into<String>,
2079 options: Vec<SessionConfigSelectOption>,
2080 ) -> Self {
2081 Self {
2082 group: group.into(),
2083 name: name.into(),
2084 options,
2085 meta: None,
2086 }
2087 }
2088
2089 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2090 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2091 /// these keys.
2092 ///
2093 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2094 #[must_use]
2095 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2096 self.meta = meta.into_option();
2097 self
2098 }
2099}
2100
2101/// Possible values for a session configuration option.
2102#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2103#[serde(untagged)]
2104#[non_exhaustive]
2105pub enum SessionConfigSelectOptions {
2106 /// A flat list of options with no grouping.
2107 Ungrouped(Vec<SessionConfigSelectOption>),
2108 /// A list of options grouped under headers.
2109 Grouped(Vec<SessionConfigSelectGroup>),
2110}
2111
2112impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
2113 fn from(options: Vec<SessionConfigSelectOption>) -> Self {
2114 SessionConfigSelectOptions::Ungrouped(options)
2115 }
2116}
2117
2118impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
2119 fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
2120 SessionConfigSelectOptions::Grouped(groups)
2121 }
2122}
2123
2124/// A single-value selector (dropdown) session configuration option payload.
2125#[skip_serializing_none]
2126#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2127#[serde(rename_all = "camelCase")]
2128#[non_exhaustive]
2129pub struct SessionConfigSelect {
2130 /// The currently selected value.
2131 pub current_value: SessionConfigValueId,
2132 /// The set of selectable options.
2133 pub options: SessionConfigSelectOptions,
2134}
2135
2136impl SessionConfigSelect {
2137 /// Builds [`SessionConfigSelect`] with the required fields set; optional fields start unset or empty.
2138 #[must_use]
2139 pub fn new(
2140 current_value: impl Into<SessionConfigValueId>,
2141 options: impl Into<SessionConfigSelectOptions>,
2142 ) -> Self {
2143 Self {
2144 current_value: current_value.into(),
2145 options: options.into(),
2146 }
2147 }
2148}
2149
2150/// **UNSTABLE**
2151///
2152/// This capability is not part of the spec yet, and may be removed or changed at any point.
2153///
2154/// A boolean on/off toggle session configuration option payload.
2155#[cfg(feature = "unstable_boolean_config")]
2156#[skip_serializing_none]
2157#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2158#[serde(rename_all = "camelCase")]
2159#[non_exhaustive]
2160pub struct SessionConfigBoolean {
2161 /// The current value of the boolean option.
2162 pub current_value: bool,
2163}
2164
2165#[cfg(feature = "unstable_boolean_config")]
2166impl SessionConfigBoolean {
2167 /// Builds [`SessionConfigBoolean`] with the required fields set; optional fields start unset or empty.
2168 #[must_use]
2169 pub fn new(current_value: bool) -> Self {
2170 Self { current_value }
2171 }
2172}
2173
2174/// Semantic category for a session configuration option.
2175///
2176/// This is intended to help Clients distinguish broadly common selectors (e.g. model selector vs
2177/// session mode selector vs thought/reasoning level) for UX purposes (keyboard shortcuts, icons,
2178/// placement). It MUST NOT be required for correctness. Clients MUST handle missing or unknown
2179/// categories gracefully.
2180///
2181/// Category names beginning with `_` are free for custom use, like other ACP extension methods.
2182/// Category names that do not begin with `_` are reserved for the ACP spec.
2183#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2184#[serde(rename_all = "snake_case")]
2185#[non_exhaustive]
2186pub enum SessionConfigOptionCategory {
2187 /// Session mode selector.
2188 Mode,
2189 /// Model selector.
2190 Model,
2191 /// Model-related configuration parameter.
2192 ModelConfig,
2193 /// Thought/reasoning level selector.
2194 ThoughtLevel,
2195 /// Custom or future category.
2196 ///
2197 /// Values beginning with `_` are reserved for implementation-specific
2198 /// extensions. Unknown values that do not begin with `_` are reserved for
2199 /// future ACP variants.
2200 #[serde(untagged)]
2201 Other(String),
2202}
2203
2204/// Type-specific session configuration option payload.
2205#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2206#[serde(tag = "type", rename_all = "snake_case")]
2207#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2208#[non_exhaustive]
2209pub enum SessionConfigKind {
2210 /// Single-value selector (dropdown).
2211 Select(SessionConfigSelect),
2212 /// **UNSTABLE**
2213 ///
2214 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2215 ///
2216 /// Boolean on/off toggle.
2217 #[cfg(feature = "unstable_boolean_config")]
2218 Boolean(SessionConfigBoolean),
2219 /// Custom or future session configuration option payload.
2220 ///
2221 /// Values beginning with `_` are reserved for implementation-specific
2222 /// extensions. Unknown values that do not begin with `_` are reserved for
2223 /// future ACP variants.
2224 ///
2225 /// Clients that do not understand this option type should preserve the raw
2226 /// payload when storing, replaying, proxying, or forwarding configuration
2227 /// data, and otherwise ignore the option or display it generically.
2228 #[serde(untagged)]
2229 Other(OtherSessionConfigKind),
2230}
2231
2232/// Custom or future session configuration option payload.
2233#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2234#[schemars(inline)]
2235#[schemars(transform = other_session_config_kind_schema)]
2236#[serde(rename_all = "camelCase")]
2237#[non_exhaustive]
2238pub struct OtherSessionConfigKind {
2239 /// Custom or future session configuration option type.
2240 ///
2241 /// Values beginning with `_` are reserved for implementation-specific
2242 /// extensions. Unknown values that do not begin with `_` are reserved for
2243 /// future ACP variants.
2244 #[serde(rename = "type")]
2245 pub type_: String,
2246 /// Additional fields from the unknown session configuration option payload.
2247 #[serde(flatten)]
2248 pub fields: BTreeMap<String, serde_json::Value>,
2249}
2250
2251impl OtherSessionConfigKind {
2252 /// Builds [`OtherSessionConfigKind`] from an unknown discriminator and preserves the remaining extension fields.
2253 #[must_use]
2254 pub fn new(type_: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2255 fields.remove("type");
2256 fields.remove("_meta");
2257 Self {
2258 type_: type_.into(),
2259 fields,
2260 }
2261 }
2262}
2263
2264impl<'de> Deserialize<'de> for OtherSessionConfigKind {
2265 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2266 where
2267 D: serde::Deserializer<'de>,
2268 {
2269 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2270 let type_ = fields
2271 .remove("type")
2272 .ok_or_else(|| serde::de::Error::missing_field("type"))?;
2273 let serde_json::Value::String(type_) = type_ else {
2274 return Err(serde::de::Error::custom("`type` must be a string"));
2275 };
2276
2277 if is_known_session_config_kind_type(&type_) {
2278 return Err(serde::de::Error::custom(format!(
2279 "known session configuration option `{type_}` did not match its schema"
2280 )));
2281 }
2282
2283 Ok(Self { type_, fields })
2284 }
2285}
2286
2287fn is_known_session_config_kind_type(type_: &str) -> bool {
2288 match type_ {
2289 "select" => true,
2290 #[cfg(feature = "unstable_boolean_config")]
2291 "boolean" => true,
2292 _ => false,
2293 }
2294}
2295
2296fn other_session_config_kind_schema(schema: &mut Schema) {
2297 super::schema_util::reject_known_string_discriminators(
2298 schema,
2299 "type",
2300 &[
2301 "select",
2302 #[cfg(feature = "unstable_boolean_config")]
2303 "boolean",
2304 ],
2305 );
2306}
2307
2308/// A session configuration option selector and its current state.
2309#[serde_as]
2310#[skip_serializing_none]
2311#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2312#[serde(rename_all = "camelCase")]
2313#[non_exhaustive]
2314pub struct SessionConfigOption {
2315 /// Unique identifier for the configuration option.
2316 pub id: SessionConfigId,
2317 /// Human-readable label for the option.
2318 pub name: String,
2319 /// Optional description for the Client to display to the user.
2320 #[serde(default)]
2321 pub description: Option<String>,
2322 /// Optional semantic category for this option (UX only).
2323 #[serde_as(deserialize_as = "DefaultOnError")]
2324 #[schemars(extend("x-deserialize-default-on-error" = true))]
2325 #[serde(default)]
2326 pub category: Option<SessionConfigOptionCategory>,
2327 /// Type-specific fields for this configuration option.
2328 #[serde(flatten)]
2329 pub kind: SessionConfigKind,
2330 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2331 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2332 /// these keys.
2333 ///
2334 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2335 #[serde(rename = "_meta")]
2336 pub meta: Option<Meta>,
2337}
2338
2339impl SessionConfigOption {
2340 /// Builds [`SessionConfigOption`] with the required fields set; optional fields start unset or empty.
2341 #[must_use]
2342 pub fn new(
2343 id: impl Into<SessionConfigId>,
2344 name: impl Into<String>,
2345 kind: SessionConfigKind,
2346 ) -> Self {
2347 Self {
2348 id: id.into(),
2349 name: name.into(),
2350 description: None,
2351 category: None,
2352 kind,
2353 meta: None,
2354 }
2355 }
2356
2357 /// Builds a select-style session configuration option with its current value and choices.
2358 #[must_use]
2359 pub fn select(
2360 id: impl Into<SessionConfigId>,
2361 name: impl Into<String>,
2362 current_value: impl Into<SessionConfigValueId>,
2363 options: impl Into<SessionConfigSelectOptions>,
2364 ) -> Self {
2365 Self::new(
2366 id,
2367 name,
2368 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2369 )
2370 }
2371
2372 /// **UNSTABLE**
2373 ///
2374 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2375 #[cfg(feature = "unstable_boolean_config")]
2376 #[must_use]
2377 pub fn boolean(
2378 id: impl Into<SessionConfigId>,
2379 name: impl Into<String>,
2380 current_value: bool,
2381 ) -> Self {
2382 Self::new(
2383 id,
2384 name,
2385 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2386 )
2387 }
2388
2389 /// Sets or clears the optional `description` field.
2390 #[must_use]
2391 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2392 self.description = description.into_option();
2393 self
2394 }
2395
2396 /// Sets or clears the optional `category` field.
2397 #[must_use]
2398 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2399 self.category = category.into_option();
2400 self
2401 }
2402
2403 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2404 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2405 /// these keys.
2406 ///
2407 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2408 #[must_use]
2409 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2410 self.meta = meta.into_option();
2411 self
2412 }
2413}
2414
2415/// **UNSTABLE**
2416///
2417/// This capability is not part of the spec yet, and may be removed or changed at any point.
2418///
2419/// The value to set for a session configuration option.
2420///
2421/// The `type` field acts as the discriminator in the serialized JSON form.
2422/// When no `type` is present, the value is treated as a [`SessionConfigValueId`]
2423/// via the [`ValueId`](Self::ValueId) fallback variant.
2424///
2425/// The `type` discriminator describes the *shape* of the value, not the option
2426/// kind. For example every option kind that picks from a list of ids
2427/// (`select`, `radio`, …) would use [`ValueId`](Self::ValueId), while a
2428/// future freeform text option would get its own variant.
2429#[cfg(feature = "unstable_boolean_config")]
2430#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2431#[serde(tag = "type", rename_all = "snake_case")]
2432#[non_exhaustive]
2433pub enum SessionConfigOptionValue {
2434 /// A boolean value (`type: "boolean"`).
2435 Boolean {
2436 /// The boolean value.
2437 value: bool,
2438 },
2439 /// A [`SessionConfigValueId`] string value.
2440 ///
2441 /// This is the default when `type` is absent on the wire. Unknown `type`
2442 /// values with string payloads also gracefully deserialize into this
2443 /// variant.
2444 #[serde(untagged)]
2445 ValueId {
2446 /// The value ID.
2447 value: SessionConfigValueId,
2448 },
2449}
2450
2451#[cfg(feature = "unstable_boolean_config")]
2452impl SessionConfigOptionValue {
2453 /// Create a value-id option value (used by `select` and other id-based option types).
2454 #[must_use]
2455 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2456 Self::ValueId { value: id.into() }
2457 }
2458
2459 /// Create a boolean option value.
2460 #[must_use]
2461 pub fn boolean(val: bool) -> Self {
2462 Self::Boolean { value: val }
2463 }
2464
2465 /// Return the inner [`SessionConfigValueId`] if this is a
2466 /// [`ValueId`](Self::ValueId) value.
2467 #[must_use]
2468 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2469 match self {
2470 Self::ValueId { value } => Some(value),
2471 _ => None,
2472 }
2473 }
2474
2475 /// Return the inner [`bool`] if this is a [`Boolean`](Self::Boolean) value.
2476 #[must_use]
2477 pub fn as_bool(&self) -> Option<bool> {
2478 match self {
2479 Self::Boolean { value } => Some(*value),
2480 _ => None,
2481 }
2482 }
2483}
2484
2485#[cfg(feature = "unstable_boolean_config")]
2486impl From<SessionConfigValueId> for SessionConfigOptionValue {
2487 fn from(value: SessionConfigValueId) -> Self {
2488 Self::ValueId { value }
2489 }
2490}
2491
2492#[cfg(feature = "unstable_boolean_config")]
2493impl From<bool> for SessionConfigOptionValue {
2494 fn from(value: bool) -> Self {
2495 Self::Boolean { value }
2496 }
2497}
2498
2499#[cfg(feature = "unstable_boolean_config")]
2500impl From<&str> for SessionConfigOptionValue {
2501 fn from(value: &str) -> Self {
2502 Self::ValueId {
2503 value: SessionConfigValueId::new(value),
2504 }
2505 }
2506}
2507
2508/// Request parameters for setting a session configuration option.
2509#[skip_serializing_none]
2510#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2511#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2512#[serde(rename_all = "camelCase")]
2513#[non_exhaustive]
2514pub struct SetSessionConfigOptionRequest {
2515 /// The ID of the session to set the configuration option for.
2516 pub session_id: SessionId,
2517 /// The ID of the configuration option to set.
2518 pub config_id: SessionConfigId,
2519 /// The value to set, including a `type` discriminator and the raw `value`.
2520 ///
2521 /// When `type` is absent on the wire, defaults to treating the value as a
2522 /// [`SessionConfigValueId`] for `select` options.
2523 #[cfg(feature = "unstable_boolean_config")]
2524 #[serde(flatten)]
2525 pub value: SessionConfigOptionValue,
2526 /// The ID of the configuration option value to set.
2527 #[cfg(not(feature = "unstable_boolean_config"))]
2528 pub value: SessionConfigValueId,
2529 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2530 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2531 /// these keys.
2532 ///
2533 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2534 #[serde(rename = "_meta")]
2535 pub meta: Option<Meta>,
2536}
2537
2538impl SetSessionConfigOptionRequest {
2539 /// Builds [`SetSessionConfigOptionRequest`] with the required request fields set; optional fields start unset or empty.
2540 #[cfg(feature = "unstable_boolean_config")]
2541 #[must_use]
2542 pub fn new(
2543 session_id: impl Into<SessionId>,
2544 config_id: impl Into<SessionConfigId>,
2545 value: impl Into<SessionConfigOptionValue>,
2546 ) -> Self {
2547 Self {
2548 session_id: session_id.into(),
2549 config_id: config_id.into(),
2550 value: value.into(),
2551 meta: None,
2552 }
2553 }
2554
2555 /// Builds a select-value `session/set_config_option` request for crates built
2556 /// without boolean session configuration support.
2557 #[cfg(not(feature = "unstable_boolean_config"))]
2558 #[must_use]
2559 pub fn new(
2560 session_id: impl Into<SessionId>,
2561 config_id: impl Into<SessionConfigId>,
2562 value: impl Into<SessionConfigValueId>,
2563 ) -> Self {
2564 Self {
2565 session_id: session_id.into(),
2566 config_id: config_id.into(),
2567 value: value.into(),
2568 meta: None,
2569 }
2570 }
2571
2572 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2573 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2574 /// these keys.
2575 ///
2576 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2577 #[must_use]
2578 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2579 self.meta = meta.into_option();
2580 self
2581 }
2582}
2583
2584/// Response to `session/set_config_option` method.
2585#[serde_as]
2586#[skip_serializing_none]
2587#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2588#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2589#[serde(rename_all = "camelCase")]
2590#[non_exhaustive]
2591pub struct SetSessionConfigOptionResponse {
2592 /// The full set of configuration options and their current values.
2593 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2594 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2595 pub config_options: Vec<SessionConfigOption>,
2596 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2597 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2598 /// these keys.
2599 ///
2600 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2601 #[serde(rename = "_meta")]
2602 pub meta: Option<Meta>,
2603}
2604
2605impl SetSessionConfigOptionResponse {
2606 /// Builds [`SetSessionConfigOptionResponse`] with the required response fields set; optional fields start unset or empty.
2607 #[must_use]
2608 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2609 Self {
2610 config_options,
2611 meta: None,
2612 }
2613 }
2614
2615 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2616 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2617 /// these keys.
2618 ///
2619 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2620 #[must_use]
2621 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2622 self.meta = meta.into_option();
2623 self
2624 }
2625}
2626
2627// MCP
2628
2629/// Configuration for connecting to an MCP (Model Context Protocol) server.
2630///
2631/// MCP servers provide tools and context that the agent can use when
2632/// processing prompts.
2633///
2634/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
2635#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2636#[serde(tag = "type", rename_all = "snake_case")]
2637#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2638#[non_exhaustive]
2639pub enum McpServer {
2640 /// HTTP transport configuration
2641 ///
2642 /// Only available when the Agent capabilities include `session.mcp.http`.
2643 Http(McpServerHttp),
2644 /// **UNSTABLE**
2645 ///
2646 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2647 ///
2648 /// ACP transport configuration
2649 ///
2650 /// Only available when the Agent capabilities include `session.mcp.acp`.
2651 /// The MCP server is provided by an ACP component and communicates over the ACP channel.
2652 #[cfg(feature = "unstable_mcp_over_acp")]
2653 Acp(McpServerAcp),
2654 /// Stdio transport configuration
2655 ///
2656 /// Only available when the Agent capabilities include `session.mcp.stdio`.
2657 Stdio(McpServerStdio),
2658 /// Custom or future MCP server transport configuration.
2659 ///
2660 /// Values beginning with `_` are reserved for implementation-specific
2661 /// extensions. Unknown values that do not begin with `_` are reserved for
2662 /// future ACP variants.
2663 ///
2664 /// Receivers that do not understand this transport should preserve the raw
2665 /// payload when storing, replaying, proxying, or forwarding session setup
2666 /// data, and otherwise ignore it or reject the server configuration.
2667 #[serde(untagged)]
2668 Other(OtherMcpServer),
2669}
2670
2671/// Custom or future MCP server transport payload.
2672#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2673#[schemars(inline)]
2674#[schemars(transform = other_mcp_server_schema)]
2675#[serde(rename_all = "camelCase")]
2676#[non_exhaustive]
2677pub struct OtherMcpServer {
2678 /// Custom or future MCP server transport type.
2679 ///
2680 /// Values beginning with `_` are reserved for implementation-specific
2681 /// extensions. Unknown values that do not begin with `_` are reserved for
2682 /// future ACP variants.
2683 #[serde(rename = "type")]
2684 pub type_: String,
2685 /// Additional fields from the unknown MCP server transport payload.
2686 #[serde(flatten)]
2687 pub fields: BTreeMap<String, serde_json::Value>,
2688}
2689
2690impl OtherMcpServer {
2691 /// Builds [`OtherMcpServer`] from an unknown discriminator and preserves the remaining extension fields.
2692 #[must_use]
2693 pub fn new(type_: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2694 fields.remove("type");
2695 Self {
2696 type_: type_.into(),
2697 fields,
2698 }
2699 }
2700}
2701
2702impl<'de> Deserialize<'de> for OtherMcpServer {
2703 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2704 where
2705 D: serde::Deserializer<'de>,
2706 {
2707 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2708 let type_ = fields
2709 .remove("type")
2710 .ok_or_else(|| serde::de::Error::missing_field("type"))?;
2711 let serde_json::Value::String(type_) = type_ else {
2712 return Err(serde::de::Error::custom("`type` must be a string"));
2713 };
2714
2715 if is_known_mcp_server_type(&type_) {
2716 return Err(serde::de::Error::custom(format!(
2717 "known MCP server transport `{type_}` did not match its schema"
2718 )));
2719 }
2720
2721 Ok(Self { type_, fields })
2722 }
2723}
2724
2725fn is_known_mcp_server_type(type_: &str) -> bool {
2726 match type_ {
2727 "http" | "stdio" => true,
2728 #[cfg(feature = "unstable_mcp_over_acp")]
2729 "acp" => true,
2730 _ => false,
2731 }
2732}
2733
2734fn other_mcp_server_schema(schema: &mut Schema) {
2735 super::schema_util::reject_known_string_discriminators(
2736 schema,
2737 "type",
2738 &[
2739 "http",
2740 "stdio",
2741 #[cfg(feature = "unstable_mcp_over_acp")]
2742 "acp",
2743 ],
2744 );
2745}
2746
2747/// HTTP transport configuration for MCP.
2748#[skip_serializing_none]
2749#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2750#[serde(rename_all = "camelCase")]
2751#[non_exhaustive]
2752pub struct McpServerHttp {
2753 /// Human-readable name identifying this MCP server.
2754 pub name: String,
2755 /// URL to the MCP server.
2756 pub url: String,
2757 /// HTTP headers to set when making requests to the MCP server.
2758 pub headers: Vec<HttpHeader>,
2759 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2760 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2761 /// these keys.
2762 ///
2763 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2764 #[serde(rename = "_meta")]
2765 pub meta: Option<Meta>,
2766}
2767
2768impl McpServerHttp {
2769 /// Builds [`McpServerHttp`] with the required fields set; optional fields start unset or empty.
2770 #[must_use]
2771 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2772 Self {
2773 name: name.into(),
2774 url: url.into(),
2775 headers: Vec::new(),
2776 meta: None,
2777 }
2778 }
2779
2780 /// HTTP headers to set when making requests to the MCP server.
2781 #[must_use]
2782 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2783 self.headers = headers;
2784 self
2785 }
2786
2787 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2788 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2789 /// these keys.
2790 ///
2791 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2792 #[must_use]
2793 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2794 self.meta = meta.into_option();
2795 self
2796 }
2797}
2798
2799/// **UNSTABLE**
2800///
2801/// This capability is not part of the spec yet, and may be removed or changed at any point.
2802///
2803/// Unique identifier for an MCP server using the ACP transport.
2804///
2805/// The value is opaque and generated by the ACP component providing the MCP server. It is
2806/// used by `mcp/connect` to route connection requests back to the component that declared the
2807/// server.
2808#[cfg(feature = "unstable_mcp_over_acp")]
2809#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2810#[serde(transparent)]
2811#[from(Arc<str>, String, &'static str)]
2812#[non_exhaustive]
2813pub struct McpServerAcpId(pub Arc<str>);
2814
2815#[cfg(feature = "unstable_mcp_over_acp")]
2816impl McpServerAcpId {
2817 /// Wraps a protocol string as a typed [`McpServerAcpId`].
2818 #[must_use]
2819 pub fn new(id: impl Into<Arc<str>>) -> Self {
2820 Self(id.into())
2821 }
2822}
2823
2824/// **UNSTABLE**
2825///
2826/// This capability is not part of the spec yet, and may be removed or changed at any point.
2827///
2828/// ACP transport configuration for MCP.
2829///
2830/// The MCP server is provided by an ACP component and communicates over the ACP channel
2831/// using `mcp/connect`, `mcp/message`, and `mcp/disconnect`.
2832#[skip_serializing_none]
2833#[cfg(feature = "unstable_mcp_over_acp")]
2834#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2835#[serde(rename_all = "camelCase")]
2836#[non_exhaustive]
2837pub struct McpServerAcp {
2838 /// Human-readable name identifying this MCP server.
2839 pub name: String,
2840 /// Unique identifier for this MCP server, generated by the component providing it.
2841 ///
2842 /// Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible
2843 /// on the same ACP connection.
2844 pub id: McpServerAcpId,
2845 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2846 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2847 /// these keys.
2848 ///
2849 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2850 #[serde(rename = "_meta")]
2851 pub meta: Option<Meta>,
2852}
2853
2854#[cfg(feature = "unstable_mcp_over_acp")]
2855impl McpServerAcp {
2856 /// Builds [`McpServerAcp`] with the required fields set; optional fields start unset or empty.
2857 #[must_use]
2858 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2859 Self {
2860 name: name.into(),
2861 id: id.into(),
2862 meta: None,
2863 }
2864 }
2865
2866 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2867 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2868 /// these keys.
2869 ///
2870 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2871 #[must_use]
2872 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2873 self.meta = meta.into_option();
2874 self
2875 }
2876}
2877
2878/// Stdio transport configuration for MCP.
2879#[skip_serializing_none]
2880#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2881#[serde(rename_all = "camelCase")]
2882#[non_exhaustive]
2883pub struct McpServerStdio {
2884 /// Human-readable name identifying this MCP server.
2885 pub name: String,
2886 /// Path to the MCP server executable.
2887 pub command: PathBuf,
2888 /// Command-line arguments to pass to the MCP server.
2889 pub args: Vec<String>,
2890 /// Environment variables to set when launching the MCP server.
2891 pub env: Vec<EnvVariable>,
2892 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2893 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2894 /// these keys.
2895 ///
2896 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2897 #[serde(rename = "_meta")]
2898 pub meta: Option<Meta>,
2899}
2900
2901impl McpServerStdio {
2902 /// Builds [`McpServerStdio`] with the required fields set; optional fields start unset or empty.
2903 #[must_use]
2904 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2905 Self {
2906 name: name.into(),
2907 command: command.into(),
2908 args: Vec::new(),
2909 env: Vec::new(),
2910 meta: None,
2911 }
2912 }
2913
2914 /// Command-line arguments to pass to the MCP server.
2915 #[must_use]
2916 pub fn args(mut self, args: Vec<String>) -> Self {
2917 self.args = args;
2918 self
2919 }
2920
2921 /// Environment variables to set when launching the MCP server.
2922 #[must_use]
2923 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2924 self.env = env;
2925 self
2926 }
2927
2928 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2929 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2930 /// these keys.
2931 ///
2932 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2933 #[must_use]
2934 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2935 self.meta = meta.into_option();
2936 self
2937 }
2938}
2939
2940/// An environment variable to set when launching an MCP server.
2941#[skip_serializing_none]
2942#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2943#[serde(rename_all = "camelCase")]
2944#[non_exhaustive]
2945pub struct EnvVariable {
2946 /// The name of the environment variable.
2947 pub name: String,
2948 /// The value to set for the environment variable.
2949 pub value: String,
2950 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2951 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2952 /// these keys.
2953 ///
2954 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2955 #[serde(rename = "_meta")]
2956 pub meta: Option<Meta>,
2957}
2958
2959impl EnvVariable {
2960 /// Builds [`EnvVariable`] with the required fields set; optional fields start unset or empty.
2961 #[must_use]
2962 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2963 Self {
2964 name: name.into(),
2965 value: value.into(),
2966 meta: None,
2967 }
2968 }
2969
2970 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2971 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2972 /// these keys.
2973 ///
2974 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2975 #[must_use]
2976 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2977 self.meta = meta.into_option();
2978 self
2979 }
2980}
2981
2982/// An HTTP header to set when making requests to the MCP server.
2983#[skip_serializing_none]
2984#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2985#[serde(rename_all = "camelCase")]
2986#[non_exhaustive]
2987pub struct HttpHeader {
2988 /// The name of the HTTP header.
2989 pub name: String,
2990 /// The value to set for the HTTP header.
2991 pub value: String,
2992 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2993 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2994 /// these keys.
2995 ///
2996 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2997 #[serde(rename = "_meta")]
2998 pub meta: Option<Meta>,
2999}
3000
3001impl HttpHeader {
3002 /// Builds [`HttpHeader`] with the required fields set; optional fields start unset or empty.
3003 #[must_use]
3004 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3005 Self {
3006 name: name.into(),
3007 value: value.into(),
3008 meta: None,
3009 }
3010 }
3011
3012 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3013 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3014 /// these keys.
3015 ///
3016 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3017 #[must_use]
3018 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3019 self.meta = meta.into_option();
3020 self
3021 }
3022}
3023
3024// Prompt
3025
3026/// Request parameters for sending a user prompt to the agent.
3027///
3028/// Contains the user's message and any additional context.
3029///
3030/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-lifecycle#1-user-message)
3031#[skip_serializing_none]
3032#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3033#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3034#[serde(rename_all = "camelCase")]
3035#[non_exhaustive]
3036pub struct PromptRequest {
3037 /// The ID of the session to send this user message to
3038 pub session_id: SessionId,
3039 /// The blocks of content that compose the user's message.
3040 ///
3041 /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
3042 /// while other variants are optionally enabled via [`PromptCapabilities`].
3043 ///
3044 /// The Client MUST adapt its interface according to [`PromptCapabilities`].
3045 ///
3046 /// The client MAY include referenced pieces of context as either
3047 /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
3048 ///
3049 /// When available, [`ContentBlock::Resource`] is preferred
3050 /// as it avoids extra round-trips and allows the message to include
3051 /// pieces of context from sources the agent may not have access to.
3052 pub prompt: Vec<ContentBlock>,
3053 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3054 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3055 /// these keys.
3056 ///
3057 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3058 #[serde(rename = "_meta")]
3059 pub meta: Option<Meta>,
3060}
3061
3062impl PromptRequest {
3063 /// Builds [`PromptRequest`] with the required request fields set; optional fields start unset or empty.
3064 #[must_use]
3065 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3066 Self {
3067 session_id: session_id.into(),
3068 prompt,
3069 meta: None,
3070 }
3071 }
3072
3073 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3074 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3075 /// these keys.
3076 ///
3077 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3078 #[must_use]
3079 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3080 self.meta = meta.into_option();
3081 self
3082 }
3083}
3084
3085/// Response acknowledging that a user prompt was accepted.
3086///
3087/// This response does not indicate that the agent has finished processing.
3088/// Agents report session state through `state_update` session updates.
3089///
3090/// See protocol docs: [Prompt Accepted](https://agentclientprotocol.com/protocol/prompt-lifecycle#2-prompt-accepted)
3091#[skip_serializing_none]
3092#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3093#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3094#[serde(rename_all = "camelCase")]
3095#[non_exhaustive]
3096pub struct PromptResponse {
3097 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3098 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3099 /// these keys.
3100 ///
3101 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3102 #[serde(rename = "_meta")]
3103 pub meta: Option<Meta>,
3104}
3105
3106impl PromptResponse {
3107 /// Builds [`PromptResponse`] with the required response fields set; optional fields start unset or empty.
3108 #[must_use]
3109 pub fn new() -> Self {
3110 Self::default()
3111 }
3112
3113 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3114 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3115 /// these keys.
3116 ///
3117 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3118 #[must_use]
3119 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3120 self.meta = meta.into_option();
3121 self
3122 }
3123}
3124
3125/// Reasons why an agent stops active session work.
3126///
3127/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-lifecycle#stop-reasons)
3128#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3129#[serde(rename_all = "snake_case")]
3130#[non_exhaustive]
3131pub enum StopReason {
3132 /// The active work ended successfully.
3133 EndTurn,
3134 /// The active work ended because the agent reached the maximum number of tokens.
3135 MaxTokens,
3136 /// The active work ended because the agent reached the maximum number of
3137 /// allowed agent requests before returning idle.
3138 MaxTurnRequests,
3139 /// The active work ended because the agent refused to continue. The user
3140 /// prompt and everything that comes after it won't be included in the next
3141 /// prompt, so this should be reflected in the UI.
3142 Refusal,
3143 /// Active session work was cancelled by the client via `session/cancel`.
3144 ///
3145 /// Agents should report this stop reason on an idle `state_update` session update
3146 /// when cancellation succeeds, even if cancellation causes exceptions in
3147 /// underlying operations.
3148 Cancelled,
3149 /// Custom or future stop reason.
3150 ///
3151 /// Values beginning with `_` are reserved for implementation-specific
3152 /// extensions. Unknown values that do not begin with `_` are reserved for
3153 /// future ACP variants.
3154 #[serde(untagged)]
3155 Other(String),
3156}
3157
3158/// **UNSTABLE**
3159///
3160/// This capability is not part of the spec yet, and may be removed or changed at any point.
3161///
3162/// Token usage information for completed session work.
3163#[cfg(feature = "unstable_end_turn_token_usage")]
3164#[skip_serializing_none]
3165#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3166#[serde(rename_all = "camelCase")]
3167#[non_exhaustive]
3168pub struct Usage {
3169 /// Sum of all token types across session.
3170 pub total_tokens: u64,
3171 /// Total input tokens.
3172 pub input_tokens: u64,
3173 /// Total output tokens.
3174 pub output_tokens: u64,
3175 /// Total thought/reasoning tokens
3176 pub thought_tokens: Option<u64>,
3177 /// Total cache read tokens.
3178 pub cached_read_tokens: Option<u64>,
3179 /// Total cache write tokens.
3180 pub cached_write_tokens: Option<u64>,
3181 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3182 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3183 /// these keys.
3184 ///
3185 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3186 #[serde(rename = "_meta")]
3187 pub meta: Option<Meta>,
3188}
3189
3190#[cfg(feature = "unstable_end_turn_token_usage")]
3191impl Usage {
3192 /// Builds [`Usage`] with the required fields set; optional fields start unset or empty.
3193 #[must_use]
3194 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3195 Self {
3196 total_tokens,
3197 input_tokens,
3198 output_tokens,
3199 thought_tokens: None,
3200 cached_read_tokens: None,
3201 cached_write_tokens: None,
3202 meta: None,
3203 }
3204 }
3205
3206 /// Total thought/reasoning tokens
3207 #[must_use]
3208 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3209 self.thought_tokens = thought_tokens.into_option();
3210 self
3211 }
3212
3213 /// Total cache read tokens.
3214 #[must_use]
3215 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3216 self.cached_read_tokens = cached_read_tokens.into_option();
3217 self
3218 }
3219
3220 /// Total cache write tokens.
3221 #[must_use]
3222 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3223 self.cached_write_tokens = cached_write_tokens.into_option();
3224 self
3225 }
3226
3227 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3228 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3229 /// these keys.
3230 ///
3231 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3232 #[must_use]
3233 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3234 self.meta = meta.into_option();
3235 self
3236 }
3237}
3238
3239// Providers
3240
3241/// **UNSTABLE**
3242///
3243/// This capability is not part of the spec yet, and may be removed or changed at any point.
3244///
3245/// Well-known API protocol identifiers for LLM providers.
3246///
3247/// Agents and clients MUST handle unknown protocol identifiers gracefully.
3248///
3249/// Protocol names beginning with `_` are free for custom use, like other ACP extension methods.
3250/// Protocol names that do not begin with `_` are reserved for the ACP spec.
3251#[cfg(feature = "unstable_llm_providers")]
3252#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3253#[serde(rename_all = "snake_case")]
3254#[non_exhaustive]
3255#[expect(clippy::doc_markdown)]
3256pub enum LlmProtocol {
3257 /// Anthropic API protocol.
3258 Anthropic,
3259 /// OpenAI API protocol.
3260 #[serde(rename = "openai")]
3261 OpenAi,
3262 /// Azure OpenAI API protocol.
3263 Azure,
3264 /// Google Vertex AI API protocol.
3265 Vertex,
3266 /// AWS Bedrock API protocol.
3267 Bedrock,
3268 /// Custom or future protocol.
3269 ///
3270 /// Values beginning with `_` are reserved for implementation-specific
3271 /// extensions. Unknown values that do not begin with `_` are reserved for
3272 /// future ACP variants.
3273 #[serde(untagged)]
3274 Other(String),
3275}
3276
3277/// **UNSTABLE**
3278///
3279/// This capability is not part of the spec yet, and may be removed or changed at any point.
3280///
3281/// Current effective non-secret routing configuration for a provider.
3282#[cfg(feature = "unstable_llm_providers")]
3283#[skip_serializing_none]
3284#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3285#[serde(rename_all = "camelCase")]
3286#[non_exhaustive]
3287pub struct ProviderCurrentConfig {
3288 /// Protocol currently used by this provider.
3289 pub api_type: LlmProtocol,
3290 /// Base URL currently used by this provider.
3291 pub base_url: String,
3292 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3293 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3294 /// these keys.
3295 ///
3296 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3297 #[serde(rename = "_meta")]
3298 pub meta: Option<Meta>,
3299}
3300
3301#[cfg(feature = "unstable_llm_providers")]
3302impl ProviderCurrentConfig {
3303 /// Builds [`ProviderCurrentConfig`] with the required fields set; optional fields start unset or empty.
3304 #[must_use]
3305 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3306 Self {
3307 api_type,
3308 base_url: base_url.into(),
3309 meta: None,
3310 }
3311 }
3312
3313 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3314 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3315 /// these keys.
3316 ///
3317 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3318 #[must_use]
3319 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3320 self.meta = meta.into_option();
3321 self
3322 }
3323}
3324
3325/// **UNSTABLE**
3326///
3327/// This capability is not part of the spec yet, and may be removed or changed at any point.
3328///
3329/// Information about a configurable LLM provider.
3330#[cfg(feature = "unstable_llm_providers")]
3331#[serde_as]
3332#[skip_serializing_none]
3333#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3334#[serde(rename_all = "camelCase")]
3335#[non_exhaustive]
3336pub struct ProviderInfo {
3337 /// Provider identifier, for example "main" or "openai".
3338 pub id: String,
3339 /// Supported protocol types for this provider.
3340 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3341 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3342 pub supported: Vec<LlmProtocol>,
3343 /// Whether this provider is mandatory and cannot be disabled via `providers/disable`.
3344 /// If true, clients must not call `providers/disable` for this id.
3345 pub required: bool,
3346 /// Current effective non-secret routing config.
3347 /// Null or omitted means provider is disabled.
3348 pub current: Option<ProviderCurrentConfig>,
3349 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3350 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3351 /// these keys.
3352 ///
3353 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3354 #[serde(rename = "_meta")]
3355 pub meta: Option<Meta>,
3356}
3357
3358#[cfg(feature = "unstable_llm_providers")]
3359impl ProviderInfo {
3360 /// Builds [`ProviderInfo`] with the required fields set; optional fields start unset or empty.
3361 #[must_use]
3362 pub fn new(
3363 id: impl Into<String>,
3364 supported: Vec<LlmProtocol>,
3365 required: bool,
3366 current: impl IntoOption<ProviderCurrentConfig>,
3367 ) -> Self {
3368 Self {
3369 id: id.into(),
3370 supported,
3371 required,
3372 current: current.into_option(),
3373 meta: None,
3374 }
3375 }
3376
3377 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3378 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3379 /// these keys.
3380 ///
3381 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3382 #[must_use]
3383 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3384 self.meta = meta.into_option();
3385 self
3386 }
3387}
3388
3389/// **UNSTABLE**
3390///
3391/// This capability is not part of the spec yet, and may be removed or changed at any point.
3392///
3393/// Request parameters for `providers/list`.
3394#[cfg(feature = "unstable_llm_providers")]
3395#[skip_serializing_none]
3396#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3397#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3398#[serde(rename_all = "camelCase")]
3399#[non_exhaustive]
3400pub struct ListProvidersRequest {
3401 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3402 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3403 /// these keys.
3404 ///
3405 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3406 #[serde(rename = "_meta")]
3407 pub meta: Option<Meta>,
3408}
3409
3410#[cfg(feature = "unstable_llm_providers")]
3411impl ListProvidersRequest {
3412 /// Builds [`ListProvidersRequest`] with the required request fields set; optional fields start unset or empty.
3413 #[must_use]
3414 pub fn new() -> Self {
3415 Self::default()
3416 }
3417
3418 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3419 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3420 /// these keys.
3421 ///
3422 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3423 #[must_use]
3424 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3425 self.meta = meta.into_option();
3426 self
3427 }
3428}
3429
3430/// **UNSTABLE**
3431///
3432/// This capability is not part of the spec yet, and may be removed or changed at any point.
3433///
3434/// Response to `providers/list`.
3435#[cfg(feature = "unstable_llm_providers")]
3436#[serde_as]
3437#[skip_serializing_none]
3438#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3439#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3440#[serde(rename_all = "camelCase")]
3441#[non_exhaustive]
3442pub struct ListProvidersResponse {
3443 /// Configurable providers with current routing info suitable for UI display.
3444 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3445 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3446 pub providers: Vec<ProviderInfo>,
3447 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3448 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3449 /// these keys.
3450 ///
3451 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3452 #[serde(rename = "_meta")]
3453 pub meta: Option<Meta>,
3454}
3455
3456#[cfg(feature = "unstable_llm_providers")]
3457impl ListProvidersResponse {
3458 /// Builds [`ListProvidersResponse`] with the required response fields set; optional fields start unset or empty.
3459 #[must_use]
3460 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3461 Self {
3462 providers,
3463 meta: None,
3464 }
3465 }
3466
3467 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3468 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3469 /// these keys.
3470 ///
3471 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3472 #[must_use]
3473 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3474 self.meta = meta.into_option();
3475 self
3476 }
3477}
3478
3479/// **UNSTABLE**
3480///
3481/// This capability is not part of the spec yet, and may be removed or changed at any point.
3482///
3483/// Request parameters for `providers/set`.
3484///
3485/// Replaces the full configuration for one provider id.
3486#[cfg(feature = "unstable_llm_providers")]
3487#[skip_serializing_none]
3488#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3489#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3490#[serde(rename_all = "camelCase")]
3491#[non_exhaustive]
3492pub struct SetProviderRequest {
3493 /// Provider id to configure.
3494 pub id: String,
3495 /// Protocol type for this provider.
3496 pub api_type: LlmProtocol,
3497 /// Base URL for requests sent through this provider.
3498 pub base_url: String,
3499 /// Full headers map for this provider.
3500 /// May include authorization, routing, or other integration-specific headers.
3501 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3502 pub headers: HashMap<String, String>,
3503 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3504 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3505 /// these keys.
3506 ///
3507 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3508 #[serde(rename = "_meta")]
3509 pub meta: Option<Meta>,
3510}
3511
3512#[cfg(feature = "unstable_llm_providers")]
3513impl SetProviderRequest {
3514 /// Builds [`SetProviderRequest`] with the required request fields set; optional fields start unset or empty.
3515 #[must_use]
3516 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3517 Self {
3518 id: id.into(),
3519 api_type,
3520 base_url: base_url.into(),
3521 headers: HashMap::new(),
3522 meta: None,
3523 }
3524 }
3525
3526 /// Full headers map for this provider.
3527 /// May include authorization, routing, or other integration-specific headers.
3528 #[must_use]
3529 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3530 self.headers = headers;
3531 self
3532 }
3533
3534 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3535 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3536 /// these keys.
3537 ///
3538 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3539 #[must_use]
3540 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3541 self.meta = meta.into_option();
3542 self
3543 }
3544}
3545
3546/// **UNSTABLE**
3547///
3548/// This capability is not part of the spec yet, and may be removed or changed at any point.
3549///
3550/// Response to `providers/set`.
3551#[cfg(feature = "unstable_llm_providers")]
3552#[skip_serializing_none]
3553#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3554#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3555#[serde(rename_all = "camelCase")]
3556#[non_exhaustive]
3557pub struct SetProviderResponse {
3558 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3559 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3560 /// these keys.
3561 ///
3562 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3563 #[serde(rename = "_meta")]
3564 pub meta: Option<Meta>,
3565}
3566
3567#[cfg(feature = "unstable_llm_providers")]
3568impl SetProviderResponse {
3569 /// Builds [`SetProviderResponse`] with the required response fields set; optional fields start unset or empty.
3570 #[must_use]
3571 pub fn new() -> Self {
3572 Self::default()
3573 }
3574
3575 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3576 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3577 /// these keys.
3578 ///
3579 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3580 #[must_use]
3581 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3582 self.meta = meta.into_option();
3583 self
3584 }
3585}
3586
3587/// **UNSTABLE**
3588///
3589/// This capability is not part of the spec yet, and may be removed or changed at any point.
3590///
3591/// Request parameters for `providers/disable`.
3592#[cfg(feature = "unstable_llm_providers")]
3593#[skip_serializing_none]
3594#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3595#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3596#[serde(rename_all = "camelCase")]
3597#[non_exhaustive]
3598pub struct DisableProviderRequest {
3599 /// Provider id to disable.
3600 pub id: String,
3601 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3602 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3603 /// these keys.
3604 ///
3605 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3606 #[serde(rename = "_meta")]
3607 pub meta: Option<Meta>,
3608}
3609
3610#[cfg(feature = "unstable_llm_providers")]
3611impl DisableProviderRequest {
3612 /// Builds [`DisableProviderRequest`] with the required request fields set; optional fields start unset or empty.
3613 #[must_use]
3614 pub fn new(id: impl Into<String>) -> Self {
3615 Self {
3616 id: id.into(),
3617 meta: None,
3618 }
3619 }
3620
3621 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3622 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3623 /// these keys.
3624 ///
3625 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3626 #[must_use]
3627 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3628 self.meta = meta.into_option();
3629 self
3630 }
3631}
3632
3633/// **UNSTABLE**
3634///
3635/// This capability is not part of the spec yet, and may be removed or changed at any point.
3636///
3637/// Response to `providers/disable`.
3638#[cfg(feature = "unstable_llm_providers")]
3639#[skip_serializing_none]
3640#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3641#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3642#[serde(rename_all = "camelCase")]
3643#[non_exhaustive]
3644pub struct DisableProviderResponse {
3645 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3646 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3647 /// these keys.
3648 ///
3649 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3650 #[serde(rename = "_meta")]
3651 pub meta: Option<Meta>,
3652}
3653
3654#[cfg(feature = "unstable_llm_providers")]
3655impl DisableProviderResponse {
3656 /// Builds [`DisableProviderResponse`] with the required response fields set; optional fields start unset or empty.
3657 #[must_use]
3658 pub fn new() -> Self {
3659 Self::default()
3660 }
3661
3662 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3663 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3664 /// these keys.
3665 ///
3666 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3667 #[must_use]
3668 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3669 self.meta = meta.into_option();
3670 self
3671 }
3672}
3673
3674// Capabilities
3675
3676/// Capabilities supported by the agent.
3677///
3678/// Advertised during initialization to inform the client about
3679/// available features and content types.
3680///
3681/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
3682#[serde_as]
3683#[skip_serializing_none]
3684#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3685#[serde(rename_all = "camelCase")]
3686#[non_exhaustive]
3687pub struct AgentCapabilities {
3688 /// Session capabilities supported by the agent.
3689 ///
3690 /// Optional. Omitted or `null` both mean the agent does not support the
3691 /// `session/*` method surface. Supplying `{}` means the agent supports the
3692 /// baseline session methods: `session/new`, `session/prompt`,
3693 /// `session/cancel`, and `session/update`.
3694 #[serde_as(deserialize_as = "DefaultOnError")]
3695 #[schemars(extend("x-deserialize-default-on-error" = true))]
3696 #[serde(default)]
3697 pub session: Option<SessionCapabilities>,
3698 /// Authentication-related capabilities supported by the agent.
3699 #[serde(default)]
3700 pub auth: AgentAuthCapabilities,
3701 /// **UNSTABLE**
3702 ///
3703 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3704 ///
3705 /// Provider configuration capabilities supported by the agent.
3706 ///
3707 /// By supplying `{}` it means that the agent supports provider configuration methods.
3708 #[cfg(feature = "unstable_llm_providers")]
3709 #[serde_as(deserialize_as = "DefaultOnError")]
3710 #[schemars(extend("x-deserialize-default-on-error" = true))]
3711 #[serde(default)]
3712 pub providers: Option<ProvidersCapabilities>,
3713 /// **UNSTABLE**
3714 ///
3715 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3716 ///
3717 /// NES (Next Edit Suggestions) capabilities supported by the agent.
3718 #[cfg(feature = "unstable_nes")]
3719 #[serde_as(deserialize_as = "DefaultOnError")]
3720 #[schemars(extend("x-deserialize-default-on-error" = true))]
3721 #[serde(default)]
3722 pub nes: Option<NesCapabilities>,
3723 /// **UNSTABLE**
3724 ///
3725 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3726 ///
3727 /// The position encoding selected by the agent from the client's supported encodings.
3728 #[cfg(feature = "unstable_nes")]
3729 #[serde_as(deserialize_as = "DefaultOnError")]
3730 #[schemars(extend("x-deserialize-default-on-error" = true))]
3731 #[serde(default)]
3732 pub position_encoding: Option<PositionEncodingKind>,
3733 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3734 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3735 /// these keys.
3736 ///
3737 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3738 #[serde(rename = "_meta")]
3739 pub meta: Option<Meta>,
3740}
3741
3742impl AgentCapabilities {
3743 /// Builds an empty [`AgentCapabilities`]; use builder methods to advertise supported sub-capabilities.
3744 #[must_use]
3745 pub fn new() -> Self {
3746 Self::default()
3747 }
3748
3749 /// Session capabilities supported by the agent.
3750 ///
3751 /// Omitted or `null` both mean the agent does not support the `session/*`
3752 /// method surface. Supplying `{}` means the agent supports the baseline
3753 /// session methods: `session/new`, `session/prompt`, `session/cancel`, and
3754 /// `session/update`.
3755 #[must_use]
3756 pub fn session(mut self, session: impl IntoOption<SessionCapabilities>) -> Self {
3757 self.session = session.into_option();
3758 self
3759 }
3760
3761 /// Authentication-related capabilities supported by the agent.
3762 #[must_use]
3763 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
3764 self.auth = auth;
3765 self
3766 }
3767
3768 /// **UNSTABLE**
3769 ///
3770 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3771 ///
3772 /// Provider configuration capabilities supported by the agent.
3773 #[cfg(feature = "unstable_llm_providers")]
3774 #[must_use]
3775 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
3776 self.providers = providers.into_option();
3777 self
3778 }
3779
3780 /// **UNSTABLE**
3781 ///
3782 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3783 ///
3784 /// NES (Next Edit Suggestions) capabilities supported by the agent.
3785 #[cfg(feature = "unstable_nes")]
3786 #[must_use]
3787 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
3788 self.nes = nes.into_option();
3789 self
3790 }
3791
3792 /// **UNSTABLE**
3793 ///
3794 /// The position encoding selected by the agent from the client's supported encodings.
3795 #[cfg(feature = "unstable_nes")]
3796 #[must_use]
3797 pub fn position_encoding(
3798 mut self,
3799 position_encoding: impl IntoOption<PositionEncodingKind>,
3800 ) -> Self {
3801 self.position_encoding = position_encoding.into_option();
3802 self
3803 }
3804
3805 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3806 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3807 /// these keys.
3808 ///
3809 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3810 #[must_use]
3811 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3812 self.meta = meta.into_option();
3813 self
3814 }
3815}
3816
3817/// **UNSTABLE**
3818///
3819/// This capability is not part of the spec yet, and may be removed or changed at any point.
3820///
3821/// Provider configuration capabilities supported by the agent.
3822///
3823/// By supplying `{}` it means that the agent supports provider configuration methods.
3824#[cfg(feature = "unstable_llm_providers")]
3825#[skip_serializing_none]
3826#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3827#[non_exhaustive]
3828pub struct ProvidersCapabilities {
3829 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3830 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3831 /// these keys.
3832 ///
3833 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3834 #[serde(rename = "_meta")]
3835 pub meta: Option<Meta>,
3836}
3837
3838#[cfg(feature = "unstable_llm_providers")]
3839impl ProvidersCapabilities {
3840 /// Builds an empty [`ProvidersCapabilities`]; use builder methods to advertise supported sub-capabilities.
3841 #[must_use]
3842 pub fn new() -> Self {
3843 Self::default()
3844 }
3845
3846 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3847 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3848 /// these keys.
3849 ///
3850 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3851 #[must_use]
3852 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3853 self.meta = meta.into_option();
3854 self
3855 }
3856}
3857
3858/// Session capabilities supported by the agent.
3859///
3860/// Supplying `{}` means the agent supports the baseline session methods:
3861/// `session/new`, `session/prompt`, `session/cancel`, and `session/update`.
3862///
3863/// Agents that support sessions **MAY** support additional session methods,
3864/// prompt content types, and MCP transports by specifying additional
3865/// capabilities.
3866///
3867/// See protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)
3868#[serde_as]
3869#[skip_serializing_none]
3870#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3871#[serde(rename_all = "camelCase")]
3872#[non_exhaustive]
3873pub struct SessionCapabilities {
3874 /// Prompt capabilities supported by the agent in `session/prompt` requests.
3875 ///
3876 /// Optional. Omitted or `null` both mean the agent does not advertise any
3877 /// prompt extensions beyond the baseline text and resource-link content
3878 /// required by `session/prompt`.
3879 #[serde_as(deserialize_as = "DefaultOnError")]
3880 #[schemars(extend("x-deserialize-default-on-error" = true))]
3881 #[serde(default)]
3882 pub prompt: Option<PromptCapabilities>,
3883 /// MCP capabilities supported by the agent for session lifecycle requests.
3884 ///
3885 /// Optional. Omitted or `null` both mean the agent does not advertise MCP
3886 /// server transport support for sessions.
3887 #[serde_as(deserialize_as = "DefaultOnError")]
3888 #[schemars(extend("x-deserialize-default-on-error" = true))]
3889 #[serde(default)]
3890 pub mcp: Option<McpCapabilities>,
3891 /// Whether the agent supports `session/load`.
3892 ///
3893 /// Optional. Omitted or `null` both mean the agent does not advertise support.
3894 /// Supplying `{}` means the agent supports loading sessions.
3895 #[serde_as(deserialize_as = "DefaultOnError")]
3896 #[schemars(extend("x-deserialize-default-on-error" = true))]
3897 #[serde(default)]
3898 pub load: Option<SessionLoadCapabilities>,
3899 /// Whether the agent supports `session/list`.
3900 #[serde_as(deserialize_as = "DefaultOnError")]
3901 #[schemars(extend("x-deserialize-default-on-error" = true))]
3902 #[serde(default)]
3903 pub list: Option<SessionListCapabilities>,
3904 /// Whether the agent supports `session/delete`.
3905 ///
3906 /// Optional. Omitted or `null` both mean the agent does not advertise support.
3907 /// Supplying `{}` means the agent supports deleting sessions from `session/list`.
3908 #[serde_as(deserialize_as = "DefaultOnError")]
3909 #[schemars(extend("x-deserialize-default-on-error" = true))]
3910 #[serde(default)]
3911 pub delete: Option<SessionDeleteCapabilities>,
3912 /// Whether the agent supports `additionalDirectories` on supported session lifecycle requests.
3913 ///
3914 /// Agents that also support `session/list` may return
3915 /// `SessionInfo.additionalDirectories` to report the complete ordered
3916 /// additional-root list associated with a listed session.
3917 #[serde_as(deserialize_as = "DefaultOnError")]
3918 #[schemars(extend("x-deserialize-default-on-error" = true))]
3919 #[serde(default)]
3920 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
3921 /// **UNSTABLE**
3922 ///
3923 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3924 ///
3925 /// Whether the agent supports `session/fork`.
3926 #[cfg(feature = "unstable_session_fork")]
3927 #[serde_as(deserialize_as = "DefaultOnError")]
3928 #[schemars(extend("x-deserialize-default-on-error" = true))]
3929 #[serde(default)]
3930 pub fork: Option<SessionForkCapabilities>,
3931 /// Whether the agent supports `session/resume`.
3932 #[serde_as(deserialize_as = "DefaultOnError")]
3933 #[schemars(extend("x-deserialize-default-on-error" = true))]
3934 #[serde(default)]
3935 pub resume: Option<SessionResumeCapabilities>,
3936 /// Whether the agent supports `session/close`.
3937 #[serde_as(deserialize_as = "DefaultOnError")]
3938 #[schemars(extend("x-deserialize-default-on-error" = true))]
3939 #[serde(default)]
3940 pub close: Option<SessionCloseCapabilities>,
3941 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3942 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3943 /// these keys.
3944 ///
3945 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3946 #[serde(rename = "_meta")]
3947 pub meta: Option<Meta>,
3948}
3949
3950impl SessionCapabilities {
3951 /// Builds an empty [`SessionCapabilities`]; use builder methods to advertise supported sub-capabilities.
3952 #[must_use]
3953 pub fn new() -> Self {
3954 Self::default()
3955 }
3956
3957 /// Prompt capabilities supported by the agent in `session/prompt` requests.
3958 ///
3959 /// Omitted or `null` both mean the agent does not advertise any prompt
3960 /// extensions beyond the baseline text and resource-link content required by
3961 /// `session/prompt`.
3962 #[must_use]
3963 pub fn prompt(mut self, prompt: impl IntoOption<PromptCapabilities>) -> Self {
3964 self.prompt = prompt.into_option();
3965 self
3966 }
3967
3968 /// MCP capabilities supported by the agent for session lifecycle requests.
3969 ///
3970 /// Omitted or `null` both mean the agent does not advertise MCP server
3971 /// transport support for sessions.
3972 #[must_use]
3973 pub fn mcp(mut self, mcp: impl IntoOption<McpCapabilities>) -> Self {
3974 self.mcp = mcp.into_option();
3975 self
3976 }
3977
3978 /// Whether the agent supports `session/load`.
3979 ///
3980 /// Omitted or `null` both mean the agent does not advertise support.
3981 /// Supplying `{}` means the agent supports loading sessions.
3982 #[must_use]
3983 pub fn load(mut self, load: impl IntoOption<SessionLoadCapabilities>) -> Self {
3984 self.load = load.into_option();
3985 self
3986 }
3987
3988 /// Whether the agent supports `session/list`.
3989 #[must_use]
3990 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
3991 self.list = list.into_option();
3992 self
3993 }
3994
3995 /// Whether the agent supports `session/delete`.
3996 ///
3997 /// Omitted or `null` both mean the agent does not advertise support.
3998 /// Supplying `{}` means the agent supports deleting sessions from `session/list`.
3999 #[must_use]
4000 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4001 self.delete = delete.into_option();
4002 self
4003 }
4004
4005 /// Whether the agent supports `additionalDirectories` on supported session lifecycle requests.
4006 ///
4007 /// Agents that also support `session/list` may return
4008 /// `SessionInfo.additionalDirectories` to report the complete ordered
4009 /// additional-root list associated with a listed session.
4010 #[must_use]
4011 pub fn additional_directories(
4012 mut self,
4013 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4014 ) -> Self {
4015 self.additional_directories = additional_directories.into_option();
4016 self
4017 }
4018
4019 #[cfg(feature = "unstable_session_fork")]
4020 /// Whether the agent supports `session/fork`.
4021 #[must_use]
4022 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4023 self.fork = fork.into_option();
4024 self
4025 }
4026
4027 /// Whether the agent supports `session/resume`.
4028 #[must_use]
4029 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4030 self.resume = resume.into_option();
4031 self
4032 }
4033
4034 /// Whether the agent supports `session/close`.
4035 #[must_use]
4036 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4037 self.close = close.into_option();
4038 self
4039 }
4040
4041 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4042 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4043 /// these keys.
4044 ///
4045 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4046 #[must_use]
4047 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4048 self.meta = meta.into_option();
4049 self
4050 }
4051}
4052
4053/// Capabilities for the `session/load` method.
4054///
4055/// Supplying `{}` means the agent supports loading sessions.
4056#[skip_serializing_none]
4057#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4058#[non_exhaustive]
4059pub struct SessionLoadCapabilities {
4060 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4061 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4062 /// these keys.
4063 ///
4064 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4065 #[serde(rename = "_meta")]
4066 pub meta: Option<Meta>,
4067}
4068
4069impl SessionLoadCapabilities {
4070 /// Builds an empty [`SessionLoadCapabilities`]; use builder methods to advertise supported sub-capabilities.
4071 #[must_use]
4072 pub fn new() -> Self {
4073 Self::default()
4074 }
4075
4076 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4077 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4078 /// these keys.
4079 ///
4080 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4081 #[must_use]
4082 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4083 self.meta = meta.into_option();
4084 self
4085 }
4086}
4087
4088/// Capabilities for the `session/list` method.
4089///
4090/// By supplying `{}` it means that the agent supports listing of sessions.
4091#[skip_serializing_none]
4092#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4093#[non_exhaustive]
4094pub struct SessionListCapabilities {
4095 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4096 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4097 /// these keys.
4098 ///
4099 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4100 #[serde(rename = "_meta")]
4101 pub meta: Option<Meta>,
4102}
4103
4104impl SessionListCapabilities {
4105 /// Builds an empty [`SessionListCapabilities`]; use builder methods to advertise supported sub-capabilities.
4106 #[must_use]
4107 pub fn new() -> Self {
4108 Self::default()
4109 }
4110
4111 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4112 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4113 /// these keys.
4114 ///
4115 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4116 #[must_use]
4117 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4118 self.meta = meta.into_option();
4119 self
4120 }
4121}
4122
4123/// Capabilities for the `session/delete` method.
4124///
4125/// Supplying `{}` means the agent supports deleting sessions from `session/list`.
4126#[skip_serializing_none]
4127#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4128#[non_exhaustive]
4129pub struct SessionDeleteCapabilities {
4130 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4131 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4132 /// these keys.
4133 ///
4134 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4135 #[serde(rename = "_meta")]
4136 pub meta: Option<Meta>,
4137}
4138
4139impl SessionDeleteCapabilities {
4140 /// Builds an empty [`SessionDeleteCapabilities`]; use builder methods to advertise supported sub-capabilities.
4141 #[must_use]
4142 pub fn new() -> Self {
4143 Self::default()
4144 }
4145
4146 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4147 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4148 /// these keys.
4149 ///
4150 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4151 #[must_use]
4152 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4153 self.meta = meta.into_option();
4154 self
4155 }
4156}
4157
4158/// Capabilities for additional session directories support.
4159///
4160/// By supplying `{}` it means that the agent supports the `additionalDirectories`
4161/// field on supported session lifecycle requests. Agents that also support
4162/// `session/list` may return `SessionInfo.additionalDirectories` to report the
4163/// complete ordered additional-root list associated with a listed session.
4164#[skip_serializing_none]
4165#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4166#[non_exhaustive]
4167pub struct SessionAdditionalDirectoriesCapabilities {
4168 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4169 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4170 /// these keys.
4171 ///
4172 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4173 #[serde(rename = "_meta")]
4174 pub meta: Option<Meta>,
4175}
4176
4177impl SessionAdditionalDirectoriesCapabilities {
4178 /// Builds an empty [`SessionAdditionalDirectoriesCapabilities`]; use builder methods to advertise supported sub-capabilities.
4179 #[must_use]
4180 pub fn new() -> Self {
4181 Self::default()
4182 }
4183
4184 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4185 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4186 /// these keys.
4187 ///
4188 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4189 #[must_use]
4190 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4191 self.meta = meta.into_option();
4192 self
4193 }
4194}
4195
4196/// **UNSTABLE**
4197///
4198/// This capability is not part of the spec yet, and may be removed or changed at any point.
4199///
4200/// Capabilities for the `session/fork` method.
4201///
4202/// By supplying `{}` it means that the agent supports forking of sessions.
4203#[cfg(feature = "unstable_session_fork")]
4204#[skip_serializing_none]
4205#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4206#[non_exhaustive]
4207pub struct SessionForkCapabilities {
4208 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4209 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4210 /// these keys.
4211 ///
4212 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4213 #[serde(rename = "_meta")]
4214 pub meta: Option<Meta>,
4215}
4216
4217#[cfg(feature = "unstable_session_fork")]
4218impl SessionForkCapabilities {
4219 /// Builds an empty [`SessionForkCapabilities`]; use builder methods to advertise supported sub-capabilities.
4220 #[must_use]
4221 pub fn new() -> Self {
4222 Self::default()
4223 }
4224
4225 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4226 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4227 /// these keys.
4228 ///
4229 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4230 #[must_use]
4231 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4232 self.meta = meta.into_option();
4233 self
4234 }
4235}
4236
4237/// Capabilities for the `session/resume` method.
4238///
4239/// By supplying `{}` it means that the agent supports resuming of sessions.
4240#[skip_serializing_none]
4241#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4242#[non_exhaustive]
4243pub struct SessionResumeCapabilities {
4244 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4245 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4246 /// these keys.
4247 ///
4248 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4249 #[serde(rename = "_meta")]
4250 pub meta: Option<Meta>,
4251}
4252
4253impl SessionResumeCapabilities {
4254 /// Builds an empty [`SessionResumeCapabilities`]; use builder methods to advertise supported sub-capabilities.
4255 #[must_use]
4256 pub fn new() -> Self {
4257 Self::default()
4258 }
4259
4260 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4261 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4262 /// these keys.
4263 ///
4264 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4265 #[must_use]
4266 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4267 self.meta = meta.into_option();
4268 self
4269 }
4270}
4271
4272/// Capabilities for the `session/close` method.
4273///
4274/// By supplying `{}` it means that the agent supports closing of sessions.
4275#[skip_serializing_none]
4276#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4277#[non_exhaustive]
4278pub struct SessionCloseCapabilities {
4279 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4280 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4281 /// these keys.
4282 ///
4283 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4284 #[serde(rename = "_meta")]
4285 pub meta: Option<Meta>,
4286}
4287
4288impl SessionCloseCapabilities {
4289 /// Builds an empty [`SessionCloseCapabilities`]; use builder methods to advertise supported sub-capabilities.
4290 #[must_use]
4291 pub fn new() -> Self {
4292 Self::default()
4293 }
4294
4295 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4296 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4297 /// these keys.
4298 ///
4299 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4300 #[must_use]
4301 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4302 self.meta = meta.into_option();
4303 self
4304 }
4305}
4306
4307/// Prompt capabilities supported by the agent in `session/prompt` requests.
4308///
4309/// Baseline agent functionality requires support for [`ContentBlock::Text`]
4310/// and [`ContentBlock::ResourceLink`] in prompt requests.
4311///
4312/// Other variants must be explicitly opted in to.
4313/// Capabilities for different types of content in prompt requests.
4314///
4315/// Indicates which content types beyond the baseline (text and resource links)
4316/// the agent can process.
4317///
4318/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
4319#[serde_as]
4320#[skip_serializing_none]
4321#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4322#[serde(rename_all = "camelCase")]
4323#[non_exhaustive]
4324pub struct PromptCapabilities {
4325 /// Agent supports [`ContentBlock::Image`].
4326 ///
4327 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4328 /// Supplying `{}` means the agent supports image content in prompts.
4329 #[serde_as(deserialize_as = "DefaultOnError")]
4330 #[schemars(extend("x-deserialize-default-on-error" = true))]
4331 #[serde(default)]
4332 pub image: Option<PromptImageCapabilities>,
4333 /// Agent supports [`ContentBlock::Audio`].
4334 ///
4335 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4336 /// Supplying `{}` means the agent supports audio content in prompts.
4337 #[serde_as(deserialize_as = "DefaultOnError")]
4338 #[schemars(extend("x-deserialize-default-on-error" = true))]
4339 #[serde(default)]
4340 pub audio: Option<PromptAudioCapabilities>,
4341 /// Agent supports embedded context in `session/prompt` requests.
4342 ///
4343 /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
4344 /// in prompt requests for pieces of context that are referenced in the message.
4345 ///
4346 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4347 /// Supplying `{}` means the agent supports embedded context in prompts.
4348 #[serde_as(deserialize_as = "DefaultOnError")]
4349 #[schemars(extend("x-deserialize-default-on-error" = true))]
4350 #[serde(default)]
4351 pub embedded_context: Option<PromptEmbeddedContextCapabilities>,
4352 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4353 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4354 /// these keys.
4355 ///
4356 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4357 #[serde(rename = "_meta")]
4358 pub meta: Option<Meta>,
4359}
4360
4361impl PromptCapabilities {
4362 /// Builds an empty [`PromptCapabilities`]; use builder methods to advertise supported sub-capabilities.
4363 #[must_use]
4364 pub fn new() -> Self {
4365 Self::default()
4366 }
4367
4368 /// Agent supports [`ContentBlock::Image`].
4369 ///
4370 /// Omitted or `null` both mean the agent does not advertise support.
4371 /// Supplying `{}` means the agent supports image content in prompts.
4372 #[must_use]
4373 pub fn image(mut self, image: impl IntoOption<PromptImageCapabilities>) -> Self {
4374 self.image = image.into_option();
4375 self
4376 }
4377
4378 /// Agent supports [`ContentBlock::Audio`].
4379 ///
4380 /// Omitted or `null` both mean the agent does not advertise support.
4381 /// Supplying `{}` means the agent supports audio content in prompts.
4382 #[must_use]
4383 pub fn audio(mut self, audio: impl IntoOption<PromptAudioCapabilities>) -> Self {
4384 self.audio = audio.into_option();
4385 self
4386 }
4387
4388 /// Agent supports embedded context in `session/prompt` requests.
4389 ///
4390 /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
4391 /// in prompt requests for pieces of context that are referenced in the message.
4392 ///
4393 /// Omitted or `null` both mean the agent does not advertise support.
4394 /// Supplying `{}` means the agent supports embedded context in prompts.
4395 #[must_use]
4396 pub fn embedded_context(
4397 mut self,
4398 embedded_context: impl IntoOption<PromptEmbeddedContextCapabilities>,
4399 ) -> Self {
4400 self.embedded_context = embedded_context.into_option();
4401 self
4402 }
4403
4404 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4405 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4406 /// these keys.
4407 ///
4408 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4409 #[must_use]
4410 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4411 self.meta = meta.into_option();
4412 self
4413 }
4414}
4415
4416/// Capabilities for image content in prompt requests.
4417///
4418/// Supplying `{}` means the agent supports image content in prompts.
4419#[skip_serializing_none]
4420#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4421#[non_exhaustive]
4422pub struct PromptImageCapabilities {
4423 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4424 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4425 /// these keys.
4426 ///
4427 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4428 #[serde(rename = "_meta")]
4429 pub meta: Option<Meta>,
4430}
4431
4432impl PromptImageCapabilities {
4433 /// Builds an empty [`PromptImageCapabilities`]; use builder methods to advertise supported sub-capabilities.
4434 #[must_use]
4435 pub fn new() -> Self {
4436 Self::default()
4437 }
4438
4439 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4440 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4441 /// these keys.
4442 ///
4443 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4444 #[must_use]
4445 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4446 self.meta = meta.into_option();
4447 self
4448 }
4449}
4450
4451/// Capabilities for audio content in prompt requests.
4452///
4453/// Supplying `{}` means the agent supports audio content in prompts.
4454#[skip_serializing_none]
4455#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4456#[non_exhaustive]
4457pub struct PromptAudioCapabilities {
4458 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4459 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4460 /// these keys.
4461 ///
4462 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4463 #[serde(rename = "_meta")]
4464 pub meta: Option<Meta>,
4465}
4466
4467impl PromptAudioCapabilities {
4468 /// Builds an empty [`PromptAudioCapabilities`]; use builder methods to advertise supported sub-capabilities.
4469 #[must_use]
4470 pub fn new() -> Self {
4471 Self::default()
4472 }
4473
4474 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4475 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4476 /// these keys.
4477 ///
4478 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4479 #[must_use]
4480 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4481 self.meta = meta.into_option();
4482 self
4483 }
4484}
4485
4486/// Capabilities for embedded context in prompt requests.
4487///
4488/// Supplying `{}` means the agent supports embedded context in prompts.
4489#[skip_serializing_none]
4490#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4491#[non_exhaustive]
4492pub struct PromptEmbeddedContextCapabilities {
4493 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4494 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4495 /// these keys.
4496 ///
4497 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4498 #[serde(rename = "_meta")]
4499 pub meta: Option<Meta>,
4500}
4501
4502impl PromptEmbeddedContextCapabilities {
4503 /// Builds an empty [`PromptEmbeddedContextCapabilities`]; use builder methods to advertise supported sub-capabilities.
4504 #[must_use]
4505 pub fn new() -> Self {
4506 Self::default()
4507 }
4508
4509 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4510 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4511 /// these keys.
4512 ///
4513 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4514 #[must_use]
4515 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4516 self.meta = meta.into_option();
4517 self
4518 }
4519}
4520
4521/// MCP capabilities supported by the agent for session lifecycle requests.
4522#[serde_as]
4523#[skip_serializing_none]
4524#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4525#[serde(rename_all = "camelCase")]
4526#[non_exhaustive]
4527pub struct McpCapabilities {
4528 /// Agent supports [`McpServer::Stdio`].
4529 ///
4530 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4531 /// Supplying `{}` means the agent supports stdio MCP server transports.
4532 #[serde_as(deserialize_as = "DefaultOnError")]
4533 #[schemars(extend("x-deserialize-default-on-error" = true))]
4534 #[serde(default)]
4535 pub stdio: Option<McpStdioCapabilities>,
4536 /// Agent supports [`McpServer::Http`].
4537 ///
4538 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4539 /// Supplying `{}` means the agent supports HTTP MCP server transports.
4540 #[serde_as(deserialize_as = "DefaultOnError")]
4541 #[schemars(extend("x-deserialize-default-on-error" = true))]
4542 #[serde(default)]
4543 pub http: Option<McpHttpCapabilities>,
4544 /// **UNSTABLE**
4545 ///
4546 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4547 ///
4548 /// Agent supports [`McpServer::Acp`].
4549 #[cfg(feature = "unstable_mcp_over_acp")]
4550 ///
4551 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4552 /// Supplying `{}` means the agent supports ACP MCP server transports.
4553 #[serde_as(deserialize_as = "DefaultOnError")]
4554 #[schemars(extend("x-deserialize-default-on-error" = true))]
4555 #[serde(default)]
4556 pub acp: Option<McpAcpCapabilities>,
4557 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4558 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4559 /// these keys.
4560 ///
4561 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4562 #[serde(rename = "_meta")]
4563 pub meta: Option<Meta>,
4564}
4565
4566impl McpCapabilities {
4567 /// Builds an empty [`McpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4568 #[must_use]
4569 pub fn new() -> Self {
4570 Self::default()
4571 }
4572
4573 /// Agent supports [`McpServer::Stdio`].
4574 ///
4575 /// Omitted or `null` both mean the agent does not advertise support.
4576 /// Supplying `{}` means the agent supports stdio MCP server transports.
4577 #[must_use]
4578 pub fn stdio(mut self, stdio: impl IntoOption<McpStdioCapabilities>) -> Self {
4579 self.stdio = stdio.into_option();
4580 self
4581 }
4582
4583 /// Agent supports [`McpServer::Http`].
4584 ///
4585 /// Omitted or `null` both mean the agent does not advertise support.
4586 /// Supplying `{}` means the agent supports HTTP MCP server transports.
4587 #[must_use]
4588 pub fn http(mut self, http: impl IntoOption<McpHttpCapabilities>) -> Self {
4589 self.http = http.into_option();
4590 self
4591 }
4592
4593 /// **UNSTABLE**
4594 ///
4595 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4596 ///
4597 /// Agent supports [`McpServer::Acp`].
4598 #[cfg(feature = "unstable_mcp_over_acp")]
4599 ///
4600 /// Omitted or `null` both mean the agent does not advertise support.
4601 /// Supplying `{}` means the agent supports ACP MCP server transports.
4602 #[must_use]
4603 pub fn acp(mut self, acp: impl IntoOption<McpAcpCapabilities>) -> Self {
4604 self.acp = acp.into_option();
4605 self
4606 }
4607
4608 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4609 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4610 /// these keys.
4611 ///
4612 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4613 #[must_use]
4614 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4615 self.meta = meta.into_option();
4616 self
4617 }
4618}
4619
4620/// Capabilities for stdio MCP server transports.
4621///
4622/// Supplying `{}` means the agent supports stdio MCP server transports.
4623#[skip_serializing_none]
4624#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4625#[non_exhaustive]
4626pub struct McpStdioCapabilities {
4627 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4628 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4629 /// these keys.
4630 ///
4631 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4632 #[serde(rename = "_meta")]
4633 pub meta: Option<Meta>,
4634}
4635
4636impl McpStdioCapabilities {
4637 /// Builds an empty [`McpStdioCapabilities`]; use builder methods to advertise supported sub-capabilities.
4638 #[must_use]
4639 pub fn new() -> Self {
4640 Self::default()
4641 }
4642
4643 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4644 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4645 /// these keys.
4646 ///
4647 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4648 #[must_use]
4649 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4650 self.meta = meta.into_option();
4651 self
4652 }
4653}
4654
4655/// Capabilities for HTTP MCP server transports.
4656///
4657/// Supplying `{}` means the agent supports HTTP MCP server transports.
4658#[skip_serializing_none]
4659#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4660#[non_exhaustive]
4661pub struct McpHttpCapabilities {
4662 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4663 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4664 /// these keys.
4665 ///
4666 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4667 #[serde(rename = "_meta")]
4668 pub meta: Option<Meta>,
4669}
4670
4671impl McpHttpCapabilities {
4672 /// Builds an empty [`McpHttpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4673 #[must_use]
4674 pub fn new() -> Self {
4675 Self::default()
4676 }
4677
4678 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4679 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4680 /// these keys.
4681 ///
4682 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4683 #[must_use]
4684 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4685 self.meta = meta.into_option();
4686 self
4687 }
4688}
4689
4690/// **UNSTABLE**
4691///
4692/// This capability is not part of the spec yet, and may be removed or changed at any point.
4693///
4694/// Capabilities for ACP MCP server transports.
4695///
4696/// Supplying `{}` means the agent supports ACP MCP server transports.
4697#[cfg(feature = "unstable_mcp_over_acp")]
4698#[skip_serializing_none]
4699#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4700#[non_exhaustive]
4701pub struct McpAcpCapabilities {
4702 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4703 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4704 /// these keys.
4705 ///
4706 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4707 #[serde(rename = "_meta")]
4708 pub meta: Option<Meta>,
4709}
4710
4711#[cfg(feature = "unstable_mcp_over_acp")]
4712impl McpAcpCapabilities {
4713 /// Builds an empty [`McpAcpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4714 #[must_use]
4715 pub fn new() -> Self {
4716 Self::default()
4717 }
4718
4719 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4720 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4721 /// these keys.
4722 ///
4723 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4724 #[must_use]
4725 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4726 self.meta = meta.into_option();
4727 self
4728 }
4729}
4730
4731// Method schema
4732
4733/// Names of all methods that agents handle.
4734///
4735/// Provides a centralized definition of method names used in the protocol.
4736#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4737#[non_exhaustive]
4738pub struct AgentMethodNames {
4739 /// Method for initializing the connection.
4740 pub initialize: &'static str,
4741 /// Method for authenticating with the agent.
4742 pub authenticate: &'static str,
4743 /// Method for listing configurable providers.
4744 #[cfg(feature = "unstable_llm_providers")]
4745 pub providers_list: &'static str,
4746 /// Method for setting provider configuration.
4747 #[cfg(feature = "unstable_llm_providers")]
4748 pub providers_set: &'static str,
4749 /// Method for disabling a provider.
4750 #[cfg(feature = "unstable_llm_providers")]
4751 pub providers_disable: &'static str,
4752 /// Method for creating a new session.
4753 pub session_new: &'static str,
4754 /// Method for loading an existing session.
4755 pub session_load: &'static str,
4756 /// Method for setting a configuration option for a session.
4757 pub session_set_config_option: &'static str,
4758 /// Method for sending a prompt to the agent.
4759 pub session_prompt: &'static str,
4760 /// Notification for cancelling operations.
4761 pub session_cancel: &'static str,
4762 /// Method for exchanging MCP-over-ACP messages.
4763 #[cfg(feature = "unstable_mcp_over_acp")]
4764 pub mcp_message: &'static str,
4765 /// Method for listing existing sessions.
4766 pub session_list: &'static str,
4767 /// Method for deleting an existing session.
4768 pub session_delete: &'static str,
4769 /// Method for forking an existing session.
4770 #[cfg(feature = "unstable_session_fork")]
4771 pub session_fork: &'static str,
4772 /// Method for resuming an existing session.
4773 pub session_resume: &'static str,
4774 /// Method for closing an active session.
4775 pub session_close: &'static str,
4776 /// Method for logging out of an authenticated session.
4777 pub logout: &'static str,
4778 /// Method for starting an NES session.
4779 #[cfg(feature = "unstable_nes")]
4780 pub nes_start: &'static str,
4781 /// Method for requesting a suggestion.
4782 #[cfg(feature = "unstable_nes")]
4783 pub nes_suggest: &'static str,
4784 /// Notification for accepting a suggestion.
4785 #[cfg(feature = "unstable_nes")]
4786 pub nes_accept: &'static str,
4787 /// Notification for rejecting a suggestion.
4788 #[cfg(feature = "unstable_nes")]
4789 pub nes_reject: &'static str,
4790 /// Method for closing an NES session.
4791 #[cfg(feature = "unstable_nes")]
4792 pub nes_close: &'static str,
4793 /// Notification for document open events.
4794 #[cfg(feature = "unstable_nes")]
4795 pub document_did_open: &'static str,
4796 /// Notification for document change events.
4797 #[cfg(feature = "unstable_nes")]
4798 pub document_did_change: &'static str,
4799 /// Notification for document close events.
4800 #[cfg(feature = "unstable_nes")]
4801 pub document_did_close: &'static str,
4802 /// Notification for document save events.
4803 #[cfg(feature = "unstable_nes")]
4804 pub document_did_save: &'static str,
4805 /// Notification for document focus events.
4806 #[cfg(feature = "unstable_nes")]
4807 pub document_did_focus: &'static str,
4808}
4809
4810/// Constant containing all agent method names.
4811pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4812 initialize: INITIALIZE_METHOD_NAME,
4813 authenticate: AUTHENTICATE_METHOD_NAME,
4814 #[cfg(feature = "unstable_llm_providers")]
4815 providers_list: PROVIDERS_LIST_METHOD_NAME,
4816 #[cfg(feature = "unstable_llm_providers")]
4817 providers_set: PROVIDERS_SET_METHOD_NAME,
4818 #[cfg(feature = "unstable_llm_providers")]
4819 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4820 session_new: SESSION_NEW_METHOD_NAME,
4821 session_load: SESSION_LOAD_METHOD_NAME,
4822 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4823 session_prompt: SESSION_PROMPT_METHOD_NAME,
4824 session_cancel: SESSION_CANCEL_METHOD_NAME,
4825 #[cfg(feature = "unstable_mcp_over_acp")]
4826 mcp_message: MCP_MESSAGE_METHOD_NAME,
4827 session_list: SESSION_LIST_METHOD_NAME,
4828 session_delete: SESSION_DELETE_METHOD_NAME,
4829 #[cfg(feature = "unstable_session_fork")]
4830 session_fork: SESSION_FORK_METHOD_NAME,
4831 session_resume: SESSION_RESUME_METHOD_NAME,
4832 session_close: SESSION_CLOSE_METHOD_NAME,
4833 logout: LOGOUT_METHOD_NAME,
4834 #[cfg(feature = "unstable_nes")]
4835 nes_start: NES_START_METHOD_NAME,
4836 #[cfg(feature = "unstable_nes")]
4837 nes_suggest: NES_SUGGEST_METHOD_NAME,
4838 #[cfg(feature = "unstable_nes")]
4839 nes_accept: NES_ACCEPT_METHOD_NAME,
4840 #[cfg(feature = "unstable_nes")]
4841 nes_reject: NES_REJECT_METHOD_NAME,
4842 #[cfg(feature = "unstable_nes")]
4843 nes_close: NES_CLOSE_METHOD_NAME,
4844 #[cfg(feature = "unstable_nes")]
4845 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4846 #[cfg(feature = "unstable_nes")]
4847 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4848 #[cfg(feature = "unstable_nes")]
4849 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4850 #[cfg(feature = "unstable_nes")]
4851 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4852 #[cfg(feature = "unstable_nes")]
4853 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4854};
4855
4856/// Method name for the initialize request.
4857pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4858/// Method name for the authenticate request.
4859pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4860/// Method name for listing configurable providers.
4861#[cfg(feature = "unstable_llm_providers")]
4862pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4863/// Method name for setting provider configuration.
4864#[cfg(feature = "unstable_llm_providers")]
4865pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4866/// Method name for disabling a provider.
4867#[cfg(feature = "unstable_llm_providers")]
4868pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4869/// Method name for creating a new session.
4870pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4871/// Method name for loading an existing session.
4872pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4873/// Method name for setting a configuration option for a session.
4874pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4875/// Method name for sending a prompt.
4876pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4877/// Method name for the cancel notification.
4878pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4879/// Method name for listing existing sessions.
4880pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4881/// Method name for deleting an existing session.
4882pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4883/// Method name for forking an existing session.
4884#[cfg(feature = "unstable_session_fork")]
4885pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4886/// Method name for resuming an existing session.
4887pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4888/// Method name for closing an active session.
4889pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4890/// Method name for logging out of an authenticated session.
4891pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4892
4893/// All possible requests that a client can send to an agent.
4894///
4895/// This enum is used internally for routing RPC requests. You typically won't need
4896/// to use this directly.
4897///
4898/// This enum encompasses all method calls from client to agent.
4899#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4900#[serde(untagged)]
4901#[schemars(inline)]
4902#[non_exhaustive]
4903pub enum ClientRequest {
4904 /// Establishes the connection with a client and negotiates protocol capabilities.
4905 ///
4906 /// This method is called once at the beginning of the connection to:
4907 /// - Negotiate the protocol version to use
4908 /// - Exchange capability information between client and agent
4909 /// - Determine available authentication methods
4910 ///
4911 /// The agent should respond with its supported protocol version and capabilities.
4912 ///
4913 /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
4914 InitializeRequest(Box<InitializeRequest>),
4915 /// Authenticates the client using the specified authentication method.
4916 ///
4917 /// Called when the agent requires authentication before allowing session creation.
4918 /// The client provides the authentication method ID that was advertised during initialization.
4919 ///
4920 /// After successful authentication, the client can proceed to create sessions with
4921 /// `new_session` without receiving an `auth_required` error.
4922 ///
4923 /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
4924 AuthenticateRequest(AuthenticateRequest),
4925 /// **UNSTABLE**
4926 ///
4927 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4928 ///
4929 /// Lists providers that can be configured by the client.
4930 #[cfg(feature = "unstable_llm_providers")]
4931 ListProvidersRequest(ListProvidersRequest),
4932 /// **UNSTABLE**
4933 ///
4934 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4935 ///
4936 /// Replaces the configuration for a provider.
4937 #[cfg(feature = "unstable_llm_providers")]
4938 SetProviderRequest(Box<SetProviderRequest>),
4939 /// **UNSTABLE**
4940 ///
4941 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4942 ///
4943 /// Disables a provider.
4944 #[cfg(feature = "unstable_llm_providers")]
4945 DisableProviderRequest(DisableProviderRequest),
4946 /// Logs out of the current authenticated state.
4947 ///
4948 /// After a successful logout, all new sessions will require authentication.
4949 /// There is no guarantee about the behavior of already running sessions.
4950 LogoutRequest(LogoutRequest),
4951 /// Creates a new conversation session with the agent.
4952 ///
4953 /// Sessions represent independent conversation contexts with their own history and state.
4954 ///
4955 /// The agent should:
4956 /// - Create a new session context
4957 /// - Connect to any specified MCP servers
4958 /// - Return a unique session ID for future requests
4959 ///
4960 /// May return an `auth_required` error if the agent requires authentication.
4961 ///
4962 /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
4963 NewSessionRequest(NewSessionRequest),
4964 /// Loads an existing session to resume a previous conversation.
4965 ///
4966 /// This method is only available if the agent advertises the `session.load` capability.
4967 ///
4968 /// The agent should:
4969 /// - Restore the session context and conversation history
4970 /// - Connect to the specified MCP servers
4971 /// - Stream the entire conversation history back to the client via notifications
4972 ///
4973 /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
4974 LoadSessionRequest(LoadSessionRequest),
4975 /// Lists existing sessions known to the agent.
4976 ///
4977 /// This method is only available if the agent advertises the `session.list` capability.
4978 ///
4979 /// The agent should return metadata about sessions with optional filtering and pagination support.
4980 ListSessionsRequest(ListSessionsRequest),
4981 /// Deletes an existing session from `session/list`.
4982 ///
4983 /// This method is only available if the agent advertises the `session.delete` capability.
4984 DeleteSessionRequest(DeleteSessionRequest),
4985 #[cfg(feature = "unstable_session_fork")]
4986 /// **UNSTABLE**
4987 ///
4988 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4989 ///
4990 /// Forks an existing session to create a new independent session.
4991 ///
4992 /// This method is only available if the agent advertises the `session.fork` capability.
4993 ///
4994 /// The agent should create a new session with the same conversation context as the
4995 /// original, allowing operations like generating summaries without affecting the
4996 /// original session's history.
4997 ForkSessionRequest(ForkSessionRequest),
4998 /// Resumes an existing session without returning previous messages.
4999 ///
5000 /// This method is only available if the agent advertises the `session.resume` capability.
5001 ///
5002 /// The agent should resume the session context, allowing the conversation to continue
5003 /// without replaying the message history (unlike `session/load`).
5004 ResumeSessionRequest(ResumeSessionRequest),
5005 /// Closes an active session and frees up any resources associated with it.
5006 ///
5007 /// This method is only available if the agent advertises the `session.close` capability.
5008 ///
5009 /// The agent must cancel any ongoing work (as if `session/cancel` was called)
5010 /// and then free up any resources associated with the session.
5011 CloseSessionRequest(CloseSessionRequest),
5012 /// Sets the current value for a session configuration option.
5013 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5014 /// Processes a user prompt within a session.
5015 ///
5016 /// This request accepts the prompt:
5017 /// - Receives user messages with optional context (files, images, etc.)
5018 /// - Returns once the prompt is accepted
5019 ///
5020 /// After acceptance, the Agent reports the accepted user message,
5021 /// processing state, output, tool calls, and completion through
5022 /// `session/update` notifications.
5023 ///
5024 /// See protocol docs: [Prompt Lifecycle](https://agentclientprotocol.com/protocol/prompt-lifecycle)
5025 PromptRequest(PromptRequest),
5026 #[cfg(feature = "unstable_nes")]
5027 /// **UNSTABLE**
5028 ///
5029 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5030 ///
5031 /// Starts an NES session.
5032 StartNesRequest(Box<StartNesRequest>),
5033 #[cfg(feature = "unstable_nes")]
5034 /// **UNSTABLE**
5035 ///
5036 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5037 ///
5038 /// Requests a code suggestion.
5039 SuggestNesRequest(Box<SuggestNesRequest>),
5040 #[cfg(feature = "unstable_nes")]
5041 /// **UNSTABLE**
5042 ///
5043 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5044 ///
5045 /// Closes an active NES session and frees up any resources associated with it.
5046 ///
5047 /// The agent must cancel any ongoing work and then free up any resources
5048 /// associated with the NES session.
5049 CloseNesRequest(CloseNesRequest),
5050 /// **UNSTABLE**
5051 ///
5052 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5053 ///
5054 /// Exchanges an MCP-over-ACP message.
5055 #[cfg(feature = "unstable_mcp_over_acp")]
5056 MessageMcpRequest(MessageMcpRequest),
5057 /// Handles extension method requests from the client.
5058 ///
5059 /// Extension methods provide a way to add custom functionality while maintaining
5060 /// protocol compatibility.
5061 ///
5062 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5063 ExtMethodRequest(ExtRequest),
5064}
5065
5066impl ClientRequest {
5067 /// Returns the corresponding method name of the request.
5068 #[must_use]
5069 pub fn method(&self) -> &str {
5070 match self {
5071 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5072 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5073 #[cfg(feature = "unstable_llm_providers")]
5074 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5075 #[cfg(feature = "unstable_llm_providers")]
5076 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
5077 #[cfg(feature = "unstable_llm_providers")]
5078 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5079 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5080 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5081 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5082 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5083 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5084 #[cfg(feature = "unstable_session_fork")]
5085 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5086 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5087 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5088 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5089 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5090 #[cfg(feature = "unstable_nes")]
5091 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5092 #[cfg(feature = "unstable_nes")]
5093 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5094 #[cfg(feature = "unstable_nes")]
5095 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5096 #[cfg(feature = "unstable_mcp_over_acp")]
5097 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5098 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5099 }
5100 }
5101}
5102
5103/// All possible responses that an agent can send to a client.
5104///
5105/// This enum is used internally for routing RPC responses. You typically won't need
5106/// to use this directly - the responses are handled automatically by the connection.
5107///
5108/// These are responses to the corresponding `ClientRequest` variants.
5109#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5110#[serde(untagged)]
5111#[schemars(inline)]
5112#[non_exhaustive]
5113pub enum AgentResponse {
5114 /// Successful result returned for a `initialize` request.
5115 InitializeResponse(Box<InitializeResponse>),
5116 /// Successful result returned for a `authenticate` request.
5117 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5118 /// Successful result returned for a `providers/list` request.
5119 #[cfg(feature = "unstable_llm_providers")]
5120 ListProvidersResponse(ListProvidersResponse),
5121 /// Successful result returned for a `providers/set` request.
5122 #[cfg(feature = "unstable_llm_providers")]
5123 SetProviderResponse(#[serde(default)] SetProviderResponse),
5124 /// Successful result returned for a `providers/disable` request.
5125 #[cfg(feature = "unstable_llm_providers")]
5126 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5127 /// Successful result returned for a `logout` request.
5128 LogoutResponse(#[serde(default)] LogoutResponse),
5129 /// Successful result returned for a `session/new` request.
5130 NewSessionResponse(NewSessionResponse),
5131 /// Successful result returned for a `session/load` request.
5132 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5133 /// Successful result returned for a `session/list` request.
5134 ListSessionsResponse(ListSessionsResponse),
5135 /// Successful result returned for a `session/delete` request.
5136 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5137 /// Successful result returned for a `session/fork` request.
5138 #[cfg(feature = "unstable_session_fork")]
5139 ForkSessionResponse(ForkSessionResponse),
5140 /// Successful result returned for a `session/resume` request.
5141 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5142 /// Successful result returned for a `session/close` request.
5143 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5144 /// Successful result returned for a `session/set_config_option` request.
5145 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5146 /// Successful result returned for a `session/prompt` request.
5147 PromptResponse(PromptResponse),
5148 /// Successful result returned for a `nes/start` request.
5149 #[cfg(feature = "unstable_nes")]
5150 StartNesResponse(StartNesResponse),
5151 /// Successful result returned for a `nes/suggest` request.
5152 #[cfg(feature = "unstable_nes")]
5153 SuggestNesResponse(SuggestNesResponse),
5154 /// Successful result returned for a `nes/close` request.
5155 #[cfg(feature = "unstable_nes")]
5156 CloseNesResponse(#[serde(default)] CloseNesResponse),
5157 /// Successful result returned by an extension method outside the core ACP method set.
5158 ExtMethodResponse(ExtResponse),
5159 /// Successful result returned by an MCP-over-ACP `mcp/message` request.
5160 #[cfg(feature = "unstable_mcp_over_acp")]
5161 MessageMcpResponse(MessageMcpResponse),
5162}
5163
5164/// All possible notifications that a client can send to an agent.
5165///
5166/// This enum is used internally for routing RPC notifications. You typically won't need
5167/// to use this directly.
5168///
5169/// Notifications do not expect a response.
5170#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5171#[serde(untagged)]
5172#[schemars(inline)]
5173#[non_exhaustive]
5174pub enum ClientNotification {
5175 /// Cancels ongoing operations for a session.
5176 ///
5177 /// This is a notification sent by the client to cancel active work in a
5178 /// session.
5179 ///
5180 /// Upon receiving this notification, the Agent SHOULD:
5181 /// - Stop all language model requests as soon as possible
5182 /// - Abort all tool call invocations in progress
5183 /// - Send any pending `session/update` notifications
5184 /// - Report an idle `state_update` with `StopReason::Cancelled` after
5185 /// cancellation succeeds
5186 ///
5187 /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-lifecycle#cancellation)
5188 CancelNotification(CancelNotification),
5189 #[cfg(feature = "unstable_nes")]
5190 /// **UNSTABLE**
5191 ///
5192 /// Notification sent when a file is opened in the editor.
5193 DidOpenDocumentNotification(DidOpenDocumentNotification),
5194 #[cfg(feature = "unstable_nes")]
5195 /// **UNSTABLE**
5196 ///
5197 /// Notification sent when a file is edited.
5198 DidChangeDocumentNotification(DidChangeDocumentNotification),
5199 #[cfg(feature = "unstable_nes")]
5200 /// **UNSTABLE**
5201 ///
5202 /// Notification sent when a file is closed.
5203 DidCloseDocumentNotification(DidCloseDocumentNotification),
5204 #[cfg(feature = "unstable_nes")]
5205 /// **UNSTABLE**
5206 ///
5207 /// Notification sent when a file is saved.
5208 DidSaveDocumentNotification(DidSaveDocumentNotification),
5209 #[cfg(feature = "unstable_nes")]
5210 /// **UNSTABLE**
5211 ///
5212 /// Notification sent when a file becomes the active editor tab.
5213 DidFocusDocumentNotification(Box<DidFocusDocumentNotification>),
5214 #[cfg(feature = "unstable_nes")]
5215 /// **UNSTABLE**
5216 ///
5217 /// Notification sent when a suggestion is accepted.
5218 AcceptNesNotification(AcceptNesNotification),
5219 #[cfg(feature = "unstable_nes")]
5220 /// **UNSTABLE**
5221 ///
5222 /// Notification sent when a suggestion is rejected.
5223 RejectNesNotification(RejectNesNotification),
5224 /// **UNSTABLE**
5225 ///
5226 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5227 ///
5228 /// Sends an MCP-over-ACP notification.
5229 #[cfg(feature = "unstable_mcp_over_acp")]
5230 MessageMcpNotification(MessageMcpNotification),
5231 /// Handles extension notifications from the client.
5232 ///
5233 /// Extension notifications provide a way to send one-way messages for custom functionality
5234 /// while maintaining protocol compatibility.
5235 ///
5236 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5237 ExtNotification(ExtNotification),
5238}
5239
5240impl ClientNotification {
5241 /// Returns the corresponding method name of the notification.
5242 #[must_use]
5243 pub fn method(&self) -> &str {
5244 match self {
5245 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5246 #[cfg(feature = "unstable_nes")]
5247 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5248 #[cfg(feature = "unstable_nes")]
5249 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5250 #[cfg(feature = "unstable_nes")]
5251 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5252 #[cfg(feature = "unstable_nes")]
5253 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5254 #[cfg(feature = "unstable_nes")]
5255 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5256 #[cfg(feature = "unstable_nes")]
5257 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5258 #[cfg(feature = "unstable_nes")]
5259 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5260 #[cfg(feature = "unstable_mcp_over_acp")]
5261 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5262 Self::ExtNotification(ext_notification) => &ext_notification.method,
5263 }
5264 }
5265}
5266
5267/// Notification to cancel ongoing operations for a session.
5268///
5269/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-lifecycle#cancellation)
5270#[skip_serializing_none]
5271#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5272#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5273#[serde(rename_all = "camelCase")]
5274#[non_exhaustive]
5275pub struct CancelNotification {
5276 /// The ID of the session to cancel operations for.
5277 pub session_id: SessionId,
5278 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
5279 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
5280 /// these keys.
5281 ///
5282 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5283 #[serde(rename = "_meta")]
5284 pub meta: Option<Meta>,
5285}
5286
5287impl CancelNotification {
5288 /// Builds [`CancelNotification`] with the required notification fields set; optional fields start unset or empty.
5289 #[must_use]
5290 pub fn new(session_id: impl Into<SessionId>) -> Self {
5291 Self {
5292 session_id: session_id.into(),
5293 meta: None,
5294 }
5295 }
5296
5297 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
5298 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
5299 /// these keys.
5300 ///
5301 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5302 #[must_use]
5303 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5304 self.meta = meta.into_option();
5305 self
5306 }
5307}
5308
5309#[cfg(test)]
5310mod test_serialization {
5311 use super::*;
5312 use serde_json::json;
5313
5314 fn test_meta() -> Meta {
5315 json!({ "source": "test" }).as_object().unwrap().clone()
5316 }
5317
5318 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5319 serde_json::to_string(value)
5320 .unwrap()
5321 .matches("\"_meta\"")
5322 .count()
5323 }
5324
5325 #[test]
5326 fn test_mcp_server_stdio_serialization() {
5327 let server = McpServer::Stdio(
5328 McpServerStdio::new("test-server", "/usr/bin/server")
5329 .args(vec!["--port".to_string(), "3000".to_string()])
5330 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5331 );
5332
5333 let json = serde_json::to_value(&server).unwrap();
5334 assert_eq!(
5335 json,
5336 json!({
5337 "type": "stdio",
5338 "name": "test-server",
5339 "command": "/usr/bin/server",
5340 "args": ["--port", "3000"],
5341 "env": [
5342 {
5343 "name": "API_KEY",
5344 "value": "secret123"
5345 }
5346 ]
5347 })
5348 );
5349
5350 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5351 match deserialized {
5352 McpServer::Stdio(McpServerStdio {
5353 name,
5354 command,
5355 args,
5356 env,
5357 meta: _,
5358 }) => {
5359 assert_eq!(name, "test-server");
5360 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5361 assert_eq!(args, vec!["--port", "3000"]);
5362 assert_eq!(env.len(), 1);
5363 assert_eq!(env[0].name, "API_KEY");
5364 assert_eq!(env[0].value, "secret123");
5365 }
5366 _ => panic!("Expected Stdio variant"),
5367 }
5368 }
5369
5370 #[test]
5371 fn test_mcp_server_unknown_transport_serialization() {
5372 let json = json!({
5373 "type": "websocket",
5374 "name": "future-server",
5375 "url": "wss://example.com/mcp",
5376 "protocolVersion": "2026-01-01"
5377 });
5378
5379 let deserialized: McpServer = serde_json::from_value(json.clone()).unwrap();
5380 let McpServer::Other(OtherMcpServer { type_, fields }) = &deserialized else {
5381 panic!("Expected Other variant");
5382 };
5383
5384 assert_eq!(type_, "websocket");
5385 assert_eq!(fields["name"], "future-server");
5386 assert_eq!(fields["url"], "wss://example.com/mcp");
5387 assert_eq!(fields["protocolVersion"], "2026-01-01");
5388 assert_eq!(serde_json::to_value(&deserialized).unwrap(), json);
5389 }
5390
5391 #[test]
5392 fn test_mcp_server_stdio_requires_type() {
5393 let result = serde_json::from_value::<McpServer>(json!({
5394 "name": "test-server",
5395 "command": "/usr/bin/server",
5396 "args": [],
5397 "env": []
5398 }));
5399
5400 assert!(result.is_err());
5401 }
5402
5403 #[test]
5404 fn test_mcp_server_unknown_does_not_hide_malformed_known_transport() {
5405 let result = serde_json::from_value::<McpServer>(json!({
5406 "type": "stdio",
5407 "name": "test-server",
5408 "args": [],
5409 "env": []
5410 }));
5411
5412 assert!(result.is_err());
5413 }
5414
5415 #[test]
5416 fn test_mcp_server_http_serialization() {
5417 let server = McpServer::Http(
5418 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5419 HttpHeader::new("Authorization", "Bearer token123"),
5420 HttpHeader::new("Content-Type", "application/json"),
5421 ]),
5422 );
5423
5424 let json = serde_json::to_value(&server).unwrap();
5425 assert_eq!(
5426 json,
5427 json!({
5428 "type": "http",
5429 "name": "http-server",
5430 "url": "https://api.example.com",
5431 "headers": [
5432 {
5433 "name": "Authorization",
5434 "value": "Bearer token123"
5435 },
5436 {
5437 "name": "Content-Type",
5438 "value": "application/json"
5439 }
5440 ]
5441 })
5442 );
5443
5444 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5445 match deserialized {
5446 McpServer::Http(McpServerHttp {
5447 name,
5448 url,
5449 headers,
5450 meta: _,
5451 }) => {
5452 assert_eq!(name, "http-server");
5453 assert_eq!(url, "https://api.example.com");
5454 assert_eq!(headers.len(), 2);
5455 assert_eq!(headers[0].name, "Authorization");
5456 assert_eq!(headers[0].value, "Bearer token123");
5457 assert_eq!(headers[1].name, "Content-Type");
5458 assert_eq!(headers[1].value, "application/json");
5459 }
5460 _ => panic!("Expected Http variant"),
5461 }
5462 }
5463
5464 #[cfg(feature = "unstable_mcp_over_acp")]
5465 #[test]
5466 fn test_client_mcp_message_method_names() {
5467 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5468
5469 assert_eq!(
5470 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5471 .method(),
5472 "mcp/message"
5473 );
5474 assert_eq!(
5475 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5476 "conn-1",
5477 "notifications/progress"
5478 ))
5479 .method(),
5480 "mcp/message"
5481 );
5482 }
5483
5484 #[test]
5485 fn test_session_config_option_category_known_variants() {
5486 // Test serialization of known variants
5487 assert_eq!(
5488 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5489 json!("mode")
5490 );
5491 assert_eq!(
5492 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5493 json!("model")
5494 );
5495 assert_eq!(
5496 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5497 json!("model_config")
5498 );
5499 assert_eq!(
5500 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5501 json!("thought_level")
5502 );
5503
5504 // Test deserialization of known variants
5505 assert_eq!(
5506 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5507 SessionConfigOptionCategory::Mode
5508 );
5509 assert_eq!(
5510 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5511 SessionConfigOptionCategory::Model
5512 );
5513 assert_eq!(
5514 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5515 SessionConfigOptionCategory::ModelConfig
5516 );
5517 assert_eq!(
5518 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5519 SessionConfigOptionCategory::ThoughtLevel
5520 );
5521 }
5522
5523 #[test]
5524 fn test_session_config_option_category_unknown_variants() {
5525 // Test that unknown strings are captured in Other variant
5526 let unknown: SessionConfigOptionCategory =
5527 serde_json::from_str("\"some_future_category\"").unwrap();
5528 assert_eq!(
5529 unknown,
5530 SessionConfigOptionCategory::Other("some_future_category".to_string())
5531 );
5532
5533 // Test round-trip of unknown category
5534 let json = serde_json::to_value(&unknown).unwrap();
5535 assert_eq!(json, json!("some_future_category"));
5536 }
5537
5538 #[test]
5539 fn test_session_config_option_category_custom_categories() {
5540 // Category names beginning with `_` are free for custom use
5541 let custom: SessionConfigOptionCategory =
5542 serde_json::from_str("\"_my_custom_category\"").unwrap();
5543 assert_eq!(
5544 custom,
5545 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5546 );
5547
5548 // Test round-trip preserves the custom category name
5549 let json = serde_json::to_value(&custom).unwrap();
5550 assert_eq!(json, json!("_my_custom_category"));
5551
5552 // Deserialize back and verify
5553 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5554 assert_eq!(
5555 deserialized,
5556 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5557 );
5558 }
5559
5560 #[test]
5561 fn test_auth_method_agent_serialization() {
5562 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5563
5564 let json = serde_json::to_value(&method).unwrap();
5565 assert_eq!(
5566 json,
5567 json!({
5568 "id": "default-auth",
5569 "name": "Default Auth",
5570 "type": "agent"
5571 })
5572 );
5573 // description should be omitted when None
5574 assert!(!json.as_object().unwrap().contains_key("description"));
5575
5576 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5577 match deserialized {
5578 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5579 assert_eq!(id.0.as_ref(), "default-auth");
5580 assert_eq!(name, "Default Auth");
5581 }
5582 _ => panic!("Expected Agent variant"),
5583 }
5584 }
5585
5586 #[test]
5587 fn test_auth_method_agent_deserialization() {
5588 let json = json!({
5589 "id": "agent-auth",
5590 "name": "Agent Auth",
5591 "type": "agent"
5592 });
5593
5594 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5595 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5596 }
5597
5598 #[test]
5599 fn test_auth_method_agent_requires_type() {
5600 assert!(
5601 serde_json::from_value::<AuthMethod>(json!({
5602 "id": "agent-auth",
5603 "name": "Agent Auth"
5604 }))
5605 .is_err()
5606 );
5607 }
5608
5609 #[test]
5610 fn test_auth_method_agent_rejects_null_type() {
5611 assert!(
5612 serde_json::from_value::<AuthMethod>(json!({
5613 "id": "agent-auth",
5614 "name": "Agent Auth",
5615 "type": null
5616 }))
5617 .is_err()
5618 );
5619 }
5620
5621 #[test]
5622 fn test_auth_method_unknown_does_not_hide_malformed_agent() {
5623 assert!(
5624 serde_json::from_value::<AuthMethod>(json!({
5625 "id": "agent-auth",
5626 "type": "agent"
5627 }))
5628 .is_err()
5629 );
5630 }
5631
5632 #[test]
5633 fn test_auth_method_unknown_variant_roundtrip() {
5634 let method: AuthMethod = serde_json::from_value(json!({
5635 "id": "oauth",
5636 "name": "OAuth",
5637 "type": "_oauth",
5638 "authorizationUrl": "https://example.com/auth"
5639 }))
5640 .unwrap();
5641
5642 assert_eq!(method.id().0.as_ref(), "oauth");
5643 assert_eq!(method.name(), "OAuth");
5644 let AuthMethod::Other(unknown) = method else {
5645 panic!("expected unknown auth method");
5646 };
5647 assert_eq!(unknown.type_, "_oauth");
5648 assert_eq!(
5649 unknown.fields.get("authorizationUrl"),
5650 Some(&json!("https://example.com/auth"))
5651 );
5652
5653 assert_eq!(
5654 serde_json::to_value(AuthMethod::Other(unknown)).unwrap(),
5655 json!({
5656 "id": "oauth",
5657 "name": "OAuth",
5658 "type": "_oauth",
5659 "authorizationUrl": "https://example.com/auth"
5660 })
5661 );
5662 }
5663
5664 #[cfg(feature = "unstable_auth_methods")]
5665 #[test]
5666 fn test_auth_method_unknown_does_not_hide_malformed_known_variant() {
5667 assert!(
5668 serde_json::from_value::<AuthMethod>(json!({
5669 "id": "api-key",
5670 "name": "API Key",
5671 "type": "env_var"
5672 }))
5673 .is_err()
5674 );
5675 }
5676
5677 #[test]
5678 fn test_session_delete_serialization() {
5679 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5680 assert_eq!(
5681 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5682 "session/delete"
5683 );
5684 assert_eq!(
5685 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5686 json!({
5687 "sessionId": "sess_abc123"
5688 })
5689 );
5690 assert_eq!(
5691 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5692 json!({})
5693 );
5694 assert_eq!(
5695 serde_json::to_value(
5696 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5697 )
5698 .unwrap(),
5699 json!({
5700 "delete": {}
5701 })
5702 );
5703 }
5704 #[test]
5705 fn test_session_additional_directories_serialization() {
5706 assert_eq!(
5707 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5708 json!({
5709 "cwd": "/home/user/project",
5710 "mcpServers": []
5711 })
5712 );
5713 assert_eq!(
5714 serde_json::to_value(
5715 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5716 PathBuf::from("/home/user/shared-lib"),
5717 PathBuf::from("/home/user/product-docs"),
5718 ])
5719 )
5720 .unwrap(),
5721 json!({
5722 "cwd": "/home/user/project",
5723 "additionalDirectories": [
5724 "/home/user/shared-lib",
5725 "/home/user/product-docs"
5726 ],
5727 "mcpServers": []
5728 })
5729 );
5730 assert_eq!(
5731 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5732 json!({
5733 "sessionId": "sess_abc123",
5734 "cwd": "/home/user/project"
5735 })
5736 );
5737 assert_eq!(
5738 serde_json::to_value(
5739 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5740 PathBuf::from("/home/user/shared-lib"),
5741 PathBuf::from("/home/user/product-docs"),
5742 ])
5743 )
5744 .unwrap(),
5745 json!({
5746 "sessionId": "sess_abc123",
5747 "cwd": "/home/user/project",
5748 "additionalDirectories": [
5749 "/home/user/shared-lib",
5750 "/home/user/product-docs"
5751 ]
5752 })
5753 );
5754 assert_eq!(
5755 serde_json::from_value::<SessionInfo>(json!({
5756 "sessionId": "sess_abc123",
5757 "cwd": "/home/user/project"
5758 }))
5759 .unwrap()
5760 .additional_directories,
5761 Vec::<PathBuf>::new()
5762 );
5763 }
5764 #[test]
5765 fn test_session_load_capabilities_serialization() {
5766 assert_eq!(
5767 serde_json::to_value(SessionCapabilities::new().load(SessionLoadCapabilities::new()))
5768 .unwrap(),
5769 json!({
5770 "load": {}
5771 })
5772 );
5773 }
5774
5775 #[test]
5776 fn test_session_additional_directories_capabilities_serialization() {
5777 assert_eq!(
5778 serde_json::to_value(
5779 SessionCapabilities::new()
5780 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5781 )
5782 .unwrap(),
5783 json!({
5784 "additionalDirectories": {}
5785 })
5786 );
5787 }
5788
5789 #[cfg(feature = "unstable_auth_methods")]
5790 #[test]
5791 fn test_auth_method_env_var_serialization() {
5792 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5793 "api-key",
5794 "API Key",
5795 vec![AuthEnvVar::new("API_KEY")],
5796 ));
5797
5798 let json = serde_json::to_value(&method).unwrap();
5799 assert_eq!(
5800 json,
5801 json!({
5802 "id": "api-key",
5803 "name": "API Key",
5804 "type": "env_var",
5805 "vars": [{"name": "API_KEY"}]
5806 })
5807 );
5808 // secret defaults to true and should be omitted; optional defaults to false and should be omitted
5809 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5810 assert!(
5811 !json["vars"][0]
5812 .as_object()
5813 .unwrap()
5814 .contains_key("optional")
5815 );
5816
5817 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5818 match deserialized {
5819 AuthMethod::EnvVar(AuthMethodEnvVar {
5820 id,
5821 name: method_name,
5822 vars,
5823 link,
5824 ..
5825 }) => {
5826 assert_eq!(id.0.as_ref(), "api-key");
5827 assert_eq!(method_name, "API Key");
5828 assert_eq!(vars.len(), 1);
5829 assert_eq!(vars[0].name, "API_KEY");
5830 assert!(vars[0].secret);
5831 assert!(!vars[0].optional);
5832 assert!(link.is_none());
5833 }
5834 _ => panic!("Expected EnvVar variant"),
5835 }
5836 }
5837
5838 #[cfg(feature = "unstable_auth_methods")]
5839 #[test]
5840 fn test_auth_method_env_var_with_link_serialization() {
5841 let method = AuthMethod::EnvVar(
5842 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5843 .link("https://example.com/keys"),
5844 );
5845
5846 let json = serde_json::to_value(&method).unwrap();
5847 assert_eq!(
5848 json,
5849 json!({
5850 "id": "api-key",
5851 "name": "API Key",
5852 "type": "env_var",
5853 "vars": [{"name": "API_KEY"}],
5854 "link": "https://example.com/keys"
5855 })
5856 );
5857
5858 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5859 match deserialized {
5860 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5861 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5862 }
5863 _ => panic!("Expected EnvVar variant"),
5864 }
5865 }
5866
5867 #[cfg(feature = "unstable_auth_methods")]
5868 #[test]
5869 fn test_auth_method_env_var_multiple_vars() {
5870 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5871 "azure-openai",
5872 "Azure OpenAI",
5873 vec![
5874 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5875 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5876 .label("Endpoint URL")
5877 .secret(false),
5878 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5879 .label("API Version")
5880 .secret(false)
5881 .optional(true),
5882 ],
5883 ));
5884
5885 let json = serde_json::to_value(&method).unwrap();
5886 assert_eq!(
5887 json,
5888 json!({
5889 "id": "azure-openai",
5890 "name": "Azure OpenAI",
5891 "type": "env_var",
5892 "vars": [
5893 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5894 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5895 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5896 ]
5897 })
5898 );
5899
5900 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5901 match deserialized {
5902 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5903 assert_eq!(vars.len(), 3);
5904 // First var: secret (default true), not optional (default false)
5905 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5906 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5907 assert!(vars[0].secret);
5908 assert!(!vars[0].optional);
5909 // Second var: not a secret, not optional
5910 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5911 assert!(!vars[1].secret);
5912 assert!(!vars[1].optional);
5913 // Third var: not a secret, optional
5914 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5915 assert!(!vars[2].secret);
5916 assert!(vars[2].optional);
5917 }
5918 _ => panic!("Expected EnvVar variant"),
5919 }
5920 }
5921
5922 #[cfg(feature = "unstable_auth_methods")]
5923 #[test]
5924 fn test_auth_method_terminal_serialization() {
5925 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5926
5927 let json = serde_json::to_value(&method).unwrap();
5928 assert_eq!(
5929 json,
5930 json!({
5931 "id": "tui-auth",
5932 "name": "Terminal Auth",
5933 "type": "terminal"
5934 })
5935 );
5936 // args and env should be omitted when empty
5937 assert!(!json.as_object().unwrap().contains_key("args"));
5938 assert!(!json.as_object().unwrap().contains_key("env"));
5939
5940 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5941 match deserialized {
5942 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5943 assert!(args.is_empty());
5944 assert!(env.is_empty());
5945 }
5946 _ => panic!("Expected Terminal variant"),
5947 }
5948 }
5949
5950 #[cfg(feature = "unstable_auth_methods")]
5951 #[test]
5952 fn test_auth_method_terminal_with_args_and_env_serialization() {
5953 use std::collections::HashMap;
5954
5955 let mut env = HashMap::new();
5956 env.insert("TERM".to_string(), "xterm-256color".to_string());
5957
5958 let method = AuthMethod::Terminal(
5959 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5960 .args(vec!["--interactive".to_string(), "--color".to_string()])
5961 .env(env),
5962 );
5963
5964 let json = serde_json::to_value(&method).unwrap();
5965 assert_eq!(
5966 json,
5967 json!({
5968 "id": "tui-auth",
5969 "name": "Terminal Auth",
5970 "type": "terminal",
5971 "args": ["--interactive", "--color"],
5972 "env": {
5973 "TERM": "xterm-256color"
5974 }
5975 })
5976 );
5977
5978 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5979 match deserialized {
5980 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5981 assert_eq!(args, vec!["--interactive", "--color"]);
5982 assert_eq!(env.len(), 1);
5983 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
5984 }
5985 _ => panic!("Expected Terminal variant"),
5986 }
5987 }
5988
5989 #[cfg(feature = "unstable_boolean_config")]
5990 #[test]
5991 fn test_session_config_option_value_id_serialize() {
5992 let val = SessionConfigOptionValue::value_id("model-1");
5993 let json = serde_json::to_value(&val).unwrap();
5994 // ValueId omits the "type" field (it's the default)
5995 assert_eq!(json, json!({ "value": "model-1" }));
5996 assert!(!json.as_object().unwrap().contains_key("type"));
5997 }
5998
5999 #[cfg(feature = "unstable_boolean_config")]
6000 #[test]
6001 fn test_session_config_option_value_boolean_serialize() {
6002 let val = SessionConfigOptionValue::boolean(true);
6003 let json = serde_json::to_value(&val).unwrap();
6004 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6005 }
6006
6007 #[cfg(feature = "unstable_boolean_config")]
6008 #[test]
6009 fn test_session_config_option_value_deserialize_no_type() {
6010 // Missing "type" should default to ValueId
6011 let json = json!({ "value": "model-1" });
6012 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6013 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6014 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6015 }
6016
6017 #[cfg(feature = "unstable_boolean_config")]
6018 #[test]
6019 fn test_session_config_option_value_deserialize_boolean() {
6020 let json = json!({ "type": "boolean", "value": true });
6021 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6022 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6023 assert_eq!(val.as_bool(), Some(true));
6024 }
6025
6026 #[cfg(feature = "unstable_boolean_config")]
6027 #[test]
6028 fn test_session_config_option_value_deserialize_boolean_false() {
6029 let json = json!({ "type": "boolean", "value": false });
6030 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6031 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6032 assert_eq!(val.as_bool(), Some(false));
6033 }
6034
6035 #[cfg(feature = "unstable_boolean_config")]
6036 #[test]
6037 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6038 // Unknown type with a string value gracefully falls back to ValueId
6039 let json = json!({ "type": "text", "value": "freeform input" });
6040 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6041 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6042 }
6043
6044 #[cfg(feature = "unstable_boolean_config")]
6045 #[test]
6046 fn test_session_config_option_value_roundtrip_value_id() {
6047 let original = SessionConfigOptionValue::value_id("option-a");
6048 let json = serde_json::to_value(&original).unwrap();
6049 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6050 assert_eq!(original, roundtripped);
6051 }
6052
6053 #[cfg(feature = "unstable_boolean_config")]
6054 #[test]
6055 fn test_session_config_option_value_roundtrip_boolean() {
6056 let original = SessionConfigOptionValue::boolean(false);
6057 let json = serde_json::to_value(&original).unwrap();
6058 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6059 assert_eq!(original, roundtripped);
6060 }
6061
6062 #[cfg(feature = "unstable_boolean_config")]
6063 #[test]
6064 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6065 // type says "boolean" but value is a string — falls to untagged ValueId
6066 let json = json!({ "type": "boolean", "value": "not a bool" });
6067 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6068 // serde tries Boolean first (fails), then falls to untagged ValueId (succeeds)
6069 assert!(result.is_ok());
6070 assert_eq!(
6071 result.unwrap().as_value_id().unwrap().to_string(),
6072 "not a bool"
6073 );
6074 }
6075
6076 #[cfg(feature = "unstable_boolean_config")]
6077 #[test]
6078 fn test_session_config_option_value_from_impls() {
6079 let from_str: SessionConfigOptionValue = "model-1".into();
6080 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6081
6082 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6083 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6084
6085 let from_bool: SessionConfigOptionValue = true.into();
6086 assert_eq!(from_bool.as_bool(), Some(true));
6087 }
6088
6089 #[cfg(feature = "unstable_boolean_config")]
6090 #[test]
6091 fn test_set_session_config_option_request_value_id() {
6092 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6093 let json = serde_json::to_value(&req).unwrap();
6094 assert_eq!(
6095 json,
6096 json!({
6097 "sessionId": "sess_1",
6098 "configId": "model",
6099 "value": "model-1"
6100 })
6101 );
6102 // No "type" field for value_id
6103 assert!(!json.as_object().unwrap().contains_key("type"));
6104 }
6105
6106 #[cfg(feature = "unstable_boolean_config")]
6107 #[test]
6108 fn test_set_session_config_option_request_boolean() {
6109 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6110 let json = serde_json::to_value(&req).unwrap();
6111 assert_eq!(
6112 json,
6113 json!({
6114 "sessionId": "sess_1",
6115 "configId": "brave_mode",
6116 "type": "boolean",
6117 "value": true
6118 })
6119 );
6120 }
6121
6122 #[cfg(feature = "unstable_boolean_config")]
6123 #[test]
6124 fn test_set_session_config_option_request_deserialize_no_type() {
6125 // Backwards-compatible: no "type" field → value_id
6126 let json = json!({
6127 "sessionId": "sess_1",
6128 "configId": "model",
6129 "value": "model-1"
6130 });
6131 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6132 assert_eq!(req.session_id.to_string(), "sess_1");
6133 assert_eq!(req.config_id.to_string(), "model");
6134 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6135 }
6136
6137 #[cfg(feature = "unstable_boolean_config")]
6138 #[test]
6139 fn test_set_session_config_option_request_deserialize_boolean() {
6140 let json = json!({
6141 "sessionId": "sess_1",
6142 "configId": "brave_mode",
6143 "type": "boolean",
6144 "value": true
6145 });
6146 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6147 assert_eq!(req.value.as_bool(), Some(true));
6148 }
6149
6150 #[cfg(feature = "unstable_boolean_config")]
6151 #[test]
6152 fn test_set_session_config_option_request_roundtrip_value_id() {
6153 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6154 let json = serde_json::to_value(&original).unwrap();
6155 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6156 assert_eq!(original, roundtripped);
6157 }
6158
6159 #[cfg(feature = "unstable_boolean_config")]
6160 #[test]
6161 fn test_set_session_config_option_request_roundtrip_boolean() {
6162 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6163 let json = serde_json::to_value(&original).unwrap();
6164 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6165 assert_eq!(original, roundtripped);
6166 }
6167
6168 #[cfg(feature = "unstable_boolean_config")]
6169 #[test]
6170 fn test_session_config_boolean_serialization() {
6171 let cfg = SessionConfigBoolean::new(true);
6172 let json = serde_json::to_value(&cfg).unwrap();
6173 assert_eq!(json, json!({ "currentValue": true }));
6174
6175 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6176 assert!(deserialized.current_value);
6177 }
6178
6179 #[cfg(feature = "unstable_boolean_config")]
6180 #[test]
6181 fn test_session_config_option_boolean_variant() {
6182 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6183 .description("Skip confirmation prompts")
6184 .meta(test_meta());
6185 assert_eq!(serialized_meta_key_count(&opt), 1);
6186
6187 let json = serde_json::to_value(&opt).unwrap();
6188 assert_eq!(
6189 json,
6190 json!({
6191 "id": "brave_mode",
6192 "name": "Brave Mode",
6193 "description": "Skip confirmation prompts",
6194 "type": "boolean",
6195 "currentValue": false,
6196 "_meta": {
6197 "source": "test"
6198 }
6199 })
6200 );
6201
6202 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6203 assert_eq!(deserialized.id.to_string(), "brave_mode");
6204 assert_eq!(deserialized.name, "Brave Mode");
6205 match deserialized.kind {
6206 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6207 _ => panic!("Expected Boolean kind"),
6208 }
6209 }
6210
6211 #[cfg(feature = "unstable_boolean_config")]
6212 #[test]
6213 fn test_session_config_option_select_still_works() {
6214 // Make sure existing select options are unaffected
6215 let opt = SessionConfigOption::select(
6216 "model",
6217 "Model",
6218 "model-1",
6219 vec![
6220 SessionConfigSelectOption::new("model-1", "Model 1"),
6221 SessionConfigSelectOption::new("model-2", "Model 2"),
6222 ],
6223 )
6224 .meta(test_meta());
6225 assert_eq!(serialized_meta_key_count(&opt), 1);
6226
6227 let json = serde_json::to_value(&opt).unwrap();
6228 assert_eq!(json["type"], "select");
6229 assert_eq!(json["currentValue"], "model-1");
6230 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6231 assert_eq!(json["_meta"]["source"], "test");
6232
6233 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6234 match deserialized.kind {
6235 SessionConfigKind::Select(ref s) => {
6236 assert_eq!(s.current_value.to_string(), "model-1");
6237 }
6238 _ => panic!("Expected Select kind"),
6239 }
6240 }
6241
6242 #[test]
6243 fn test_session_config_option_unknown_kind_roundtrip() {
6244 let option: SessionConfigOption = serde_json::from_value(json!({
6245 "id": "verbosity",
6246 "name": "Verbosity",
6247 "type": "_slider",
6248 "currentValue": 3,
6249 "min": 0,
6250 "max": 5,
6251 "_meta": {
6252 "source": "test"
6253 }
6254 }))
6255 .unwrap();
6256
6257 assert_eq!(option.id.to_string(), "verbosity");
6258 assert_eq!(option.meta.as_ref().unwrap()["source"], "test");
6259 let SessionConfigKind::Other(unknown) = &option.kind else {
6260 panic!("expected unknown config kind");
6261 };
6262 assert_eq!(unknown.type_, "_slider");
6263 assert_eq!(unknown.fields.get("currentValue"), Some(&json!(3)));
6264 assert!(!unknown.fields.contains_key("_meta"));
6265 assert_eq!(serialized_meta_key_count(&option), 1);
6266
6267 let json = serde_json::to_value(&option).unwrap();
6268 assert_eq!(json["type"], "_slider");
6269 assert_eq!(json["currentValue"], 3);
6270 assert_eq!(json["min"], 0);
6271 assert_eq!(json["max"], 5);
6272 assert_eq!(json["_meta"]["source"], "test");
6273 }
6274
6275 #[test]
6276 fn test_session_config_option_unknown_kind_does_not_duplicate_flattened_meta() {
6277 let mut fields = std::collections::BTreeMap::new();
6278 fields.insert("currentValue".to_string(), json!(3));
6279 fields.insert("_meta".to_string(), json!({ "inner": "ignored" }));
6280
6281 let option = SessionConfigOption::new(
6282 "verbosity",
6283 "Verbosity",
6284 SessionConfigKind::Other(OtherSessionConfigKind::new("_slider", fields)),
6285 )
6286 .meta(test_meta());
6287
6288 let SessionConfigKind::Other(unknown) = &option.kind else {
6289 panic!("expected unknown config kind");
6290 };
6291 assert!(!unknown.fields.contains_key("_meta"));
6292 assert_eq!(serialized_meta_key_count(&option), 1);
6293
6294 let json = serde_json::to_value(&option).unwrap();
6295 assert_eq!(json["type"], "_slider");
6296 assert_eq!(json["currentValue"], 3);
6297 assert_eq!(json["_meta"]["source"], "test");
6298 }
6299
6300 #[test]
6301 fn test_session_config_option_unknown_does_not_hide_malformed_known_kind() {
6302 assert!(
6303 serde_json::from_value::<SessionConfigOption>(json!({
6304 "id": "model",
6305 "name": "Model",
6306 "type": "select"
6307 }))
6308 .is_err()
6309 );
6310 }
6311
6312 #[cfg(feature = "unstable_llm_providers")]
6313 #[test]
6314 fn test_llm_protocol_known_variants() {
6315 assert_eq!(
6316 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6317 json!("anthropic")
6318 );
6319 assert_eq!(
6320 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6321 json!("openai")
6322 );
6323 assert_eq!(
6324 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6325 json!("azure")
6326 );
6327 assert_eq!(
6328 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6329 json!("vertex")
6330 );
6331 assert_eq!(
6332 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6333 json!("bedrock")
6334 );
6335
6336 assert_eq!(
6337 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6338 LlmProtocol::Anthropic
6339 );
6340 assert_eq!(
6341 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6342 LlmProtocol::OpenAi
6343 );
6344 assert_eq!(
6345 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6346 LlmProtocol::Azure
6347 );
6348 assert_eq!(
6349 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6350 LlmProtocol::Vertex
6351 );
6352 assert_eq!(
6353 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6354 LlmProtocol::Bedrock
6355 );
6356 }
6357
6358 #[cfg(feature = "unstable_llm_providers")]
6359 #[test]
6360 fn test_llm_protocol_unknown_variant() {
6361 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6362 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6363
6364 let json = serde_json::to_value(&unknown).unwrap();
6365 assert_eq!(json, json!("cohere"));
6366 }
6367
6368 #[cfg(feature = "unstable_llm_providers")]
6369 #[test]
6370 fn test_provider_current_config_serialization() {
6371 let config =
6372 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6373
6374 let json = serde_json::to_value(&config).unwrap();
6375 assert_eq!(
6376 json,
6377 json!({
6378 "apiType": "anthropic",
6379 "baseUrl": "https://api.anthropic.com"
6380 })
6381 );
6382
6383 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6384 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6385 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6386 }
6387
6388 #[cfg(feature = "unstable_llm_providers")]
6389 #[test]
6390 fn test_provider_info_with_current_config() {
6391 let info = ProviderInfo::new(
6392 "main",
6393 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6394 true,
6395 Some(ProviderCurrentConfig::new(
6396 LlmProtocol::Anthropic,
6397 "https://api.anthropic.com",
6398 )),
6399 );
6400
6401 let json = serde_json::to_value(&info).unwrap();
6402 assert_eq!(
6403 json,
6404 json!({
6405 "id": "main",
6406 "supported": ["anthropic", "openai"],
6407 "required": true,
6408 "current": {
6409 "apiType": "anthropic",
6410 "baseUrl": "https://api.anthropic.com"
6411 }
6412 })
6413 );
6414
6415 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6416 assert_eq!(deserialized.id, "main");
6417 assert_eq!(deserialized.supported.len(), 2);
6418 assert!(deserialized.required);
6419 assert!(deserialized.current.is_some());
6420 assert_eq!(
6421 deserialized.current.as_ref().unwrap().api_type,
6422 LlmProtocol::Anthropic
6423 );
6424 }
6425
6426 #[cfg(feature = "unstable_llm_providers")]
6427 #[test]
6428 fn test_provider_info_disabled() {
6429 let info = ProviderInfo::new(
6430 "secondary",
6431 vec![LlmProtocol::OpenAi],
6432 false,
6433 None::<ProviderCurrentConfig>,
6434 );
6435
6436 let json = serde_json::to_value(&info).unwrap();
6437 assert_eq!(
6438 json,
6439 json!({
6440 "id": "secondary",
6441 "supported": ["openai"],
6442 "required": false
6443 })
6444 );
6445
6446 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6447 assert_eq!(deserialized.id, "secondary");
6448 assert!(!deserialized.required);
6449 assert!(deserialized.current.is_none());
6450 }
6451
6452 #[cfg(feature = "unstable_llm_providers")]
6453 #[test]
6454 fn test_provider_info_missing_current_defaults_to_none() {
6455 // current is optional; omitting it should decode as None
6456 let json = json!({
6457 "id": "main",
6458 "supported": ["anthropic"],
6459 "required": true
6460 });
6461 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6462 assert!(deserialized.current.is_none());
6463 }
6464
6465 #[cfg(feature = "unstable_llm_providers")]
6466 #[test]
6467 fn test_provider_info_explicit_null_current_decodes_to_none() {
6468 // current: null and an omitted current are equivalent on the wire;
6469 // both must deserialize into None so the disabled state is preserved
6470 // regardless of which form the peer chose to send.
6471 let json = json!({
6472 "id": "main",
6473 "supported": ["anthropic"],
6474 "required": true,
6475 "current": null
6476 });
6477 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6478 assert!(deserialized.current.is_none());
6479 }
6480
6481 #[cfg(feature = "unstable_llm_providers")]
6482 #[test]
6483 fn test_list_providers_response_serialization() {
6484 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6485 "main",
6486 vec![LlmProtocol::Anthropic],
6487 true,
6488 Some(ProviderCurrentConfig::new(
6489 LlmProtocol::Anthropic,
6490 "https://api.anthropic.com",
6491 )),
6492 )]);
6493
6494 let json = serde_json::to_value(&response).unwrap();
6495 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6496 assert_eq!(json["providers"][0]["id"], "main");
6497
6498 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6499 assert_eq!(deserialized.providers.len(), 1);
6500 }
6501
6502 #[cfg(feature = "unstable_llm_providers")]
6503 #[test]
6504 fn test_set_provider_request_serialization() {
6505 use std::collections::HashMap;
6506
6507 let mut headers = HashMap::new();
6508 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6509
6510 let request =
6511 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6512 .headers(headers);
6513
6514 let json = serde_json::to_value(&request).unwrap();
6515 assert_eq!(
6516 json,
6517 json!({
6518 "id": "main",
6519 "apiType": "openai",
6520 "baseUrl": "https://api.openai.com/v1",
6521 "headers": {
6522 "Authorization": "Bearer sk-test"
6523 }
6524 })
6525 );
6526
6527 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6528 assert_eq!(deserialized.id, "main");
6529 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6530 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6531 assert_eq!(deserialized.headers.len(), 1);
6532 assert_eq!(
6533 deserialized.headers.get("Authorization").unwrap(),
6534 "Bearer sk-test"
6535 );
6536 }
6537
6538 #[cfg(feature = "unstable_llm_providers")]
6539 #[test]
6540 fn test_set_provider_request_omits_empty_headers() {
6541 let request =
6542 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6543
6544 let json = serde_json::to_value(&request).unwrap();
6545 // headers should be omitted when empty
6546 assert!(!json.as_object().unwrap().contains_key("headers"));
6547 }
6548
6549 #[cfg(feature = "unstable_llm_providers")]
6550 #[test]
6551 fn test_disable_provider_request_serialization() {
6552 let request = DisableProviderRequest::new("secondary");
6553
6554 let json = serde_json::to_value(&request).unwrap();
6555 assert_eq!(json, json!({ "id": "secondary" }));
6556
6557 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6558 assert_eq!(deserialized.id, "secondary");
6559 }
6560
6561 #[cfg(feature = "unstable_llm_providers")]
6562 #[test]
6563 fn test_providers_capabilities_serialization() {
6564 let caps = ProvidersCapabilities::new();
6565
6566 let json = serde_json::to_value(&caps).unwrap();
6567 assert_eq!(json, json!({}));
6568
6569 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6570 assert!(deserialized.meta.is_none());
6571 }
6572
6573 #[cfg(feature = "unstable_llm_providers")]
6574 #[test]
6575 fn test_agent_capabilities_with_providers() {
6576 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6577
6578 let json = serde_json::to_value(&caps).unwrap();
6579 assert_eq!(json["providers"], json!({}));
6580
6581 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6582 assert!(deserialized.providers.is_some());
6583 }
6584
6585 #[test]
6586 fn test_agent_capabilities_session_is_explicit() {
6587 let json = serde_json::to_value(AgentCapabilities::new()).unwrap();
6588 assert!(json.get("session").is_none());
6589
6590 let caps = AgentCapabilities::new().session(
6591 SessionCapabilities::new()
6592 .prompt(PromptCapabilities::new().image(PromptImageCapabilities::new()))
6593 .mcp(McpCapabilities::new().stdio(McpStdioCapabilities::new()))
6594 .load(SessionLoadCapabilities::new()),
6595 );
6596
6597 assert_eq!(
6598 serde_json::to_value(&caps).unwrap(),
6599 json!({
6600 "auth": {},
6601 "session": {
6602 "prompt": {
6603 "image": {}
6604 },
6605 "mcp": {
6606 "stdio": {}
6607 },
6608 "load": {}
6609 }
6610 })
6611 );
6612
6613 let deserialized: AgentCapabilities = serde_json::from_value(json!({
6614 "session": false
6615 }))
6616 .unwrap();
6617 assert!(deserialized.session.is_none());
6618 }
6619
6620 #[test]
6621 fn test_prompt_capabilities_serialize_supported_content_as_objects() {
6622 let caps = PromptCapabilities::new()
6623 .image(PromptImageCapabilities::new())
6624 .audio(PromptAudioCapabilities::new())
6625 .embedded_context(PromptEmbeddedContextCapabilities::new());
6626
6627 assert_eq!(
6628 serde_json::to_value(&caps).unwrap(),
6629 json!({
6630 "image": {},
6631 "audio": {},
6632 "embeddedContext": {}
6633 })
6634 );
6635
6636 let deserialized: PromptCapabilities = serde_json::from_value(json!({
6637 "image": null,
6638 "audio": false,
6639 "embeddedContext": {}
6640 }))
6641 .unwrap();
6642 assert!(deserialized.image.is_none());
6643 assert!(deserialized.audio.is_none());
6644 assert!(deserialized.embedded_context.is_some());
6645 }
6646
6647 #[test]
6648 fn test_mcp_capabilities_serialize_supported_transports_as_objects() {
6649 let caps = McpCapabilities::new()
6650 .stdio(McpStdioCapabilities::new())
6651 .http(McpHttpCapabilities::new());
6652
6653 assert_eq!(
6654 serde_json::to_value(&caps).unwrap(),
6655 json!({
6656 "stdio": {},
6657 "http": {}
6658 })
6659 );
6660
6661 let deserialized: McpCapabilities = serde_json::from_value(json!({
6662 "stdio": null,
6663 "http": false
6664 }))
6665 .unwrap();
6666 assert!(deserialized.stdio.is_none());
6667 assert!(deserialized.http.is_none());
6668 }
6669
6670 #[cfg(feature = "unstable_mcp_over_acp")]
6671 #[test]
6672 fn test_mcp_capabilities_serialize_acp_support_as_object() {
6673 let caps = McpCapabilities::new().acp(McpAcpCapabilities::new());
6674
6675 assert_eq!(
6676 serde_json::to_value(&caps).unwrap(),
6677 json!({
6678 "acp": {}
6679 })
6680 );
6681 }
6682}