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 /// **UNSTABLE**
2192 ///
2193 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2194 ///
2195 /// Model-related configuration parameter.
2196 #[cfg(feature = "unstable_model_config_category")]
2197 ModelConfig,
2198 /// Thought/reasoning level selector.
2199 ThoughtLevel,
2200 /// Custom or future category.
2201 ///
2202 /// Values beginning with `_` are reserved for implementation-specific
2203 /// extensions. Unknown values that do not begin with `_` are reserved for
2204 /// future ACP variants.
2205 #[serde(untagged)]
2206 Other(String),
2207}
2208
2209/// Type-specific session configuration option payload.
2210#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2211#[serde(tag = "type", rename_all = "snake_case")]
2212#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2213#[non_exhaustive]
2214pub enum SessionConfigKind {
2215 /// Single-value selector (dropdown).
2216 Select(SessionConfigSelect),
2217 /// **UNSTABLE**
2218 ///
2219 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2220 ///
2221 /// Boolean on/off toggle.
2222 #[cfg(feature = "unstable_boolean_config")]
2223 Boolean(SessionConfigBoolean),
2224 /// Custom or future session configuration option payload.
2225 ///
2226 /// Values beginning with `_` are reserved for implementation-specific
2227 /// extensions. Unknown values that do not begin with `_` are reserved for
2228 /// future ACP variants.
2229 ///
2230 /// Clients that do not understand this option type should preserve the raw
2231 /// payload when storing, replaying, proxying, or forwarding configuration
2232 /// data, and otherwise ignore the option or display it generically.
2233 #[serde(untagged)]
2234 Other(OtherSessionConfigKind),
2235}
2236
2237/// Custom or future session configuration option payload.
2238#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2239#[schemars(inline)]
2240#[schemars(transform = other_session_config_kind_schema)]
2241#[serde(rename_all = "camelCase")]
2242#[non_exhaustive]
2243pub struct OtherSessionConfigKind {
2244 /// Custom or future session configuration option type.
2245 ///
2246 /// Values beginning with `_` are reserved for implementation-specific
2247 /// extensions. Unknown values that do not begin with `_` are reserved for
2248 /// future ACP variants.
2249 #[serde(rename = "type")]
2250 pub type_: String,
2251 /// Additional fields from the unknown session configuration option payload.
2252 #[serde(flatten)]
2253 pub fields: BTreeMap<String, serde_json::Value>,
2254}
2255
2256impl OtherSessionConfigKind {
2257 /// Builds [`OtherSessionConfigKind`] from an unknown discriminator and preserves the remaining extension fields.
2258 #[must_use]
2259 pub fn new(type_: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2260 fields.remove("type");
2261 fields.remove("_meta");
2262 Self {
2263 type_: type_.into(),
2264 fields,
2265 }
2266 }
2267}
2268
2269impl<'de> Deserialize<'de> for OtherSessionConfigKind {
2270 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2271 where
2272 D: serde::Deserializer<'de>,
2273 {
2274 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2275 let type_ = fields
2276 .remove("type")
2277 .ok_or_else(|| serde::de::Error::missing_field("type"))?;
2278 let serde_json::Value::String(type_) = type_ else {
2279 return Err(serde::de::Error::custom("`type` must be a string"));
2280 };
2281
2282 if is_known_session_config_kind_type(&type_) {
2283 return Err(serde::de::Error::custom(format!(
2284 "known session configuration option `{type_}` did not match its schema"
2285 )));
2286 }
2287
2288 Ok(Self { type_, fields })
2289 }
2290}
2291
2292fn is_known_session_config_kind_type(type_: &str) -> bool {
2293 match type_ {
2294 "select" => true,
2295 #[cfg(feature = "unstable_boolean_config")]
2296 "boolean" => true,
2297 _ => false,
2298 }
2299}
2300
2301fn other_session_config_kind_schema(schema: &mut Schema) {
2302 super::schema_util::reject_known_string_discriminators(
2303 schema,
2304 "type",
2305 &[
2306 "select",
2307 #[cfg(feature = "unstable_boolean_config")]
2308 "boolean",
2309 ],
2310 );
2311}
2312
2313/// A session configuration option selector and its current state.
2314#[serde_as]
2315#[skip_serializing_none]
2316#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2317#[serde(rename_all = "camelCase")]
2318#[non_exhaustive]
2319pub struct SessionConfigOption {
2320 /// Unique identifier for the configuration option.
2321 pub id: SessionConfigId,
2322 /// Human-readable label for the option.
2323 pub name: String,
2324 /// Optional description for the Client to display to the user.
2325 #[serde(default)]
2326 pub description: Option<String>,
2327 /// Optional semantic category for this option (UX only).
2328 #[serde_as(deserialize_as = "DefaultOnError")]
2329 #[schemars(extend("x-deserialize-default-on-error" = true))]
2330 #[serde(default)]
2331 pub category: Option<SessionConfigOptionCategory>,
2332 /// Type-specific fields for this configuration option.
2333 #[serde(flatten)]
2334 pub kind: SessionConfigKind,
2335 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2336 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2337 /// these keys.
2338 ///
2339 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2340 #[serde(rename = "_meta")]
2341 pub meta: Option<Meta>,
2342}
2343
2344impl SessionConfigOption {
2345 /// Builds [`SessionConfigOption`] with the required fields set; optional fields start unset or empty.
2346 #[must_use]
2347 pub fn new(
2348 id: impl Into<SessionConfigId>,
2349 name: impl Into<String>,
2350 kind: SessionConfigKind,
2351 ) -> Self {
2352 Self {
2353 id: id.into(),
2354 name: name.into(),
2355 description: None,
2356 category: None,
2357 kind,
2358 meta: None,
2359 }
2360 }
2361
2362 /// Builds a select-style session configuration option with its current value and choices.
2363 #[must_use]
2364 pub fn select(
2365 id: impl Into<SessionConfigId>,
2366 name: impl Into<String>,
2367 current_value: impl Into<SessionConfigValueId>,
2368 options: impl Into<SessionConfigSelectOptions>,
2369 ) -> Self {
2370 Self::new(
2371 id,
2372 name,
2373 SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2374 )
2375 }
2376
2377 /// **UNSTABLE**
2378 ///
2379 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2380 #[cfg(feature = "unstable_boolean_config")]
2381 #[must_use]
2382 pub fn boolean(
2383 id: impl Into<SessionConfigId>,
2384 name: impl Into<String>,
2385 current_value: bool,
2386 ) -> Self {
2387 Self::new(
2388 id,
2389 name,
2390 SessionConfigKind::Boolean(SessionConfigBoolean::new(current_value)),
2391 )
2392 }
2393
2394 /// Sets or clears the optional `description` field.
2395 #[must_use]
2396 pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2397 self.description = description.into_option();
2398 self
2399 }
2400
2401 /// Sets or clears the optional `category` field.
2402 #[must_use]
2403 pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2404 self.category = category.into_option();
2405 self
2406 }
2407
2408 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2409 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2410 /// these keys.
2411 ///
2412 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2413 #[must_use]
2414 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2415 self.meta = meta.into_option();
2416 self
2417 }
2418}
2419
2420/// **UNSTABLE**
2421///
2422/// This capability is not part of the spec yet, and may be removed or changed at any point.
2423///
2424/// The value to set for a session configuration option.
2425///
2426/// The `type` field acts as the discriminator in the serialized JSON form.
2427/// When no `type` is present, the value is treated as a [`SessionConfigValueId`]
2428/// via the [`ValueId`](Self::ValueId) fallback variant.
2429///
2430/// The `type` discriminator describes the *shape* of the value, not the option
2431/// kind. For example every option kind that picks from a list of ids
2432/// (`select`, `radio`, …) would use [`ValueId`](Self::ValueId), while a
2433/// future freeform text option would get its own variant.
2434#[cfg(feature = "unstable_boolean_config")]
2435#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2436#[serde(tag = "type", rename_all = "snake_case")]
2437#[non_exhaustive]
2438pub enum SessionConfigOptionValue {
2439 /// A boolean value (`type: "boolean"`).
2440 Boolean {
2441 /// The boolean value.
2442 value: bool,
2443 },
2444 /// A [`SessionConfigValueId`] string value.
2445 ///
2446 /// This is the default when `type` is absent on the wire. Unknown `type`
2447 /// values with string payloads also gracefully deserialize into this
2448 /// variant.
2449 #[serde(untagged)]
2450 ValueId {
2451 /// The value ID.
2452 value: SessionConfigValueId,
2453 },
2454}
2455
2456#[cfg(feature = "unstable_boolean_config")]
2457impl SessionConfigOptionValue {
2458 /// Create a value-id option value (used by `select` and other id-based option types).
2459 #[must_use]
2460 pub fn value_id(id: impl Into<SessionConfigValueId>) -> Self {
2461 Self::ValueId { value: id.into() }
2462 }
2463
2464 /// Create a boolean option value.
2465 #[must_use]
2466 pub fn boolean(val: bool) -> Self {
2467 Self::Boolean { value: val }
2468 }
2469
2470 /// Return the inner [`SessionConfigValueId`] if this is a
2471 /// [`ValueId`](Self::ValueId) value.
2472 #[must_use]
2473 pub fn as_value_id(&self) -> Option<&SessionConfigValueId> {
2474 match self {
2475 Self::ValueId { value } => Some(value),
2476 _ => None,
2477 }
2478 }
2479
2480 /// Return the inner [`bool`] if this is a [`Boolean`](Self::Boolean) value.
2481 #[must_use]
2482 pub fn as_bool(&self) -> Option<bool> {
2483 match self {
2484 Self::Boolean { value } => Some(*value),
2485 _ => None,
2486 }
2487 }
2488}
2489
2490#[cfg(feature = "unstable_boolean_config")]
2491impl From<SessionConfigValueId> for SessionConfigOptionValue {
2492 fn from(value: SessionConfigValueId) -> Self {
2493 Self::ValueId { value }
2494 }
2495}
2496
2497#[cfg(feature = "unstable_boolean_config")]
2498impl From<bool> for SessionConfigOptionValue {
2499 fn from(value: bool) -> Self {
2500 Self::Boolean { value }
2501 }
2502}
2503
2504#[cfg(feature = "unstable_boolean_config")]
2505impl From<&str> for SessionConfigOptionValue {
2506 fn from(value: &str) -> Self {
2507 Self::ValueId {
2508 value: SessionConfigValueId::new(value),
2509 }
2510 }
2511}
2512
2513/// Request parameters for setting a session configuration option.
2514#[skip_serializing_none]
2515#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2516#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2517#[serde(rename_all = "camelCase")]
2518#[non_exhaustive]
2519pub struct SetSessionConfigOptionRequest {
2520 /// The ID of the session to set the configuration option for.
2521 pub session_id: SessionId,
2522 /// The ID of the configuration option to set.
2523 pub config_id: SessionConfigId,
2524 /// The value to set, including a `type` discriminator and the raw `value`.
2525 ///
2526 /// When `type` is absent on the wire, defaults to treating the value as a
2527 /// [`SessionConfigValueId`] for `select` options.
2528 #[cfg(feature = "unstable_boolean_config")]
2529 #[serde(flatten)]
2530 pub value: SessionConfigOptionValue,
2531 /// The ID of the configuration option value to set.
2532 #[cfg(not(feature = "unstable_boolean_config"))]
2533 pub value: SessionConfigValueId,
2534 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2535 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2536 /// these keys.
2537 ///
2538 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2539 #[serde(rename = "_meta")]
2540 pub meta: Option<Meta>,
2541}
2542
2543impl SetSessionConfigOptionRequest {
2544 /// Builds [`SetSessionConfigOptionRequest`] with the required request fields set; optional fields start unset or empty.
2545 #[cfg(feature = "unstable_boolean_config")]
2546 #[must_use]
2547 pub fn new(
2548 session_id: impl Into<SessionId>,
2549 config_id: impl Into<SessionConfigId>,
2550 value: impl Into<SessionConfigOptionValue>,
2551 ) -> Self {
2552 Self {
2553 session_id: session_id.into(),
2554 config_id: config_id.into(),
2555 value: value.into(),
2556 meta: None,
2557 }
2558 }
2559
2560 /// Builds a select-value `session/set_config_option` request for crates built
2561 /// without boolean session configuration support.
2562 #[cfg(not(feature = "unstable_boolean_config"))]
2563 #[must_use]
2564 pub fn new(
2565 session_id: impl Into<SessionId>,
2566 config_id: impl Into<SessionConfigId>,
2567 value: impl Into<SessionConfigValueId>,
2568 ) -> Self {
2569 Self {
2570 session_id: session_id.into(),
2571 config_id: config_id.into(),
2572 value: value.into(),
2573 meta: None,
2574 }
2575 }
2576
2577 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2578 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2579 /// these keys.
2580 ///
2581 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2582 #[must_use]
2583 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2584 self.meta = meta.into_option();
2585 self
2586 }
2587}
2588
2589/// Response to `session/set_config_option` method.
2590#[serde_as]
2591#[skip_serializing_none]
2592#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2593#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2594#[serde(rename_all = "camelCase")]
2595#[non_exhaustive]
2596pub struct SetSessionConfigOptionResponse {
2597 /// The full set of configuration options and their current values.
2598 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2599 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2600 pub config_options: Vec<SessionConfigOption>,
2601 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2602 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2603 /// these keys.
2604 ///
2605 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2606 #[serde(rename = "_meta")]
2607 pub meta: Option<Meta>,
2608}
2609
2610impl SetSessionConfigOptionResponse {
2611 /// Builds [`SetSessionConfigOptionResponse`] with the required response fields set; optional fields start unset or empty.
2612 #[must_use]
2613 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2614 Self {
2615 config_options,
2616 meta: None,
2617 }
2618 }
2619
2620 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2621 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2622 /// these keys.
2623 ///
2624 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2625 #[must_use]
2626 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2627 self.meta = meta.into_option();
2628 self
2629 }
2630}
2631
2632// MCP
2633
2634/// Configuration for connecting to an MCP (Model Context Protocol) server.
2635///
2636/// MCP servers provide tools and context that the agent can use when
2637/// processing prompts.
2638///
2639/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
2640#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2641#[serde(tag = "type", rename_all = "snake_case")]
2642#[schemars(extend("discriminator" = {"propertyName": "type"}))]
2643#[non_exhaustive]
2644pub enum McpServer {
2645 /// HTTP transport configuration
2646 ///
2647 /// Only available when the Agent capabilities include `session.mcp.http`.
2648 Http(McpServerHttp),
2649 /// **UNSTABLE**
2650 ///
2651 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2652 ///
2653 /// ACP transport configuration
2654 ///
2655 /// Only available when the Agent capabilities include `session.mcp.acp`.
2656 /// The MCP server is provided by an ACP component and communicates over the ACP channel.
2657 #[cfg(feature = "unstable_mcp_over_acp")]
2658 Acp(McpServerAcp),
2659 /// Stdio transport configuration
2660 ///
2661 /// Only available when the Agent capabilities include `session.mcp.stdio`.
2662 Stdio(McpServerStdio),
2663 /// Custom or future MCP server transport configuration.
2664 ///
2665 /// Values beginning with `_` are reserved for implementation-specific
2666 /// extensions. Unknown values that do not begin with `_` are reserved for
2667 /// future ACP variants.
2668 ///
2669 /// Receivers that do not understand this transport should preserve the raw
2670 /// payload when storing, replaying, proxying, or forwarding session setup
2671 /// data, and otherwise ignore it or reject the server configuration.
2672 #[serde(untagged)]
2673 Other(OtherMcpServer),
2674}
2675
2676/// Custom or future MCP server transport payload.
2677#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2678#[schemars(inline)]
2679#[schemars(transform = other_mcp_server_schema)]
2680#[serde(rename_all = "camelCase")]
2681#[non_exhaustive]
2682pub struct OtherMcpServer {
2683 /// Custom or future MCP server transport type.
2684 ///
2685 /// Values beginning with `_` are reserved for implementation-specific
2686 /// extensions. Unknown values that do not begin with `_` are reserved for
2687 /// future ACP variants.
2688 #[serde(rename = "type")]
2689 pub type_: String,
2690 /// Additional fields from the unknown MCP server transport payload.
2691 #[serde(flatten)]
2692 pub fields: BTreeMap<String, serde_json::Value>,
2693}
2694
2695impl OtherMcpServer {
2696 /// Builds [`OtherMcpServer`] from an unknown discriminator and preserves the remaining extension fields.
2697 #[must_use]
2698 pub fn new(type_: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2699 fields.remove("type");
2700 Self {
2701 type_: type_.into(),
2702 fields,
2703 }
2704 }
2705}
2706
2707impl<'de> Deserialize<'de> for OtherMcpServer {
2708 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2709 where
2710 D: serde::Deserializer<'de>,
2711 {
2712 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2713 let type_ = fields
2714 .remove("type")
2715 .ok_or_else(|| serde::de::Error::missing_field("type"))?;
2716 let serde_json::Value::String(type_) = type_ else {
2717 return Err(serde::de::Error::custom("`type` must be a string"));
2718 };
2719
2720 if is_known_mcp_server_type(&type_) {
2721 return Err(serde::de::Error::custom(format!(
2722 "known MCP server transport `{type_}` did not match its schema"
2723 )));
2724 }
2725
2726 Ok(Self { type_, fields })
2727 }
2728}
2729
2730fn is_known_mcp_server_type(type_: &str) -> bool {
2731 match type_ {
2732 "http" | "stdio" => true,
2733 #[cfg(feature = "unstable_mcp_over_acp")]
2734 "acp" => true,
2735 _ => false,
2736 }
2737}
2738
2739fn other_mcp_server_schema(schema: &mut Schema) {
2740 super::schema_util::reject_known_string_discriminators(
2741 schema,
2742 "type",
2743 &[
2744 "http",
2745 "stdio",
2746 #[cfg(feature = "unstable_mcp_over_acp")]
2747 "acp",
2748 ],
2749 );
2750}
2751
2752/// HTTP transport configuration for MCP.
2753#[skip_serializing_none]
2754#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2755#[serde(rename_all = "camelCase")]
2756#[non_exhaustive]
2757pub struct McpServerHttp {
2758 /// Human-readable name identifying this MCP server.
2759 pub name: String,
2760 /// URL to the MCP server.
2761 pub url: String,
2762 /// HTTP headers to set when making requests to the MCP server.
2763 pub headers: Vec<HttpHeader>,
2764 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2765 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2766 /// these keys.
2767 ///
2768 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2769 #[serde(rename = "_meta")]
2770 pub meta: Option<Meta>,
2771}
2772
2773impl McpServerHttp {
2774 /// Builds [`McpServerHttp`] with the required fields set; optional fields start unset or empty.
2775 #[must_use]
2776 pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2777 Self {
2778 name: name.into(),
2779 url: url.into(),
2780 headers: Vec::new(),
2781 meta: None,
2782 }
2783 }
2784
2785 /// HTTP headers to set when making requests to the MCP server.
2786 #[must_use]
2787 pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2788 self.headers = headers;
2789 self
2790 }
2791
2792 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2793 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2794 /// these keys.
2795 ///
2796 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2797 #[must_use]
2798 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2799 self.meta = meta.into_option();
2800 self
2801 }
2802}
2803
2804/// **UNSTABLE**
2805///
2806/// This capability is not part of the spec yet, and may be removed or changed at any point.
2807///
2808/// Unique identifier for an MCP server using the ACP transport.
2809///
2810/// The value is opaque and generated by the ACP component providing the MCP server. It is
2811/// used by `mcp/connect` to route connection requests back to the component that declared the
2812/// server.
2813#[cfg(feature = "unstable_mcp_over_acp")]
2814#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2815#[serde(transparent)]
2816#[from(Arc<str>, String, &'static str)]
2817#[non_exhaustive]
2818pub struct McpServerAcpId(pub Arc<str>);
2819
2820#[cfg(feature = "unstable_mcp_over_acp")]
2821impl McpServerAcpId {
2822 /// Wraps a protocol string as a typed [`McpServerAcpId`].
2823 #[must_use]
2824 pub fn new(id: impl Into<Arc<str>>) -> Self {
2825 Self(id.into())
2826 }
2827}
2828
2829/// **UNSTABLE**
2830///
2831/// This capability is not part of the spec yet, and may be removed or changed at any point.
2832///
2833/// ACP transport configuration for MCP.
2834///
2835/// The MCP server is provided by an ACP component and communicates over the ACP channel
2836/// using `mcp/connect`, `mcp/message`, and `mcp/disconnect`.
2837#[skip_serializing_none]
2838#[cfg(feature = "unstable_mcp_over_acp")]
2839#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2840#[serde(rename_all = "camelCase")]
2841#[non_exhaustive]
2842pub struct McpServerAcp {
2843 /// Human-readable name identifying this MCP server.
2844 pub name: String,
2845 /// Unique identifier for this MCP server, generated by the component providing it.
2846 ///
2847 /// Providers MUST NOT reuse an ID for multiple ACP-transport MCP servers that are visible
2848 /// on the same ACP connection.
2849 pub id: McpServerAcpId,
2850 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2851 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2852 /// these keys.
2853 ///
2854 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2855 #[serde(rename = "_meta")]
2856 pub meta: Option<Meta>,
2857}
2858
2859#[cfg(feature = "unstable_mcp_over_acp")]
2860impl McpServerAcp {
2861 /// Builds [`McpServerAcp`] with the required fields set; optional fields start unset or empty.
2862 #[must_use]
2863 pub fn new(name: impl Into<String>, id: impl Into<McpServerAcpId>) -> Self {
2864 Self {
2865 name: name.into(),
2866 id: id.into(),
2867 meta: None,
2868 }
2869 }
2870
2871 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2872 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2873 /// these keys.
2874 ///
2875 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2876 #[must_use]
2877 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2878 self.meta = meta.into_option();
2879 self
2880 }
2881}
2882
2883/// Stdio transport configuration for MCP.
2884#[skip_serializing_none]
2885#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2886#[serde(rename_all = "camelCase")]
2887#[non_exhaustive]
2888pub struct McpServerStdio {
2889 /// Human-readable name identifying this MCP server.
2890 pub name: String,
2891 /// Path to the MCP server executable.
2892 pub command: PathBuf,
2893 /// Command-line arguments to pass to the MCP server.
2894 pub args: Vec<String>,
2895 /// Environment variables to set when launching the MCP server.
2896 pub env: Vec<EnvVariable>,
2897 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2898 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2899 /// these keys.
2900 ///
2901 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2902 #[serde(rename = "_meta")]
2903 pub meta: Option<Meta>,
2904}
2905
2906impl McpServerStdio {
2907 /// Builds [`McpServerStdio`] with the required fields set; optional fields start unset or empty.
2908 #[must_use]
2909 pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2910 Self {
2911 name: name.into(),
2912 command: command.into(),
2913 args: Vec::new(),
2914 env: Vec::new(),
2915 meta: None,
2916 }
2917 }
2918
2919 /// Command-line arguments to pass to the MCP server.
2920 #[must_use]
2921 pub fn args(mut self, args: Vec<String>) -> Self {
2922 self.args = args;
2923 self
2924 }
2925
2926 /// Environment variables to set when launching the MCP server.
2927 #[must_use]
2928 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2929 self.env = env;
2930 self
2931 }
2932
2933 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2934 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2935 /// these keys.
2936 ///
2937 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2938 #[must_use]
2939 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2940 self.meta = meta.into_option();
2941 self
2942 }
2943}
2944
2945/// An environment variable to set when launching an MCP server.
2946#[skip_serializing_none]
2947#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2948#[serde(rename_all = "camelCase")]
2949#[non_exhaustive]
2950pub struct EnvVariable {
2951 /// The name of the environment variable.
2952 pub name: String,
2953 /// The value to set for the environment variable.
2954 pub value: String,
2955 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2956 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2957 /// these keys.
2958 ///
2959 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2960 #[serde(rename = "_meta")]
2961 pub meta: Option<Meta>,
2962}
2963
2964impl EnvVariable {
2965 /// Builds [`EnvVariable`] with the required fields set; optional fields start unset or empty.
2966 #[must_use]
2967 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2968 Self {
2969 name: name.into(),
2970 value: value.into(),
2971 meta: None,
2972 }
2973 }
2974
2975 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2976 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2977 /// these keys.
2978 ///
2979 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2980 #[must_use]
2981 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2982 self.meta = meta.into_option();
2983 self
2984 }
2985}
2986
2987/// An HTTP header to set when making requests to the MCP server.
2988#[skip_serializing_none]
2989#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2990#[serde(rename_all = "camelCase")]
2991#[non_exhaustive]
2992pub struct HttpHeader {
2993 /// The name of the HTTP header.
2994 pub name: String,
2995 /// The value to set for the HTTP header.
2996 pub value: String,
2997 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2998 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2999 /// these keys.
3000 ///
3001 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3002 #[serde(rename = "_meta")]
3003 pub meta: Option<Meta>,
3004}
3005
3006impl HttpHeader {
3007 /// Builds [`HttpHeader`] with the required fields set; optional fields start unset or empty.
3008 #[must_use]
3009 pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
3010 Self {
3011 name: name.into(),
3012 value: value.into(),
3013 meta: None,
3014 }
3015 }
3016
3017 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3018 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3019 /// these keys.
3020 ///
3021 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3022 #[must_use]
3023 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3024 self.meta = meta.into_option();
3025 self
3026 }
3027}
3028
3029// Prompt
3030
3031/// Request parameters for sending a user prompt to the agent.
3032///
3033/// Contains the user's message and any additional context.
3034///
3035/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-lifecycle#1-user-message)
3036#[skip_serializing_none]
3037#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
3038#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3039#[serde(rename_all = "camelCase")]
3040#[non_exhaustive]
3041pub struct PromptRequest {
3042 /// The ID of the session to send this user message to
3043 pub session_id: SessionId,
3044 /// The blocks of content that compose the user's message.
3045 ///
3046 /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
3047 /// while other variants are optionally enabled via [`PromptCapabilities`].
3048 ///
3049 /// The Client MUST adapt its interface according to [`PromptCapabilities`].
3050 ///
3051 /// The client MAY include referenced pieces of context as either
3052 /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
3053 ///
3054 /// When available, [`ContentBlock::Resource`] is preferred
3055 /// as it avoids extra round-trips and allows the message to include
3056 /// pieces of context from sources the agent may not have access to.
3057 pub prompt: Vec<ContentBlock>,
3058 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3059 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3060 /// these keys.
3061 ///
3062 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3063 #[serde(rename = "_meta")]
3064 pub meta: Option<Meta>,
3065}
3066
3067impl PromptRequest {
3068 /// Builds [`PromptRequest`] with the required request fields set; optional fields start unset or empty.
3069 #[must_use]
3070 pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
3071 Self {
3072 session_id: session_id.into(),
3073 prompt,
3074 meta: None,
3075 }
3076 }
3077
3078 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3079 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3080 /// these keys.
3081 ///
3082 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3083 #[must_use]
3084 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3085 self.meta = meta.into_option();
3086 self
3087 }
3088}
3089
3090/// Response acknowledging that a user prompt was accepted.
3091///
3092/// This response does not indicate that the agent has finished processing.
3093/// Agents report session state through `state_update` session updates.
3094///
3095/// See protocol docs: [Prompt Accepted](https://agentclientprotocol.com/protocol/prompt-lifecycle#2-prompt-accepted)
3096#[skip_serializing_none]
3097#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3098#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
3099#[serde(rename_all = "camelCase")]
3100#[non_exhaustive]
3101pub struct PromptResponse {
3102 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3103 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3104 /// these keys.
3105 ///
3106 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3107 #[serde(rename = "_meta")]
3108 pub meta: Option<Meta>,
3109}
3110
3111impl PromptResponse {
3112 /// Builds [`PromptResponse`] with the required response fields set; optional fields start unset or empty.
3113 #[must_use]
3114 pub fn new() -> Self {
3115 Self::default()
3116 }
3117
3118 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3119 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3120 /// these keys.
3121 ///
3122 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3123 #[must_use]
3124 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3125 self.meta = meta.into_option();
3126 self
3127 }
3128}
3129
3130/// Reasons why an agent stops active session work.
3131///
3132/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-lifecycle#stop-reasons)
3133#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
3134#[serde(rename_all = "snake_case")]
3135#[non_exhaustive]
3136pub enum StopReason {
3137 /// The active work ended successfully.
3138 EndTurn,
3139 /// The active work ended because the agent reached the maximum number of tokens.
3140 MaxTokens,
3141 /// The active work ended because the agent reached the maximum number of
3142 /// allowed agent requests before returning idle.
3143 MaxTurnRequests,
3144 /// The active work ended because the agent refused to continue. The user
3145 /// prompt and everything that comes after it won't be included in the next
3146 /// prompt, so this should be reflected in the UI.
3147 Refusal,
3148 /// Active session work was cancelled by the client via `session/cancel`.
3149 ///
3150 /// Agents should report this stop reason on an idle `state_update` session update
3151 /// when cancellation succeeds, even if cancellation causes exceptions in
3152 /// underlying operations.
3153 Cancelled,
3154 /// Custom or future stop reason.
3155 ///
3156 /// Values beginning with `_` are reserved for implementation-specific
3157 /// extensions. Unknown values that do not begin with `_` are reserved for
3158 /// future ACP variants.
3159 #[serde(untagged)]
3160 Other(String),
3161}
3162
3163/// **UNSTABLE**
3164///
3165/// This capability is not part of the spec yet, and may be removed or changed at any point.
3166///
3167/// Token usage information for completed session work.
3168#[cfg(feature = "unstable_end_turn_token_usage")]
3169#[skip_serializing_none]
3170#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3171#[serde(rename_all = "camelCase")]
3172#[non_exhaustive]
3173pub struct Usage {
3174 /// Sum of all token types across session.
3175 pub total_tokens: u64,
3176 /// Total input tokens.
3177 pub input_tokens: u64,
3178 /// Total output tokens.
3179 pub output_tokens: u64,
3180 /// Total thought/reasoning tokens
3181 pub thought_tokens: Option<u64>,
3182 /// Total cache read tokens.
3183 pub cached_read_tokens: Option<u64>,
3184 /// Total cache write tokens.
3185 pub cached_write_tokens: Option<u64>,
3186 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3187 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3188 /// these keys.
3189 ///
3190 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3191 #[serde(rename = "_meta")]
3192 pub meta: Option<Meta>,
3193}
3194
3195#[cfg(feature = "unstable_end_turn_token_usage")]
3196impl Usage {
3197 /// Builds [`Usage`] with the required fields set; optional fields start unset or empty.
3198 #[must_use]
3199 pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
3200 Self {
3201 total_tokens,
3202 input_tokens,
3203 output_tokens,
3204 thought_tokens: None,
3205 cached_read_tokens: None,
3206 cached_write_tokens: None,
3207 meta: None,
3208 }
3209 }
3210
3211 /// Total thought/reasoning tokens
3212 #[must_use]
3213 pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
3214 self.thought_tokens = thought_tokens.into_option();
3215 self
3216 }
3217
3218 /// Total cache read tokens.
3219 #[must_use]
3220 pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
3221 self.cached_read_tokens = cached_read_tokens.into_option();
3222 self
3223 }
3224
3225 /// Total cache write tokens.
3226 #[must_use]
3227 pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
3228 self.cached_write_tokens = cached_write_tokens.into_option();
3229 self
3230 }
3231
3232 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3233 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3234 /// these keys.
3235 ///
3236 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3237 #[must_use]
3238 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3239 self.meta = meta.into_option();
3240 self
3241 }
3242}
3243
3244// Providers
3245
3246/// **UNSTABLE**
3247///
3248/// This capability is not part of the spec yet, and may be removed or changed at any point.
3249///
3250/// Well-known API protocol identifiers for LLM providers.
3251///
3252/// Agents and clients MUST handle unknown protocol identifiers gracefully.
3253///
3254/// Protocol names beginning with `_` are free for custom use, like other ACP extension methods.
3255/// Protocol names that do not begin with `_` are reserved for the ACP spec.
3256#[cfg(feature = "unstable_llm_providers")]
3257#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3258#[serde(rename_all = "snake_case")]
3259#[non_exhaustive]
3260#[expect(clippy::doc_markdown)]
3261pub enum LlmProtocol {
3262 /// Anthropic API protocol.
3263 Anthropic,
3264 /// OpenAI API protocol.
3265 #[serde(rename = "openai")]
3266 OpenAi,
3267 /// Azure OpenAI API protocol.
3268 Azure,
3269 /// Google Vertex AI API protocol.
3270 Vertex,
3271 /// AWS Bedrock API protocol.
3272 Bedrock,
3273 /// Custom or future protocol.
3274 ///
3275 /// Values beginning with `_` are reserved for implementation-specific
3276 /// extensions. Unknown values that do not begin with `_` are reserved for
3277 /// future ACP variants.
3278 #[serde(untagged)]
3279 Other(String),
3280}
3281
3282/// **UNSTABLE**
3283///
3284/// This capability is not part of the spec yet, and may be removed or changed at any point.
3285///
3286/// Current effective non-secret routing configuration for a provider.
3287#[cfg(feature = "unstable_llm_providers")]
3288#[skip_serializing_none]
3289#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3290#[serde(rename_all = "camelCase")]
3291#[non_exhaustive]
3292pub struct ProviderCurrentConfig {
3293 /// Protocol currently used by this provider.
3294 pub api_type: LlmProtocol,
3295 /// Base URL currently used by this provider.
3296 pub base_url: String,
3297 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3298 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3299 /// these keys.
3300 ///
3301 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3302 #[serde(rename = "_meta")]
3303 pub meta: Option<Meta>,
3304}
3305
3306#[cfg(feature = "unstable_llm_providers")]
3307impl ProviderCurrentConfig {
3308 /// Builds [`ProviderCurrentConfig`] with the required fields set; optional fields start unset or empty.
3309 #[must_use]
3310 pub fn new(api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3311 Self {
3312 api_type,
3313 base_url: base_url.into(),
3314 meta: None,
3315 }
3316 }
3317
3318 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3319 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3320 /// these keys.
3321 ///
3322 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3323 #[must_use]
3324 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3325 self.meta = meta.into_option();
3326 self
3327 }
3328}
3329
3330/// **UNSTABLE**
3331///
3332/// This capability is not part of the spec yet, and may be removed or changed at any point.
3333///
3334/// Information about a configurable LLM provider.
3335#[cfg(feature = "unstable_llm_providers")]
3336#[serde_as]
3337#[skip_serializing_none]
3338#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3339#[serde(rename_all = "camelCase")]
3340#[non_exhaustive]
3341pub struct ProviderInfo {
3342 /// Provider identifier, for example "main" or "openai".
3343 pub id: String,
3344 /// Supported protocol types for this provider.
3345 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3346 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3347 pub supported: Vec<LlmProtocol>,
3348 /// Whether this provider is mandatory and cannot be disabled via `providers/disable`.
3349 /// If true, clients must not call `providers/disable` for this id.
3350 pub required: bool,
3351 /// Current effective non-secret routing config.
3352 /// Null or omitted means provider is disabled.
3353 pub current: Option<ProviderCurrentConfig>,
3354 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3355 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3356 /// these keys.
3357 ///
3358 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3359 #[serde(rename = "_meta")]
3360 pub meta: Option<Meta>,
3361}
3362
3363#[cfg(feature = "unstable_llm_providers")]
3364impl ProviderInfo {
3365 /// Builds [`ProviderInfo`] with the required fields set; optional fields start unset or empty.
3366 #[must_use]
3367 pub fn new(
3368 id: impl Into<String>,
3369 supported: Vec<LlmProtocol>,
3370 required: bool,
3371 current: impl IntoOption<ProviderCurrentConfig>,
3372 ) -> Self {
3373 Self {
3374 id: id.into(),
3375 supported,
3376 required,
3377 current: current.into_option(),
3378 meta: None,
3379 }
3380 }
3381
3382 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3383 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3384 /// these keys.
3385 ///
3386 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3387 #[must_use]
3388 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3389 self.meta = meta.into_option();
3390 self
3391 }
3392}
3393
3394/// **UNSTABLE**
3395///
3396/// This capability is not part of the spec yet, and may be removed or changed at any point.
3397///
3398/// Request parameters for `providers/list`.
3399#[cfg(feature = "unstable_llm_providers")]
3400#[skip_serializing_none]
3401#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3402#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3403#[serde(rename_all = "camelCase")]
3404#[non_exhaustive]
3405pub struct ListProvidersRequest {
3406 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3407 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3408 /// these keys.
3409 ///
3410 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3411 #[serde(rename = "_meta")]
3412 pub meta: Option<Meta>,
3413}
3414
3415#[cfg(feature = "unstable_llm_providers")]
3416impl ListProvidersRequest {
3417 /// Builds [`ListProvidersRequest`] with the required request fields set; optional fields start unset or empty.
3418 #[must_use]
3419 pub fn new() -> Self {
3420 Self::default()
3421 }
3422
3423 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3424 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3425 /// these keys.
3426 ///
3427 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3428 #[must_use]
3429 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3430 self.meta = meta.into_option();
3431 self
3432 }
3433}
3434
3435/// **UNSTABLE**
3436///
3437/// This capability is not part of the spec yet, and may be removed or changed at any point.
3438///
3439/// Response to `providers/list`.
3440#[cfg(feature = "unstable_llm_providers")]
3441#[serde_as]
3442#[skip_serializing_none]
3443#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3444#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_LIST_METHOD_NAME))]
3445#[serde(rename_all = "camelCase")]
3446#[non_exhaustive]
3447pub struct ListProvidersResponse {
3448 /// Configurable providers with current routing info suitable for UI display.
3449 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
3450 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
3451 pub providers: Vec<ProviderInfo>,
3452 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3453 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3454 /// these keys.
3455 ///
3456 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3457 #[serde(rename = "_meta")]
3458 pub meta: Option<Meta>,
3459}
3460
3461#[cfg(feature = "unstable_llm_providers")]
3462impl ListProvidersResponse {
3463 /// Builds [`ListProvidersResponse`] with the required response fields set; optional fields start unset or empty.
3464 #[must_use]
3465 pub fn new(providers: Vec<ProviderInfo>) -> Self {
3466 Self {
3467 providers,
3468 meta: None,
3469 }
3470 }
3471
3472 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3473 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3474 /// these keys.
3475 ///
3476 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3477 #[must_use]
3478 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3479 self.meta = meta.into_option();
3480 self
3481 }
3482}
3483
3484/// **UNSTABLE**
3485///
3486/// This capability is not part of the spec yet, and may be removed or changed at any point.
3487///
3488/// Request parameters for `providers/set`.
3489///
3490/// Replaces the full configuration for one provider id.
3491#[cfg(feature = "unstable_llm_providers")]
3492#[skip_serializing_none]
3493#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3494#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3495#[serde(rename_all = "camelCase")]
3496#[non_exhaustive]
3497pub struct SetProviderRequest {
3498 /// Provider id to configure.
3499 pub id: String,
3500 /// Protocol type for this provider.
3501 pub api_type: LlmProtocol,
3502 /// Base URL for requests sent through this provider.
3503 pub base_url: String,
3504 /// Full headers map for this provider.
3505 /// May include authorization, routing, or other integration-specific headers.
3506 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
3507 pub headers: HashMap<String, String>,
3508 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3509 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3510 /// these keys.
3511 ///
3512 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3513 #[serde(rename = "_meta")]
3514 pub meta: Option<Meta>,
3515}
3516
3517#[cfg(feature = "unstable_llm_providers")]
3518impl SetProviderRequest {
3519 /// Builds [`SetProviderRequest`] with the required request fields set; optional fields start unset or empty.
3520 #[must_use]
3521 pub fn new(id: impl Into<String>, api_type: LlmProtocol, base_url: impl Into<String>) -> Self {
3522 Self {
3523 id: id.into(),
3524 api_type,
3525 base_url: base_url.into(),
3526 headers: HashMap::new(),
3527 meta: None,
3528 }
3529 }
3530
3531 /// Full headers map for this provider.
3532 /// May include authorization, routing, or other integration-specific headers.
3533 #[must_use]
3534 pub fn headers(mut self, headers: HashMap<String, String>) -> Self {
3535 self.headers = headers;
3536 self
3537 }
3538
3539 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3540 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3541 /// these keys.
3542 ///
3543 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3544 #[must_use]
3545 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3546 self.meta = meta.into_option();
3547 self
3548 }
3549}
3550
3551/// **UNSTABLE**
3552///
3553/// This capability is not part of the spec yet, and may be removed or changed at any point.
3554///
3555/// Response to `providers/set`.
3556#[cfg(feature = "unstable_llm_providers")]
3557#[skip_serializing_none]
3558#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3559#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_SET_METHOD_NAME))]
3560#[serde(rename_all = "camelCase")]
3561#[non_exhaustive]
3562pub struct SetProviderResponse {
3563 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3564 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3565 /// these keys.
3566 ///
3567 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3568 #[serde(rename = "_meta")]
3569 pub meta: Option<Meta>,
3570}
3571
3572#[cfg(feature = "unstable_llm_providers")]
3573impl SetProviderResponse {
3574 /// Builds [`SetProviderResponse`] with the required response fields set; optional fields start unset or empty.
3575 #[must_use]
3576 pub fn new() -> Self {
3577 Self::default()
3578 }
3579
3580 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3581 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3582 /// these keys.
3583 ///
3584 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3585 #[must_use]
3586 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3587 self.meta = meta.into_option();
3588 self
3589 }
3590}
3591
3592/// **UNSTABLE**
3593///
3594/// This capability is not part of the spec yet, and may be removed or changed at any point.
3595///
3596/// Request parameters for `providers/disable`.
3597#[cfg(feature = "unstable_llm_providers")]
3598#[skip_serializing_none]
3599#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3600#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3601#[serde(rename_all = "camelCase")]
3602#[non_exhaustive]
3603pub struct DisableProviderRequest {
3604 /// Provider id to disable.
3605 pub id: String,
3606 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3607 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3608 /// these keys.
3609 ///
3610 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3611 #[serde(rename = "_meta")]
3612 pub meta: Option<Meta>,
3613}
3614
3615#[cfg(feature = "unstable_llm_providers")]
3616impl DisableProviderRequest {
3617 /// Builds [`DisableProviderRequest`] with the required request fields set; optional fields start unset or empty.
3618 #[must_use]
3619 pub fn new(id: impl Into<String>) -> Self {
3620 Self {
3621 id: id.into(),
3622 meta: None,
3623 }
3624 }
3625
3626 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3627 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3628 /// these keys.
3629 ///
3630 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3631 #[must_use]
3632 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3633 self.meta = meta.into_option();
3634 self
3635 }
3636}
3637
3638/// **UNSTABLE**
3639///
3640/// This capability is not part of the spec yet, and may be removed or changed at any point.
3641///
3642/// Response to `providers/disable`.
3643#[cfg(feature = "unstable_llm_providers")]
3644#[skip_serializing_none]
3645#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3646#[schemars(extend("x-side" = "agent", "x-method" = PROVIDERS_DISABLE_METHOD_NAME))]
3647#[serde(rename_all = "camelCase")]
3648#[non_exhaustive]
3649pub struct DisableProviderResponse {
3650 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3651 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3652 /// these keys.
3653 ///
3654 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3655 #[serde(rename = "_meta")]
3656 pub meta: Option<Meta>,
3657}
3658
3659#[cfg(feature = "unstable_llm_providers")]
3660impl DisableProviderResponse {
3661 /// Builds [`DisableProviderResponse`] with the required response fields set; optional fields start unset or empty.
3662 #[must_use]
3663 pub fn new() -> Self {
3664 Self::default()
3665 }
3666
3667 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3668 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3669 /// these keys.
3670 ///
3671 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3672 #[must_use]
3673 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3674 self.meta = meta.into_option();
3675 self
3676 }
3677}
3678
3679// Capabilities
3680
3681/// Capabilities supported by the agent.
3682///
3683/// Advertised during initialization to inform the client about
3684/// available features and content types.
3685///
3686/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
3687#[serde_as]
3688#[skip_serializing_none]
3689#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3690#[serde(rename_all = "camelCase")]
3691#[non_exhaustive]
3692pub struct AgentCapabilities {
3693 /// Session capabilities supported by the agent.
3694 ///
3695 /// Optional. Omitted or `null` both mean the agent does not support the
3696 /// `session/*` method surface. Supplying `{}` means the agent supports the
3697 /// baseline session methods: `session/new`, `session/prompt`,
3698 /// `session/cancel`, and `session/update`.
3699 #[serde_as(deserialize_as = "DefaultOnError")]
3700 #[schemars(extend("x-deserialize-default-on-error" = true))]
3701 #[serde(default)]
3702 pub session: Option<SessionCapabilities>,
3703 /// Authentication-related capabilities supported by the agent.
3704 #[serde(default)]
3705 pub auth: AgentAuthCapabilities,
3706 /// **UNSTABLE**
3707 ///
3708 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3709 ///
3710 /// Provider configuration capabilities supported by the agent.
3711 ///
3712 /// By supplying `{}` it means that the agent supports provider configuration methods.
3713 #[cfg(feature = "unstable_llm_providers")]
3714 #[serde_as(deserialize_as = "DefaultOnError")]
3715 #[schemars(extend("x-deserialize-default-on-error" = true))]
3716 #[serde(default)]
3717 pub providers: Option<ProvidersCapabilities>,
3718 /// **UNSTABLE**
3719 ///
3720 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3721 ///
3722 /// NES (Next Edit Suggestions) capabilities supported by the agent.
3723 #[cfg(feature = "unstable_nes")]
3724 #[serde_as(deserialize_as = "DefaultOnError")]
3725 #[schemars(extend("x-deserialize-default-on-error" = true))]
3726 #[serde(default)]
3727 pub nes: Option<NesCapabilities>,
3728 /// **UNSTABLE**
3729 ///
3730 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3731 ///
3732 /// The position encoding selected by the agent from the client's supported encodings.
3733 #[cfg(feature = "unstable_nes")]
3734 #[serde_as(deserialize_as = "DefaultOnError")]
3735 #[schemars(extend("x-deserialize-default-on-error" = true))]
3736 #[serde(default)]
3737 pub position_encoding: Option<PositionEncodingKind>,
3738 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3739 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3740 /// these keys.
3741 ///
3742 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3743 #[serde(rename = "_meta")]
3744 pub meta: Option<Meta>,
3745}
3746
3747impl AgentCapabilities {
3748 /// Builds an empty [`AgentCapabilities`]; use builder methods to advertise supported sub-capabilities.
3749 #[must_use]
3750 pub fn new() -> Self {
3751 Self::default()
3752 }
3753
3754 /// Session capabilities supported by the agent.
3755 ///
3756 /// Omitted or `null` both mean the agent does not support the `session/*`
3757 /// method surface. Supplying `{}` means the agent supports the baseline
3758 /// session methods: `session/new`, `session/prompt`, `session/cancel`, and
3759 /// `session/update`.
3760 #[must_use]
3761 pub fn session(mut self, session: impl IntoOption<SessionCapabilities>) -> Self {
3762 self.session = session.into_option();
3763 self
3764 }
3765
3766 /// Authentication-related capabilities supported by the agent.
3767 #[must_use]
3768 pub fn auth(mut self, auth: AgentAuthCapabilities) -> Self {
3769 self.auth = auth;
3770 self
3771 }
3772
3773 /// **UNSTABLE**
3774 ///
3775 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3776 ///
3777 /// Provider configuration capabilities supported by the agent.
3778 #[cfg(feature = "unstable_llm_providers")]
3779 #[must_use]
3780 pub fn providers(mut self, providers: impl IntoOption<ProvidersCapabilities>) -> Self {
3781 self.providers = providers.into_option();
3782 self
3783 }
3784
3785 /// **UNSTABLE**
3786 ///
3787 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3788 ///
3789 /// NES (Next Edit Suggestions) capabilities supported by the agent.
3790 #[cfg(feature = "unstable_nes")]
3791 #[must_use]
3792 pub fn nes(mut self, nes: impl IntoOption<NesCapabilities>) -> Self {
3793 self.nes = nes.into_option();
3794 self
3795 }
3796
3797 /// **UNSTABLE**
3798 ///
3799 /// The position encoding selected by the agent from the client's supported encodings.
3800 #[cfg(feature = "unstable_nes")]
3801 #[must_use]
3802 pub fn position_encoding(
3803 mut self,
3804 position_encoding: impl IntoOption<PositionEncodingKind>,
3805 ) -> Self {
3806 self.position_encoding = position_encoding.into_option();
3807 self
3808 }
3809
3810 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3811 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3812 /// these keys.
3813 ///
3814 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3815 #[must_use]
3816 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3817 self.meta = meta.into_option();
3818 self
3819 }
3820}
3821
3822/// **UNSTABLE**
3823///
3824/// This capability is not part of the spec yet, and may be removed or changed at any point.
3825///
3826/// Provider configuration capabilities supported by the agent.
3827///
3828/// By supplying `{}` it means that the agent supports provider configuration methods.
3829#[cfg(feature = "unstable_llm_providers")]
3830#[skip_serializing_none]
3831#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3832#[non_exhaustive]
3833pub struct ProvidersCapabilities {
3834 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3835 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3836 /// these keys.
3837 ///
3838 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3839 #[serde(rename = "_meta")]
3840 pub meta: Option<Meta>,
3841}
3842
3843#[cfg(feature = "unstable_llm_providers")]
3844impl ProvidersCapabilities {
3845 /// Builds an empty [`ProvidersCapabilities`]; use builder methods to advertise supported sub-capabilities.
3846 #[must_use]
3847 pub fn new() -> Self {
3848 Self::default()
3849 }
3850
3851 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3852 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3853 /// these keys.
3854 ///
3855 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3856 #[must_use]
3857 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3858 self.meta = meta.into_option();
3859 self
3860 }
3861}
3862
3863/// Session capabilities supported by the agent.
3864///
3865/// Supplying `{}` means the agent supports the baseline session methods:
3866/// `session/new`, `session/prompt`, `session/cancel`, and `session/update`.
3867///
3868/// Agents that support sessions **MAY** support additional session methods,
3869/// prompt content types, and MCP transports by specifying additional
3870/// capabilities.
3871///
3872/// See protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)
3873#[serde_as]
3874#[skip_serializing_none]
3875#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3876#[serde(rename_all = "camelCase")]
3877#[non_exhaustive]
3878pub struct SessionCapabilities {
3879 /// Prompt capabilities supported by the agent in `session/prompt` requests.
3880 ///
3881 /// Optional. Omitted or `null` both mean the agent does not advertise any
3882 /// prompt extensions beyond the baseline text and resource-link content
3883 /// required by `session/prompt`.
3884 #[serde_as(deserialize_as = "DefaultOnError")]
3885 #[schemars(extend("x-deserialize-default-on-error" = true))]
3886 #[serde(default)]
3887 pub prompt: Option<PromptCapabilities>,
3888 /// MCP capabilities supported by the agent for session lifecycle requests.
3889 ///
3890 /// Optional. Omitted or `null` both mean the agent does not advertise MCP
3891 /// server transport support for sessions.
3892 #[serde_as(deserialize_as = "DefaultOnError")]
3893 #[schemars(extend("x-deserialize-default-on-error" = true))]
3894 #[serde(default)]
3895 pub mcp: Option<McpCapabilities>,
3896 /// Whether the agent supports `session/load`.
3897 ///
3898 /// Optional. Omitted or `null` both mean the agent does not advertise support.
3899 /// Supplying `{}` means the agent supports loading sessions.
3900 #[serde_as(deserialize_as = "DefaultOnError")]
3901 #[schemars(extend("x-deserialize-default-on-error" = true))]
3902 #[serde(default)]
3903 pub load: Option<SessionLoadCapabilities>,
3904 /// Whether the agent supports `session/list`.
3905 #[serde_as(deserialize_as = "DefaultOnError")]
3906 #[schemars(extend("x-deserialize-default-on-error" = true))]
3907 #[serde(default)]
3908 pub list: Option<SessionListCapabilities>,
3909 /// Whether the agent supports `session/delete`.
3910 ///
3911 /// Optional. Omitted or `null` both mean the agent does not advertise support.
3912 /// Supplying `{}` means the agent supports deleting sessions from `session/list`.
3913 #[serde_as(deserialize_as = "DefaultOnError")]
3914 #[schemars(extend("x-deserialize-default-on-error" = true))]
3915 #[serde(default)]
3916 pub delete: Option<SessionDeleteCapabilities>,
3917 /// Whether the agent supports `additionalDirectories` on supported session lifecycle requests.
3918 ///
3919 /// Agents that also support `session/list` may return
3920 /// `SessionInfo.additionalDirectories` to report the complete ordered
3921 /// additional-root list associated with a listed session.
3922 #[serde_as(deserialize_as = "DefaultOnError")]
3923 #[schemars(extend("x-deserialize-default-on-error" = true))]
3924 #[serde(default)]
3925 pub additional_directories: Option<SessionAdditionalDirectoriesCapabilities>,
3926 /// **UNSTABLE**
3927 ///
3928 /// This capability is not part of the spec yet, and may be removed or changed at any point.
3929 ///
3930 /// Whether the agent supports `session/fork`.
3931 #[cfg(feature = "unstable_session_fork")]
3932 #[serde_as(deserialize_as = "DefaultOnError")]
3933 #[schemars(extend("x-deserialize-default-on-error" = true))]
3934 #[serde(default)]
3935 pub fork: Option<SessionForkCapabilities>,
3936 /// Whether the agent supports `session/resume`.
3937 #[serde_as(deserialize_as = "DefaultOnError")]
3938 #[schemars(extend("x-deserialize-default-on-error" = true))]
3939 #[serde(default)]
3940 pub resume: Option<SessionResumeCapabilities>,
3941 /// Whether the agent supports `session/close`.
3942 #[serde_as(deserialize_as = "DefaultOnError")]
3943 #[schemars(extend("x-deserialize-default-on-error" = true))]
3944 #[serde(default)]
3945 pub close: Option<SessionCloseCapabilities>,
3946 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3947 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3948 /// these keys.
3949 ///
3950 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3951 #[serde(rename = "_meta")]
3952 pub meta: Option<Meta>,
3953}
3954
3955impl SessionCapabilities {
3956 /// Builds an empty [`SessionCapabilities`]; use builder methods to advertise supported sub-capabilities.
3957 #[must_use]
3958 pub fn new() -> Self {
3959 Self::default()
3960 }
3961
3962 /// Prompt capabilities supported by the agent in `session/prompt` requests.
3963 ///
3964 /// Omitted or `null` both mean the agent does not advertise any prompt
3965 /// extensions beyond the baseline text and resource-link content required by
3966 /// `session/prompt`.
3967 #[must_use]
3968 pub fn prompt(mut self, prompt: impl IntoOption<PromptCapabilities>) -> Self {
3969 self.prompt = prompt.into_option();
3970 self
3971 }
3972
3973 /// MCP capabilities supported by the agent for session lifecycle requests.
3974 ///
3975 /// Omitted or `null` both mean the agent does not advertise MCP server
3976 /// transport support for sessions.
3977 #[must_use]
3978 pub fn mcp(mut self, mcp: impl IntoOption<McpCapabilities>) -> Self {
3979 self.mcp = mcp.into_option();
3980 self
3981 }
3982
3983 /// Whether the agent supports `session/load`.
3984 ///
3985 /// Omitted or `null` both mean the agent does not advertise support.
3986 /// Supplying `{}` means the agent supports loading sessions.
3987 #[must_use]
3988 pub fn load(mut self, load: impl IntoOption<SessionLoadCapabilities>) -> Self {
3989 self.load = load.into_option();
3990 self
3991 }
3992
3993 /// Whether the agent supports `session/list`.
3994 #[must_use]
3995 pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
3996 self.list = list.into_option();
3997 self
3998 }
3999
4000 /// Whether the agent supports `session/delete`.
4001 ///
4002 /// Omitted or `null` both mean the agent does not advertise support.
4003 /// Supplying `{}` means the agent supports deleting sessions from `session/list`.
4004 #[must_use]
4005 pub fn delete(mut self, delete: impl IntoOption<SessionDeleteCapabilities>) -> Self {
4006 self.delete = delete.into_option();
4007 self
4008 }
4009
4010 /// Whether the agent supports `additionalDirectories` on supported session lifecycle requests.
4011 ///
4012 /// Agents that also support `session/list` may return
4013 /// `SessionInfo.additionalDirectories` to report the complete ordered
4014 /// additional-root list associated with a listed session.
4015 #[must_use]
4016 pub fn additional_directories(
4017 mut self,
4018 additional_directories: impl IntoOption<SessionAdditionalDirectoriesCapabilities>,
4019 ) -> Self {
4020 self.additional_directories = additional_directories.into_option();
4021 self
4022 }
4023
4024 #[cfg(feature = "unstable_session_fork")]
4025 /// Whether the agent supports `session/fork`.
4026 #[must_use]
4027 pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
4028 self.fork = fork.into_option();
4029 self
4030 }
4031
4032 /// Whether the agent supports `session/resume`.
4033 #[must_use]
4034 pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
4035 self.resume = resume.into_option();
4036 self
4037 }
4038
4039 /// Whether the agent supports `session/close`.
4040 #[must_use]
4041 pub fn close(mut self, close: impl IntoOption<SessionCloseCapabilities>) -> Self {
4042 self.close = close.into_option();
4043 self
4044 }
4045
4046 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4047 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4048 /// these keys.
4049 ///
4050 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4051 #[must_use]
4052 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4053 self.meta = meta.into_option();
4054 self
4055 }
4056}
4057
4058/// Capabilities for the `session/load` method.
4059///
4060/// Supplying `{}` means the agent supports loading sessions.
4061#[skip_serializing_none]
4062#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4063#[non_exhaustive]
4064pub struct SessionLoadCapabilities {
4065 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4066 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4067 /// these keys.
4068 ///
4069 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4070 #[serde(rename = "_meta")]
4071 pub meta: Option<Meta>,
4072}
4073
4074impl SessionLoadCapabilities {
4075 /// Builds an empty [`SessionLoadCapabilities`]; use builder methods to advertise supported sub-capabilities.
4076 #[must_use]
4077 pub fn new() -> Self {
4078 Self::default()
4079 }
4080
4081 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4082 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4083 /// these keys.
4084 ///
4085 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4086 #[must_use]
4087 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4088 self.meta = meta.into_option();
4089 self
4090 }
4091}
4092
4093/// Capabilities for the `session/list` method.
4094///
4095/// By supplying `{}` it means that the agent supports listing of sessions.
4096#[skip_serializing_none]
4097#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4098#[non_exhaustive]
4099pub struct SessionListCapabilities {
4100 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4101 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4102 /// these keys.
4103 ///
4104 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4105 #[serde(rename = "_meta")]
4106 pub meta: Option<Meta>,
4107}
4108
4109impl SessionListCapabilities {
4110 /// Builds an empty [`SessionListCapabilities`]; use builder methods to advertise supported sub-capabilities.
4111 #[must_use]
4112 pub fn new() -> Self {
4113 Self::default()
4114 }
4115
4116 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4117 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4118 /// these keys.
4119 ///
4120 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4121 #[must_use]
4122 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4123 self.meta = meta.into_option();
4124 self
4125 }
4126}
4127
4128/// Capabilities for the `session/delete` method.
4129///
4130/// Supplying `{}` means the agent supports deleting sessions from `session/list`.
4131#[skip_serializing_none]
4132#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4133#[non_exhaustive]
4134pub struct SessionDeleteCapabilities {
4135 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4136 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4137 /// these keys.
4138 ///
4139 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4140 #[serde(rename = "_meta")]
4141 pub meta: Option<Meta>,
4142}
4143
4144impl SessionDeleteCapabilities {
4145 /// Builds an empty [`SessionDeleteCapabilities`]; use builder methods to advertise supported sub-capabilities.
4146 #[must_use]
4147 pub fn new() -> Self {
4148 Self::default()
4149 }
4150
4151 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4152 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4153 /// these keys.
4154 ///
4155 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4156 #[must_use]
4157 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4158 self.meta = meta.into_option();
4159 self
4160 }
4161}
4162
4163/// Capabilities for additional session directories support.
4164///
4165/// By supplying `{}` it means that the agent supports the `additionalDirectories`
4166/// field on supported session lifecycle requests. Agents that also support
4167/// `session/list` may return `SessionInfo.additionalDirectories` to report the
4168/// complete ordered additional-root list associated with a listed session.
4169#[skip_serializing_none]
4170#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4171#[non_exhaustive]
4172pub struct SessionAdditionalDirectoriesCapabilities {
4173 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4174 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4175 /// these keys.
4176 ///
4177 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4178 #[serde(rename = "_meta")]
4179 pub meta: Option<Meta>,
4180}
4181
4182impl SessionAdditionalDirectoriesCapabilities {
4183 /// Builds an empty [`SessionAdditionalDirectoriesCapabilities`]; use builder methods to advertise supported sub-capabilities.
4184 #[must_use]
4185 pub fn new() -> Self {
4186 Self::default()
4187 }
4188
4189 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4190 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4191 /// these keys.
4192 ///
4193 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4194 #[must_use]
4195 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4196 self.meta = meta.into_option();
4197 self
4198 }
4199}
4200
4201/// **UNSTABLE**
4202///
4203/// This capability is not part of the spec yet, and may be removed or changed at any point.
4204///
4205/// Capabilities for the `session/fork` method.
4206///
4207/// By supplying `{}` it means that the agent supports forking of sessions.
4208#[cfg(feature = "unstable_session_fork")]
4209#[skip_serializing_none]
4210#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4211#[non_exhaustive]
4212pub struct SessionForkCapabilities {
4213 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4214 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4215 /// these keys.
4216 ///
4217 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4218 #[serde(rename = "_meta")]
4219 pub meta: Option<Meta>,
4220}
4221
4222#[cfg(feature = "unstable_session_fork")]
4223impl SessionForkCapabilities {
4224 /// Builds an empty [`SessionForkCapabilities`]; use builder methods to advertise supported sub-capabilities.
4225 #[must_use]
4226 pub fn new() -> Self {
4227 Self::default()
4228 }
4229
4230 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4231 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4232 /// these keys.
4233 ///
4234 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4235 #[must_use]
4236 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4237 self.meta = meta.into_option();
4238 self
4239 }
4240}
4241
4242/// Capabilities for the `session/resume` method.
4243///
4244/// By supplying `{}` it means that the agent supports resuming of sessions.
4245#[skip_serializing_none]
4246#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4247#[non_exhaustive]
4248pub struct SessionResumeCapabilities {
4249 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4250 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4251 /// these keys.
4252 ///
4253 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4254 #[serde(rename = "_meta")]
4255 pub meta: Option<Meta>,
4256}
4257
4258impl SessionResumeCapabilities {
4259 /// Builds an empty [`SessionResumeCapabilities`]; use builder methods to advertise supported sub-capabilities.
4260 #[must_use]
4261 pub fn new() -> Self {
4262 Self::default()
4263 }
4264
4265 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4266 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4267 /// these keys.
4268 ///
4269 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4270 #[must_use]
4271 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4272 self.meta = meta.into_option();
4273 self
4274 }
4275}
4276
4277/// Capabilities for the `session/close` method.
4278///
4279/// By supplying `{}` it means that the agent supports closing of sessions.
4280#[skip_serializing_none]
4281#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4282#[non_exhaustive]
4283pub struct SessionCloseCapabilities {
4284 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4285 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4286 /// these keys.
4287 ///
4288 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4289 #[serde(rename = "_meta")]
4290 pub meta: Option<Meta>,
4291}
4292
4293impl SessionCloseCapabilities {
4294 /// Builds an empty [`SessionCloseCapabilities`]; use builder methods to advertise supported sub-capabilities.
4295 #[must_use]
4296 pub fn new() -> Self {
4297 Self::default()
4298 }
4299
4300 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4301 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4302 /// these keys.
4303 ///
4304 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4305 #[must_use]
4306 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4307 self.meta = meta.into_option();
4308 self
4309 }
4310}
4311
4312/// Prompt capabilities supported by the agent in `session/prompt` requests.
4313///
4314/// Baseline agent functionality requires support for [`ContentBlock::Text`]
4315/// and [`ContentBlock::ResourceLink`] in prompt requests.
4316///
4317/// Other variants must be explicitly opted in to.
4318/// Capabilities for different types of content in prompt requests.
4319///
4320/// Indicates which content types beyond the baseline (text and resource links)
4321/// the agent can process.
4322///
4323/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
4324#[serde_as]
4325#[skip_serializing_none]
4326#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4327#[serde(rename_all = "camelCase")]
4328#[non_exhaustive]
4329pub struct PromptCapabilities {
4330 /// Agent supports [`ContentBlock::Image`].
4331 ///
4332 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4333 /// Supplying `{}` means the agent supports image content in prompts.
4334 #[serde_as(deserialize_as = "DefaultOnError")]
4335 #[schemars(extend("x-deserialize-default-on-error" = true))]
4336 #[serde(default)]
4337 pub image: Option<PromptImageCapabilities>,
4338 /// Agent supports [`ContentBlock::Audio`].
4339 ///
4340 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4341 /// Supplying `{}` means the agent supports audio content in prompts.
4342 #[serde_as(deserialize_as = "DefaultOnError")]
4343 #[schemars(extend("x-deserialize-default-on-error" = true))]
4344 #[serde(default)]
4345 pub audio: Option<PromptAudioCapabilities>,
4346 /// Agent supports embedded context in `session/prompt` requests.
4347 ///
4348 /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
4349 /// in prompt requests for pieces of context that are referenced in the message.
4350 ///
4351 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4352 /// Supplying `{}` means the agent supports embedded context in prompts.
4353 #[serde_as(deserialize_as = "DefaultOnError")]
4354 #[schemars(extend("x-deserialize-default-on-error" = true))]
4355 #[serde(default)]
4356 pub embedded_context: Option<PromptEmbeddedContextCapabilities>,
4357 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4358 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4359 /// these keys.
4360 ///
4361 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4362 #[serde(rename = "_meta")]
4363 pub meta: Option<Meta>,
4364}
4365
4366impl PromptCapabilities {
4367 /// Builds an empty [`PromptCapabilities`]; use builder methods to advertise supported sub-capabilities.
4368 #[must_use]
4369 pub fn new() -> Self {
4370 Self::default()
4371 }
4372
4373 /// Agent supports [`ContentBlock::Image`].
4374 ///
4375 /// Omitted or `null` both mean the agent does not advertise support.
4376 /// Supplying `{}` means the agent supports image content in prompts.
4377 #[must_use]
4378 pub fn image(mut self, image: impl IntoOption<PromptImageCapabilities>) -> Self {
4379 self.image = image.into_option();
4380 self
4381 }
4382
4383 /// Agent supports [`ContentBlock::Audio`].
4384 ///
4385 /// Omitted or `null` both mean the agent does not advertise support.
4386 /// Supplying `{}` means the agent supports audio content in prompts.
4387 #[must_use]
4388 pub fn audio(mut self, audio: impl IntoOption<PromptAudioCapabilities>) -> Self {
4389 self.audio = audio.into_option();
4390 self
4391 }
4392
4393 /// Agent supports embedded context in `session/prompt` requests.
4394 ///
4395 /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
4396 /// in prompt requests for pieces of context that are referenced in the message.
4397 ///
4398 /// Omitted or `null` both mean the agent does not advertise support.
4399 /// Supplying `{}` means the agent supports embedded context in prompts.
4400 #[must_use]
4401 pub fn embedded_context(
4402 mut self,
4403 embedded_context: impl IntoOption<PromptEmbeddedContextCapabilities>,
4404 ) -> Self {
4405 self.embedded_context = embedded_context.into_option();
4406 self
4407 }
4408
4409 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4410 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4411 /// these keys.
4412 ///
4413 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4414 #[must_use]
4415 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4416 self.meta = meta.into_option();
4417 self
4418 }
4419}
4420
4421/// Capabilities for image content in prompt requests.
4422///
4423/// Supplying `{}` means the agent supports image content in prompts.
4424#[skip_serializing_none]
4425#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4426#[non_exhaustive]
4427pub struct PromptImageCapabilities {
4428 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4429 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4430 /// these keys.
4431 ///
4432 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4433 #[serde(rename = "_meta")]
4434 pub meta: Option<Meta>,
4435}
4436
4437impl PromptImageCapabilities {
4438 /// Builds an empty [`PromptImageCapabilities`]; use builder methods to advertise supported sub-capabilities.
4439 #[must_use]
4440 pub fn new() -> Self {
4441 Self::default()
4442 }
4443
4444 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4445 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4446 /// these keys.
4447 ///
4448 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4449 #[must_use]
4450 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4451 self.meta = meta.into_option();
4452 self
4453 }
4454}
4455
4456/// Capabilities for audio content in prompt requests.
4457///
4458/// Supplying `{}` means the agent supports audio content in prompts.
4459#[skip_serializing_none]
4460#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4461#[non_exhaustive]
4462pub struct PromptAudioCapabilities {
4463 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4464 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4465 /// these keys.
4466 ///
4467 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4468 #[serde(rename = "_meta")]
4469 pub meta: Option<Meta>,
4470}
4471
4472impl PromptAudioCapabilities {
4473 /// Builds an empty [`PromptAudioCapabilities`]; use builder methods to advertise supported sub-capabilities.
4474 #[must_use]
4475 pub fn new() -> Self {
4476 Self::default()
4477 }
4478
4479 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4480 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4481 /// these keys.
4482 ///
4483 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4484 #[must_use]
4485 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4486 self.meta = meta.into_option();
4487 self
4488 }
4489}
4490
4491/// Capabilities for embedded context in prompt requests.
4492///
4493/// Supplying `{}` means the agent supports embedded context in prompts.
4494#[skip_serializing_none]
4495#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4496#[non_exhaustive]
4497pub struct PromptEmbeddedContextCapabilities {
4498 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4499 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4500 /// these keys.
4501 ///
4502 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4503 #[serde(rename = "_meta")]
4504 pub meta: Option<Meta>,
4505}
4506
4507impl PromptEmbeddedContextCapabilities {
4508 /// Builds an empty [`PromptEmbeddedContextCapabilities`]; use builder methods to advertise supported sub-capabilities.
4509 #[must_use]
4510 pub fn new() -> Self {
4511 Self::default()
4512 }
4513
4514 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4515 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4516 /// these keys.
4517 ///
4518 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4519 #[must_use]
4520 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4521 self.meta = meta.into_option();
4522 self
4523 }
4524}
4525
4526/// MCP capabilities supported by the agent for session lifecycle requests.
4527#[serde_as]
4528#[skip_serializing_none]
4529#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4530#[serde(rename_all = "camelCase")]
4531#[non_exhaustive]
4532pub struct McpCapabilities {
4533 /// Agent supports [`McpServer::Stdio`].
4534 ///
4535 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4536 /// Supplying `{}` means the agent supports stdio MCP server transports.
4537 #[serde_as(deserialize_as = "DefaultOnError")]
4538 #[schemars(extend("x-deserialize-default-on-error" = true))]
4539 #[serde(default)]
4540 pub stdio: Option<McpStdioCapabilities>,
4541 /// Agent supports [`McpServer::Http`].
4542 ///
4543 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4544 /// Supplying `{}` means the agent supports HTTP MCP server transports.
4545 #[serde_as(deserialize_as = "DefaultOnError")]
4546 #[schemars(extend("x-deserialize-default-on-error" = true))]
4547 #[serde(default)]
4548 pub http: Option<McpHttpCapabilities>,
4549 /// **UNSTABLE**
4550 ///
4551 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4552 ///
4553 /// Agent supports [`McpServer::Acp`].
4554 #[cfg(feature = "unstable_mcp_over_acp")]
4555 ///
4556 /// Optional. Omitted or `null` both mean the agent does not advertise support.
4557 /// Supplying `{}` means the agent supports ACP MCP server transports.
4558 #[serde_as(deserialize_as = "DefaultOnError")]
4559 #[schemars(extend("x-deserialize-default-on-error" = true))]
4560 #[serde(default)]
4561 pub acp: Option<McpAcpCapabilities>,
4562 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4563 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4564 /// these keys.
4565 ///
4566 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4567 #[serde(rename = "_meta")]
4568 pub meta: Option<Meta>,
4569}
4570
4571impl McpCapabilities {
4572 /// Builds an empty [`McpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4573 #[must_use]
4574 pub fn new() -> Self {
4575 Self::default()
4576 }
4577
4578 /// Agent supports [`McpServer::Stdio`].
4579 ///
4580 /// Omitted or `null` both mean the agent does not advertise support.
4581 /// Supplying `{}` means the agent supports stdio MCP server transports.
4582 #[must_use]
4583 pub fn stdio(mut self, stdio: impl IntoOption<McpStdioCapabilities>) -> Self {
4584 self.stdio = stdio.into_option();
4585 self
4586 }
4587
4588 /// Agent supports [`McpServer::Http`].
4589 ///
4590 /// Omitted or `null` both mean the agent does not advertise support.
4591 /// Supplying `{}` means the agent supports HTTP MCP server transports.
4592 #[must_use]
4593 pub fn http(mut self, http: impl IntoOption<McpHttpCapabilities>) -> Self {
4594 self.http = http.into_option();
4595 self
4596 }
4597
4598 /// **UNSTABLE**
4599 ///
4600 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4601 ///
4602 /// Agent supports [`McpServer::Acp`].
4603 #[cfg(feature = "unstable_mcp_over_acp")]
4604 ///
4605 /// Omitted or `null` both mean the agent does not advertise support.
4606 /// Supplying `{}` means the agent supports ACP MCP server transports.
4607 #[must_use]
4608 pub fn acp(mut self, acp: impl IntoOption<McpAcpCapabilities>) -> Self {
4609 self.acp = acp.into_option();
4610 self
4611 }
4612
4613 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4614 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4615 /// these keys.
4616 ///
4617 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4618 #[must_use]
4619 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4620 self.meta = meta.into_option();
4621 self
4622 }
4623}
4624
4625/// Capabilities for stdio MCP server transports.
4626///
4627/// Supplying `{}` means the agent supports stdio MCP server transports.
4628#[skip_serializing_none]
4629#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4630#[non_exhaustive]
4631pub struct McpStdioCapabilities {
4632 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4633 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4634 /// these keys.
4635 ///
4636 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4637 #[serde(rename = "_meta")]
4638 pub meta: Option<Meta>,
4639}
4640
4641impl McpStdioCapabilities {
4642 /// Builds an empty [`McpStdioCapabilities`]; use builder methods to advertise supported sub-capabilities.
4643 #[must_use]
4644 pub fn new() -> Self {
4645 Self::default()
4646 }
4647
4648 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4649 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4650 /// these keys.
4651 ///
4652 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4653 #[must_use]
4654 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4655 self.meta = meta.into_option();
4656 self
4657 }
4658}
4659
4660/// Capabilities for HTTP MCP server transports.
4661///
4662/// Supplying `{}` means the agent supports HTTP MCP server transports.
4663#[skip_serializing_none]
4664#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4665#[non_exhaustive]
4666pub struct McpHttpCapabilities {
4667 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4668 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4669 /// these keys.
4670 ///
4671 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4672 #[serde(rename = "_meta")]
4673 pub meta: Option<Meta>,
4674}
4675
4676impl McpHttpCapabilities {
4677 /// Builds an empty [`McpHttpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4678 #[must_use]
4679 pub fn new() -> Self {
4680 Self::default()
4681 }
4682
4683 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4684 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4685 /// these keys.
4686 ///
4687 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4688 #[must_use]
4689 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4690 self.meta = meta.into_option();
4691 self
4692 }
4693}
4694
4695/// **UNSTABLE**
4696///
4697/// This capability is not part of the spec yet, and may be removed or changed at any point.
4698///
4699/// Capabilities for ACP MCP server transports.
4700///
4701/// Supplying `{}` means the agent supports ACP MCP server transports.
4702#[cfg(feature = "unstable_mcp_over_acp")]
4703#[skip_serializing_none]
4704#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
4705#[non_exhaustive]
4706pub struct McpAcpCapabilities {
4707 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4708 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4709 /// these keys.
4710 ///
4711 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4712 #[serde(rename = "_meta")]
4713 pub meta: Option<Meta>,
4714}
4715
4716#[cfg(feature = "unstable_mcp_over_acp")]
4717impl McpAcpCapabilities {
4718 /// Builds an empty [`McpAcpCapabilities`]; use builder methods to advertise supported sub-capabilities.
4719 #[must_use]
4720 pub fn new() -> Self {
4721 Self::default()
4722 }
4723
4724 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
4725 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
4726 /// these keys.
4727 ///
4728 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
4729 #[must_use]
4730 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
4731 self.meta = meta.into_option();
4732 self
4733 }
4734}
4735
4736// Method schema
4737
4738/// Names of all methods that agents handle.
4739///
4740/// Provides a centralized definition of method names used in the protocol.
4741#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
4742#[non_exhaustive]
4743pub struct AgentMethodNames {
4744 /// Method for initializing the connection.
4745 pub initialize: &'static str,
4746 /// Method for authenticating with the agent.
4747 pub authenticate: &'static str,
4748 /// Method for listing configurable providers.
4749 #[cfg(feature = "unstable_llm_providers")]
4750 pub providers_list: &'static str,
4751 /// Method for setting provider configuration.
4752 #[cfg(feature = "unstable_llm_providers")]
4753 pub providers_set: &'static str,
4754 /// Method for disabling a provider.
4755 #[cfg(feature = "unstable_llm_providers")]
4756 pub providers_disable: &'static str,
4757 /// Method for creating a new session.
4758 pub session_new: &'static str,
4759 /// Method for loading an existing session.
4760 pub session_load: &'static str,
4761 /// Method for setting a configuration option for a session.
4762 pub session_set_config_option: &'static str,
4763 /// Method for sending a prompt to the agent.
4764 pub session_prompt: &'static str,
4765 /// Notification for cancelling operations.
4766 pub session_cancel: &'static str,
4767 /// Method for exchanging MCP-over-ACP messages.
4768 #[cfg(feature = "unstable_mcp_over_acp")]
4769 pub mcp_message: &'static str,
4770 /// Method for listing existing sessions.
4771 pub session_list: &'static str,
4772 /// Method for deleting an existing session.
4773 pub session_delete: &'static str,
4774 /// Method for forking an existing session.
4775 #[cfg(feature = "unstable_session_fork")]
4776 pub session_fork: &'static str,
4777 /// Method for resuming an existing session.
4778 pub session_resume: &'static str,
4779 /// Method for closing an active session.
4780 pub session_close: &'static str,
4781 /// Method for logging out of an authenticated session.
4782 pub logout: &'static str,
4783 /// Method for starting an NES session.
4784 #[cfg(feature = "unstable_nes")]
4785 pub nes_start: &'static str,
4786 /// Method for requesting a suggestion.
4787 #[cfg(feature = "unstable_nes")]
4788 pub nes_suggest: &'static str,
4789 /// Notification for accepting a suggestion.
4790 #[cfg(feature = "unstable_nes")]
4791 pub nes_accept: &'static str,
4792 /// Notification for rejecting a suggestion.
4793 #[cfg(feature = "unstable_nes")]
4794 pub nes_reject: &'static str,
4795 /// Method for closing an NES session.
4796 #[cfg(feature = "unstable_nes")]
4797 pub nes_close: &'static str,
4798 /// Notification for document open events.
4799 #[cfg(feature = "unstable_nes")]
4800 pub document_did_open: &'static str,
4801 /// Notification for document change events.
4802 #[cfg(feature = "unstable_nes")]
4803 pub document_did_change: &'static str,
4804 /// Notification for document close events.
4805 #[cfg(feature = "unstable_nes")]
4806 pub document_did_close: &'static str,
4807 /// Notification for document save events.
4808 #[cfg(feature = "unstable_nes")]
4809 pub document_did_save: &'static str,
4810 /// Notification for document focus events.
4811 #[cfg(feature = "unstable_nes")]
4812 pub document_did_focus: &'static str,
4813}
4814
4815/// Constant containing all agent method names.
4816pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
4817 initialize: INITIALIZE_METHOD_NAME,
4818 authenticate: AUTHENTICATE_METHOD_NAME,
4819 #[cfg(feature = "unstable_llm_providers")]
4820 providers_list: PROVIDERS_LIST_METHOD_NAME,
4821 #[cfg(feature = "unstable_llm_providers")]
4822 providers_set: PROVIDERS_SET_METHOD_NAME,
4823 #[cfg(feature = "unstable_llm_providers")]
4824 providers_disable: PROVIDERS_DISABLE_METHOD_NAME,
4825 session_new: SESSION_NEW_METHOD_NAME,
4826 session_load: SESSION_LOAD_METHOD_NAME,
4827 session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
4828 session_prompt: SESSION_PROMPT_METHOD_NAME,
4829 session_cancel: SESSION_CANCEL_METHOD_NAME,
4830 #[cfg(feature = "unstable_mcp_over_acp")]
4831 mcp_message: MCP_MESSAGE_METHOD_NAME,
4832 session_list: SESSION_LIST_METHOD_NAME,
4833 session_delete: SESSION_DELETE_METHOD_NAME,
4834 #[cfg(feature = "unstable_session_fork")]
4835 session_fork: SESSION_FORK_METHOD_NAME,
4836 session_resume: SESSION_RESUME_METHOD_NAME,
4837 session_close: SESSION_CLOSE_METHOD_NAME,
4838 logout: LOGOUT_METHOD_NAME,
4839 #[cfg(feature = "unstable_nes")]
4840 nes_start: NES_START_METHOD_NAME,
4841 #[cfg(feature = "unstable_nes")]
4842 nes_suggest: NES_SUGGEST_METHOD_NAME,
4843 #[cfg(feature = "unstable_nes")]
4844 nes_accept: NES_ACCEPT_METHOD_NAME,
4845 #[cfg(feature = "unstable_nes")]
4846 nes_reject: NES_REJECT_METHOD_NAME,
4847 #[cfg(feature = "unstable_nes")]
4848 nes_close: NES_CLOSE_METHOD_NAME,
4849 #[cfg(feature = "unstable_nes")]
4850 document_did_open: DOCUMENT_DID_OPEN_METHOD_NAME,
4851 #[cfg(feature = "unstable_nes")]
4852 document_did_change: DOCUMENT_DID_CHANGE_METHOD_NAME,
4853 #[cfg(feature = "unstable_nes")]
4854 document_did_close: DOCUMENT_DID_CLOSE_METHOD_NAME,
4855 #[cfg(feature = "unstable_nes")]
4856 document_did_save: DOCUMENT_DID_SAVE_METHOD_NAME,
4857 #[cfg(feature = "unstable_nes")]
4858 document_did_focus: DOCUMENT_DID_FOCUS_METHOD_NAME,
4859};
4860
4861/// Method name for the initialize request.
4862pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
4863/// Method name for the authenticate request.
4864pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
4865/// Method name for listing configurable providers.
4866#[cfg(feature = "unstable_llm_providers")]
4867pub(crate) const PROVIDERS_LIST_METHOD_NAME: &str = "providers/list";
4868/// Method name for setting provider configuration.
4869#[cfg(feature = "unstable_llm_providers")]
4870pub(crate) const PROVIDERS_SET_METHOD_NAME: &str = "providers/set";
4871/// Method name for disabling a provider.
4872#[cfg(feature = "unstable_llm_providers")]
4873pub(crate) const PROVIDERS_DISABLE_METHOD_NAME: &str = "providers/disable";
4874/// Method name for creating a new session.
4875pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
4876/// Method name for loading an existing session.
4877pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
4878/// Method name for setting a configuration option for a session.
4879pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
4880/// Method name for sending a prompt.
4881pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
4882/// Method name for the cancel notification.
4883pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
4884/// Method name for listing existing sessions.
4885pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
4886/// Method name for deleting an existing session.
4887pub(crate) const SESSION_DELETE_METHOD_NAME: &str = "session/delete";
4888/// Method name for forking an existing session.
4889#[cfg(feature = "unstable_session_fork")]
4890pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
4891/// Method name for resuming an existing session.
4892pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
4893/// Method name for closing an active session.
4894pub(crate) const SESSION_CLOSE_METHOD_NAME: &str = "session/close";
4895/// Method name for logging out of an authenticated session.
4896pub(crate) const LOGOUT_METHOD_NAME: &str = "logout";
4897
4898/// All possible requests that a client can send to an agent.
4899///
4900/// This enum is used internally for routing RPC requests. You typically won't need
4901/// to use this directly.
4902///
4903/// This enum encompasses all method calls from client to agent.
4904#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
4905#[serde(untagged)]
4906#[schemars(inline)]
4907#[non_exhaustive]
4908pub enum ClientRequest {
4909 /// Establishes the connection with a client and negotiates protocol capabilities.
4910 ///
4911 /// This method is called once at the beginning of the connection to:
4912 /// - Negotiate the protocol version to use
4913 /// - Exchange capability information between client and agent
4914 /// - Determine available authentication methods
4915 ///
4916 /// The agent should respond with its supported protocol version and capabilities.
4917 ///
4918 /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
4919 InitializeRequest(Box<InitializeRequest>),
4920 /// Authenticates the client using the specified authentication method.
4921 ///
4922 /// Called when the agent requires authentication before allowing session creation.
4923 /// The client provides the authentication method ID that was advertised during initialization.
4924 ///
4925 /// After successful authentication, the client can proceed to create sessions with
4926 /// `new_session` without receiving an `auth_required` error.
4927 ///
4928 /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
4929 AuthenticateRequest(AuthenticateRequest),
4930 /// **UNSTABLE**
4931 ///
4932 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4933 ///
4934 /// Lists providers that can be configured by the client.
4935 #[cfg(feature = "unstable_llm_providers")]
4936 ListProvidersRequest(ListProvidersRequest),
4937 /// **UNSTABLE**
4938 ///
4939 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4940 ///
4941 /// Replaces the configuration for a provider.
4942 #[cfg(feature = "unstable_llm_providers")]
4943 SetProviderRequest(Box<SetProviderRequest>),
4944 /// **UNSTABLE**
4945 ///
4946 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4947 ///
4948 /// Disables a provider.
4949 #[cfg(feature = "unstable_llm_providers")]
4950 DisableProviderRequest(DisableProviderRequest),
4951 /// Logs out of the current authenticated state.
4952 ///
4953 /// After a successful logout, all new sessions will require authentication.
4954 /// There is no guarantee about the behavior of already running sessions.
4955 LogoutRequest(LogoutRequest),
4956 /// Creates a new conversation session with the agent.
4957 ///
4958 /// Sessions represent independent conversation contexts with their own history and state.
4959 ///
4960 /// The agent should:
4961 /// - Create a new session context
4962 /// - Connect to any specified MCP servers
4963 /// - Return a unique session ID for future requests
4964 ///
4965 /// May return an `auth_required` error if the agent requires authentication.
4966 ///
4967 /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
4968 NewSessionRequest(NewSessionRequest),
4969 /// Loads an existing session to resume a previous conversation.
4970 ///
4971 /// This method is only available if the agent advertises the `session.load` capability.
4972 ///
4973 /// The agent should:
4974 /// - Restore the session context and conversation history
4975 /// - Connect to the specified MCP servers
4976 /// - Stream the entire conversation history back to the client via notifications
4977 ///
4978 /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
4979 LoadSessionRequest(LoadSessionRequest),
4980 /// Lists existing sessions known to the agent.
4981 ///
4982 /// This method is only available if the agent advertises the `session.list` capability.
4983 ///
4984 /// The agent should return metadata about sessions with optional filtering and pagination support.
4985 ListSessionsRequest(ListSessionsRequest),
4986 /// Deletes an existing session from `session/list`.
4987 ///
4988 /// This method is only available if the agent advertises the `session.delete` capability.
4989 DeleteSessionRequest(DeleteSessionRequest),
4990 #[cfg(feature = "unstable_session_fork")]
4991 /// **UNSTABLE**
4992 ///
4993 /// This capability is not part of the spec yet, and may be removed or changed at any point.
4994 ///
4995 /// Forks an existing session to create a new independent session.
4996 ///
4997 /// This method is only available if the agent advertises the `session.fork` capability.
4998 ///
4999 /// The agent should create a new session with the same conversation context as the
5000 /// original, allowing operations like generating summaries without affecting the
5001 /// original session's history.
5002 ForkSessionRequest(ForkSessionRequest),
5003 /// Resumes an existing session without returning previous messages.
5004 ///
5005 /// This method is only available if the agent advertises the `session.resume` capability.
5006 ///
5007 /// The agent should resume the session context, allowing the conversation to continue
5008 /// without replaying the message history (unlike `session/load`).
5009 ResumeSessionRequest(ResumeSessionRequest),
5010 /// Closes an active session and frees up any resources associated with it.
5011 ///
5012 /// This method is only available if the agent advertises the `session.close` capability.
5013 ///
5014 /// The agent must cancel any ongoing work (as if `session/cancel` was called)
5015 /// and then free up any resources associated with the session.
5016 CloseSessionRequest(CloseSessionRequest),
5017 /// Sets the current value for a session configuration option.
5018 SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
5019 /// Processes a user prompt within a session.
5020 ///
5021 /// This request accepts the prompt:
5022 /// - Receives user messages with optional context (files, images, etc.)
5023 /// - Returns once the prompt is accepted
5024 ///
5025 /// After acceptance, the Agent reports the accepted user message,
5026 /// processing state, output, tool calls, and completion through
5027 /// `session/update` notifications.
5028 ///
5029 /// See protocol docs: [Prompt Lifecycle](https://agentclientprotocol.com/protocol/prompt-lifecycle)
5030 PromptRequest(PromptRequest),
5031 #[cfg(feature = "unstable_nes")]
5032 /// **UNSTABLE**
5033 ///
5034 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5035 ///
5036 /// Starts an NES session.
5037 StartNesRequest(Box<StartNesRequest>),
5038 #[cfg(feature = "unstable_nes")]
5039 /// **UNSTABLE**
5040 ///
5041 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5042 ///
5043 /// Requests a code suggestion.
5044 SuggestNesRequest(Box<SuggestNesRequest>),
5045 #[cfg(feature = "unstable_nes")]
5046 /// **UNSTABLE**
5047 ///
5048 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5049 ///
5050 /// Closes an active NES session and frees up any resources associated with it.
5051 ///
5052 /// The agent must cancel any ongoing work and then free up any resources
5053 /// associated with the NES session.
5054 CloseNesRequest(CloseNesRequest),
5055 /// **UNSTABLE**
5056 ///
5057 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5058 ///
5059 /// Exchanges an MCP-over-ACP message.
5060 #[cfg(feature = "unstable_mcp_over_acp")]
5061 MessageMcpRequest(MessageMcpRequest),
5062 /// Handles extension method requests from the client.
5063 ///
5064 /// Extension methods provide a way to add custom functionality while maintaining
5065 /// protocol compatibility.
5066 ///
5067 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5068 ExtMethodRequest(ExtRequest),
5069}
5070
5071impl ClientRequest {
5072 /// Returns the corresponding method name of the request.
5073 #[must_use]
5074 pub fn method(&self) -> &str {
5075 match self {
5076 Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
5077 Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
5078 #[cfg(feature = "unstable_llm_providers")]
5079 Self::ListProvidersRequest(_) => AGENT_METHOD_NAMES.providers_list,
5080 #[cfg(feature = "unstable_llm_providers")]
5081 Self::SetProviderRequest(_) => AGENT_METHOD_NAMES.providers_set,
5082 #[cfg(feature = "unstable_llm_providers")]
5083 Self::DisableProviderRequest(_) => AGENT_METHOD_NAMES.providers_disable,
5084 Self::LogoutRequest(_) => AGENT_METHOD_NAMES.logout,
5085 Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
5086 Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
5087 Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
5088 Self::DeleteSessionRequest(_) => AGENT_METHOD_NAMES.session_delete,
5089 #[cfg(feature = "unstable_session_fork")]
5090 Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
5091 Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
5092 Self::CloseSessionRequest(_) => AGENT_METHOD_NAMES.session_close,
5093 Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
5094 Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
5095 #[cfg(feature = "unstable_nes")]
5096 Self::StartNesRequest(_) => AGENT_METHOD_NAMES.nes_start,
5097 #[cfg(feature = "unstable_nes")]
5098 Self::SuggestNesRequest(_) => AGENT_METHOD_NAMES.nes_suggest,
5099 #[cfg(feature = "unstable_nes")]
5100 Self::CloseNesRequest(_) => AGENT_METHOD_NAMES.nes_close,
5101 #[cfg(feature = "unstable_mcp_over_acp")]
5102 Self::MessageMcpRequest(_) => AGENT_METHOD_NAMES.mcp_message,
5103 Self::ExtMethodRequest(ext_request) => &ext_request.method,
5104 }
5105 }
5106}
5107
5108/// All possible responses that an agent can send to a client.
5109///
5110/// This enum is used internally for routing RPC responses. You typically won't need
5111/// to use this directly - the responses are handled automatically by the connection.
5112///
5113/// These are responses to the corresponding `ClientRequest` variants.
5114#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5115#[serde(untagged)]
5116#[schemars(inline)]
5117#[non_exhaustive]
5118pub enum AgentResponse {
5119 /// Successful result returned for a `initialize` request.
5120 InitializeResponse(Box<InitializeResponse>),
5121 /// Successful result returned for a `authenticate` request.
5122 AuthenticateResponse(#[serde(default)] AuthenticateResponse),
5123 /// Successful result returned for a `providers/list` request.
5124 #[cfg(feature = "unstable_llm_providers")]
5125 ListProvidersResponse(ListProvidersResponse),
5126 /// Successful result returned for a `providers/set` request.
5127 #[cfg(feature = "unstable_llm_providers")]
5128 SetProviderResponse(#[serde(default)] SetProviderResponse),
5129 /// Successful result returned for a `providers/disable` request.
5130 #[cfg(feature = "unstable_llm_providers")]
5131 DisableProviderResponse(#[serde(default)] DisableProviderResponse),
5132 /// Successful result returned for a `logout` request.
5133 LogoutResponse(#[serde(default)] LogoutResponse),
5134 /// Successful result returned for a `session/new` request.
5135 NewSessionResponse(NewSessionResponse),
5136 /// Successful result returned for a `session/load` request.
5137 LoadSessionResponse(#[serde(default)] LoadSessionResponse),
5138 /// Successful result returned for a `session/list` request.
5139 ListSessionsResponse(ListSessionsResponse),
5140 /// Successful result returned for a `session/delete` request.
5141 DeleteSessionResponse(#[serde(default)] DeleteSessionResponse),
5142 /// Successful result returned for a `session/fork` request.
5143 #[cfg(feature = "unstable_session_fork")]
5144 ForkSessionResponse(ForkSessionResponse),
5145 /// Successful result returned for a `session/resume` request.
5146 ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
5147 /// Successful result returned for a `session/close` request.
5148 CloseSessionResponse(#[serde(default)] CloseSessionResponse),
5149 /// Successful result returned for a `session/set_config_option` request.
5150 SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
5151 /// Successful result returned for a `session/prompt` request.
5152 PromptResponse(PromptResponse),
5153 /// Successful result returned for a `nes/start` request.
5154 #[cfg(feature = "unstable_nes")]
5155 StartNesResponse(StartNesResponse),
5156 /// Successful result returned for a `nes/suggest` request.
5157 #[cfg(feature = "unstable_nes")]
5158 SuggestNesResponse(SuggestNesResponse),
5159 /// Successful result returned for a `nes/close` request.
5160 #[cfg(feature = "unstable_nes")]
5161 CloseNesResponse(#[serde(default)] CloseNesResponse),
5162 /// Successful result returned by an extension method outside the core ACP method set.
5163 ExtMethodResponse(ExtResponse),
5164 /// Successful result returned by an MCP-over-ACP `mcp/message` request.
5165 #[cfg(feature = "unstable_mcp_over_acp")]
5166 MessageMcpResponse(MessageMcpResponse),
5167}
5168
5169/// All possible notifications that a client can send to an agent.
5170///
5171/// This enum is used internally for routing RPC notifications. You typically won't need
5172/// to use this directly.
5173///
5174/// Notifications do not expect a response.
5175#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
5176#[serde(untagged)]
5177#[schemars(inline)]
5178#[non_exhaustive]
5179pub enum ClientNotification {
5180 /// Cancels ongoing operations for a session.
5181 ///
5182 /// This is a notification sent by the client to cancel active work in a
5183 /// session.
5184 ///
5185 /// Upon receiving this notification, the Agent SHOULD:
5186 /// - Stop all language model requests as soon as possible
5187 /// - Abort all tool call invocations in progress
5188 /// - Send any pending `session/update` notifications
5189 /// - Report an idle `state_update` with `StopReason::Cancelled` after
5190 /// cancellation succeeds
5191 ///
5192 /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-lifecycle#cancellation)
5193 CancelNotification(CancelNotification),
5194 #[cfg(feature = "unstable_nes")]
5195 /// **UNSTABLE**
5196 ///
5197 /// Notification sent when a file is opened in the editor.
5198 DidOpenDocumentNotification(DidOpenDocumentNotification),
5199 #[cfg(feature = "unstable_nes")]
5200 /// **UNSTABLE**
5201 ///
5202 /// Notification sent when a file is edited.
5203 DidChangeDocumentNotification(DidChangeDocumentNotification),
5204 #[cfg(feature = "unstable_nes")]
5205 /// **UNSTABLE**
5206 ///
5207 /// Notification sent when a file is closed.
5208 DidCloseDocumentNotification(DidCloseDocumentNotification),
5209 #[cfg(feature = "unstable_nes")]
5210 /// **UNSTABLE**
5211 ///
5212 /// Notification sent when a file is saved.
5213 DidSaveDocumentNotification(DidSaveDocumentNotification),
5214 #[cfg(feature = "unstable_nes")]
5215 /// **UNSTABLE**
5216 ///
5217 /// Notification sent when a file becomes the active editor tab.
5218 DidFocusDocumentNotification(Box<DidFocusDocumentNotification>),
5219 #[cfg(feature = "unstable_nes")]
5220 /// **UNSTABLE**
5221 ///
5222 /// Notification sent when a suggestion is accepted.
5223 AcceptNesNotification(AcceptNesNotification),
5224 #[cfg(feature = "unstable_nes")]
5225 /// **UNSTABLE**
5226 ///
5227 /// Notification sent when a suggestion is rejected.
5228 RejectNesNotification(RejectNesNotification),
5229 /// **UNSTABLE**
5230 ///
5231 /// This capability is not part of the spec yet, and may be removed or changed at any point.
5232 ///
5233 /// Sends an MCP-over-ACP notification.
5234 #[cfg(feature = "unstable_mcp_over_acp")]
5235 MessageMcpNotification(MessageMcpNotification),
5236 /// Handles extension notifications from the client.
5237 ///
5238 /// Extension notifications provide a way to send one-way messages for custom functionality
5239 /// while maintaining protocol compatibility.
5240 ///
5241 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5242 ExtNotification(ExtNotification),
5243}
5244
5245impl ClientNotification {
5246 /// Returns the corresponding method name of the notification.
5247 #[must_use]
5248 pub fn method(&self) -> &str {
5249 match self {
5250 Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
5251 #[cfg(feature = "unstable_nes")]
5252 Self::DidOpenDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_open,
5253 #[cfg(feature = "unstable_nes")]
5254 Self::DidChangeDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_change,
5255 #[cfg(feature = "unstable_nes")]
5256 Self::DidCloseDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_close,
5257 #[cfg(feature = "unstable_nes")]
5258 Self::DidSaveDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_save,
5259 #[cfg(feature = "unstable_nes")]
5260 Self::DidFocusDocumentNotification(_) => AGENT_METHOD_NAMES.document_did_focus,
5261 #[cfg(feature = "unstable_nes")]
5262 Self::AcceptNesNotification(_) => AGENT_METHOD_NAMES.nes_accept,
5263 #[cfg(feature = "unstable_nes")]
5264 Self::RejectNesNotification(_) => AGENT_METHOD_NAMES.nes_reject,
5265 #[cfg(feature = "unstable_mcp_over_acp")]
5266 Self::MessageMcpNotification(_) => AGENT_METHOD_NAMES.mcp_message,
5267 Self::ExtNotification(ext_notification) => &ext_notification.method,
5268 }
5269 }
5270}
5271
5272/// Notification to cancel ongoing operations for a session.
5273///
5274/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-lifecycle#cancellation)
5275#[skip_serializing_none]
5276#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
5277#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
5278#[serde(rename_all = "camelCase")]
5279#[non_exhaustive]
5280pub struct CancelNotification {
5281 /// The ID of the session to cancel operations for.
5282 pub session_id: SessionId,
5283 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
5284 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
5285 /// these keys.
5286 ///
5287 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5288 #[serde(rename = "_meta")]
5289 pub meta: Option<Meta>,
5290}
5291
5292impl CancelNotification {
5293 /// Builds [`CancelNotification`] with the required notification fields set; optional fields start unset or empty.
5294 #[must_use]
5295 pub fn new(session_id: impl Into<SessionId>) -> Self {
5296 Self {
5297 session_id: session_id.into(),
5298 meta: None,
5299 }
5300 }
5301
5302 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
5303 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
5304 /// these keys.
5305 ///
5306 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
5307 #[must_use]
5308 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
5309 self.meta = meta.into_option();
5310 self
5311 }
5312}
5313
5314#[cfg(test)]
5315mod test_serialization {
5316 use super::*;
5317 use serde_json::json;
5318
5319 fn test_meta() -> Meta {
5320 json!({ "source": "test" }).as_object().unwrap().clone()
5321 }
5322
5323 fn serialized_meta_key_count(value: &impl serde::Serialize) -> usize {
5324 serde_json::to_string(value)
5325 .unwrap()
5326 .matches("\"_meta\"")
5327 .count()
5328 }
5329
5330 #[test]
5331 fn test_mcp_server_stdio_serialization() {
5332 let server = McpServer::Stdio(
5333 McpServerStdio::new("test-server", "/usr/bin/server")
5334 .args(vec!["--port".to_string(), "3000".to_string()])
5335 .env(vec![EnvVariable::new("API_KEY", "secret123")]),
5336 );
5337
5338 let json = serde_json::to_value(&server).unwrap();
5339 assert_eq!(
5340 json,
5341 json!({
5342 "type": "stdio",
5343 "name": "test-server",
5344 "command": "/usr/bin/server",
5345 "args": ["--port", "3000"],
5346 "env": [
5347 {
5348 "name": "API_KEY",
5349 "value": "secret123"
5350 }
5351 ]
5352 })
5353 );
5354
5355 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5356 match deserialized {
5357 McpServer::Stdio(McpServerStdio {
5358 name,
5359 command,
5360 args,
5361 env,
5362 meta: _,
5363 }) => {
5364 assert_eq!(name, "test-server");
5365 assert_eq!(command, PathBuf::from("/usr/bin/server"));
5366 assert_eq!(args, vec!["--port", "3000"]);
5367 assert_eq!(env.len(), 1);
5368 assert_eq!(env[0].name, "API_KEY");
5369 assert_eq!(env[0].value, "secret123");
5370 }
5371 _ => panic!("Expected Stdio variant"),
5372 }
5373 }
5374
5375 #[test]
5376 fn test_mcp_server_unknown_transport_serialization() {
5377 let json = json!({
5378 "type": "websocket",
5379 "name": "future-server",
5380 "url": "wss://example.com/mcp",
5381 "protocolVersion": "2026-01-01"
5382 });
5383
5384 let deserialized: McpServer = serde_json::from_value(json.clone()).unwrap();
5385 let McpServer::Other(OtherMcpServer { type_, fields }) = &deserialized else {
5386 panic!("Expected Other variant");
5387 };
5388
5389 assert_eq!(type_, "websocket");
5390 assert_eq!(fields["name"], "future-server");
5391 assert_eq!(fields["url"], "wss://example.com/mcp");
5392 assert_eq!(fields["protocolVersion"], "2026-01-01");
5393 assert_eq!(serde_json::to_value(&deserialized).unwrap(), json);
5394 }
5395
5396 #[test]
5397 fn test_mcp_server_stdio_requires_type() {
5398 let result = serde_json::from_value::<McpServer>(json!({
5399 "name": "test-server",
5400 "command": "/usr/bin/server",
5401 "args": [],
5402 "env": []
5403 }));
5404
5405 assert!(result.is_err());
5406 }
5407
5408 #[test]
5409 fn test_mcp_server_unknown_does_not_hide_malformed_known_transport() {
5410 let result = serde_json::from_value::<McpServer>(json!({
5411 "type": "stdio",
5412 "name": "test-server",
5413 "args": [],
5414 "env": []
5415 }));
5416
5417 assert!(result.is_err());
5418 }
5419
5420 #[test]
5421 fn test_mcp_server_http_serialization() {
5422 let server = McpServer::Http(
5423 McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
5424 HttpHeader::new("Authorization", "Bearer token123"),
5425 HttpHeader::new("Content-Type", "application/json"),
5426 ]),
5427 );
5428
5429 let json = serde_json::to_value(&server).unwrap();
5430 assert_eq!(
5431 json,
5432 json!({
5433 "type": "http",
5434 "name": "http-server",
5435 "url": "https://api.example.com",
5436 "headers": [
5437 {
5438 "name": "Authorization",
5439 "value": "Bearer token123"
5440 },
5441 {
5442 "name": "Content-Type",
5443 "value": "application/json"
5444 }
5445 ]
5446 })
5447 );
5448
5449 let deserialized: McpServer = serde_json::from_value(json).unwrap();
5450 match deserialized {
5451 McpServer::Http(McpServerHttp {
5452 name,
5453 url,
5454 headers,
5455 meta: _,
5456 }) => {
5457 assert_eq!(name, "http-server");
5458 assert_eq!(url, "https://api.example.com");
5459 assert_eq!(headers.len(), 2);
5460 assert_eq!(headers[0].name, "Authorization");
5461 assert_eq!(headers[0].value, "Bearer token123");
5462 assert_eq!(headers[1].name, "Content-Type");
5463 assert_eq!(headers[1].value, "application/json");
5464 }
5465 _ => panic!("Expected Http variant"),
5466 }
5467 }
5468
5469 #[cfg(feature = "unstable_mcp_over_acp")]
5470 #[test]
5471 fn test_client_mcp_message_method_names() {
5472 assert_eq!(AGENT_METHOD_NAMES.mcp_message, "mcp/message");
5473
5474 assert_eq!(
5475 ClientRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
5476 .method(),
5477 "mcp/message"
5478 );
5479 assert_eq!(
5480 ClientNotification::MessageMcpNotification(MessageMcpNotification::new(
5481 "conn-1",
5482 "notifications/progress"
5483 ))
5484 .method(),
5485 "mcp/message"
5486 );
5487 }
5488
5489 #[test]
5490 fn test_session_config_option_category_known_variants() {
5491 // Test serialization of known variants
5492 assert_eq!(
5493 serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
5494 json!("mode")
5495 );
5496 assert_eq!(
5497 serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
5498 json!("model")
5499 );
5500 #[cfg(feature = "unstable_model_config_category")]
5501 assert_eq!(
5502 serde_json::to_value(&SessionConfigOptionCategory::ModelConfig).unwrap(),
5503 json!("model_config")
5504 );
5505 assert_eq!(
5506 serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
5507 json!("thought_level")
5508 );
5509
5510 // Test deserialization of known variants
5511 assert_eq!(
5512 serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
5513 SessionConfigOptionCategory::Mode
5514 );
5515 assert_eq!(
5516 serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
5517 SessionConfigOptionCategory::Model
5518 );
5519 #[cfg(feature = "unstable_model_config_category")]
5520 assert_eq!(
5521 serde_json::from_str::<SessionConfigOptionCategory>("\"model_config\"").unwrap(),
5522 SessionConfigOptionCategory::ModelConfig
5523 );
5524 assert_eq!(
5525 serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
5526 SessionConfigOptionCategory::ThoughtLevel
5527 );
5528 }
5529
5530 #[test]
5531 fn test_session_config_option_category_unknown_variants() {
5532 // Test that unknown strings are captured in Other variant
5533 let unknown: SessionConfigOptionCategory =
5534 serde_json::from_str("\"some_future_category\"").unwrap();
5535 assert_eq!(
5536 unknown,
5537 SessionConfigOptionCategory::Other("some_future_category".to_string())
5538 );
5539
5540 // Test round-trip of unknown category
5541 let json = serde_json::to_value(&unknown).unwrap();
5542 assert_eq!(json, json!("some_future_category"));
5543 }
5544
5545 #[cfg(not(feature = "unstable_model_config_category"))]
5546 #[test]
5547 fn test_session_config_option_model_config_is_unknown_without_feature() {
5548 let unknown: SessionConfigOptionCategory =
5549 serde_json::from_str("\"model_config\"").unwrap();
5550 assert_eq!(
5551 unknown,
5552 SessionConfigOptionCategory::Other("model_config".to_string())
5553 );
5554 }
5555
5556 #[test]
5557 fn test_session_config_option_category_custom_categories() {
5558 // Category names beginning with `_` are free for custom use
5559 let custom: SessionConfigOptionCategory =
5560 serde_json::from_str("\"_my_custom_category\"").unwrap();
5561 assert_eq!(
5562 custom,
5563 SessionConfigOptionCategory::Other("_my_custom_category".to_string())
5564 );
5565
5566 // Test round-trip preserves the custom category name
5567 let json = serde_json::to_value(&custom).unwrap();
5568 assert_eq!(json, json!("_my_custom_category"));
5569
5570 // Deserialize back and verify
5571 let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
5572 assert_eq!(
5573 deserialized,
5574 SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
5575 );
5576 }
5577
5578 #[test]
5579 fn test_auth_method_agent_serialization() {
5580 let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
5581
5582 let json = serde_json::to_value(&method).unwrap();
5583 assert_eq!(
5584 json,
5585 json!({
5586 "id": "default-auth",
5587 "name": "Default Auth",
5588 "type": "agent"
5589 })
5590 );
5591 // description should be omitted when None
5592 assert!(!json.as_object().unwrap().contains_key("description"));
5593
5594 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5595 match deserialized {
5596 AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
5597 assert_eq!(id.0.as_ref(), "default-auth");
5598 assert_eq!(name, "Default Auth");
5599 }
5600 _ => panic!("Expected Agent variant"),
5601 }
5602 }
5603
5604 #[test]
5605 fn test_auth_method_agent_deserialization() {
5606 let json = json!({
5607 "id": "agent-auth",
5608 "name": "Agent Auth",
5609 "type": "agent"
5610 });
5611
5612 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5613 assert!(matches!(deserialized, AuthMethod::Agent(_)));
5614 }
5615
5616 #[test]
5617 fn test_auth_method_agent_requires_type() {
5618 assert!(
5619 serde_json::from_value::<AuthMethod>(json!({
5620 "id": "agent-auth",
5621 "name": "Agent Auth"
5622 }))
5623 .is_err()
5624 );
5625 }
5626
5627 #[test]
5628 fn test_auth_method_agent_rejects_null_type() {
5629 assert!(
5630 serde_json::from_value::<AuthMethod>(json!({
5631 "id": "agent-auth",
5632 "name": "Agent Auth",
5633 "type": null
5634 }))
5635 .is_err()
5636 );
5637 }
5638
5639 #[test]
5640 fn test_auth_method_unknown_does_not_hide_malformed_agent() {
5641 assert!(
5642 serde_json::from_value::<AuthMethod>(json!({
5643 "id": "agent-auth",
5644 "type": "agent"
5645 }))
5646 .is_err()
5647 );
5648 }
5649
5650 #[test]
5651 fn test_auth_method_unknown_variant_roundtrip() {
5652 let method: AuthMethod = serde_json::from_value(json!({
5653 "id": "oauth",
5654 "name": "OAuth",
5655 "type": "_oauth",
5656 "authorizationUrl": "https://example.com/auth"
5657 }))
5658 .unwrap();
5659
5660 assert_eq!(method.id().0.as_ref(), "oauth");
5661 assert_eq!(method.name(), "OAuth");
5662 let AuthMethod::Other(unknown) = method else {
5663 panic!("expected unknown auth method");
5664 };
5665 assert_eq!(unknown.type_, "_oauth");
5666 assert_eq!(
5667 unknown.fields.get("authorizationUrl"),
5668 Some(&json!("https://example.com/auth"))
5669 );
5670
5671 assert_eq!(
5672 serde_json::to_value(AuthMethod::Other(unknown)).unwrap(),
5673 json!({
5674 "id": "oauth",
5675 "name": "OAuth",
5676 "type": "_oauth",
5677 "authorizationUrl": "https://example.com/auth"
5678 })
5679 );
5680 }
5681
5682 #[cfg(feature = "unstable_auth_methods")]
5683 #[test]
5684 fn test_auth_method_unknown_does_not_hide_malformed_known_variant() {
5685 assert!(
5686 serde_json::from_value::<AuthMethod>(json!({
5687 "id": "api-key",
5688 "name": "API Key",
5689 "type": "env_var"
5690 }))
5691 .is_err()
5692 );
5693 }
5694
5695 #[test]
5696 fn test_session_delete_serialization() {
5697 assert_eq!(AGENT_METHOD_NAMES.session_delete, "session/delete");
5698 assert_eq!(
5699 ClientRequest::DeleteSessionRequest(DeleteSessionRequest::new("sess_abc123")).method(),
5700 "session/delete"
5701 );
5702 assert_eq!(
5703 serde_json::to_value(DeleteSessionRequest::new("sess_abc123")).unwrap(),
5704 json!({
5705 "sessionId": "sess_abc123"
5706 })
5707 );
5708 assert_eq!(
5709 serde_json::to_value(DeleteSessionResponse::new()).unwrap(),
5710 json!({})
5711 );
5712 assert_eq!(
5713 serde_json::to_value(
5714 SessionCapabilities::new().delete(SessionDeleteCapabilities::new())
5715 )
5716 .unwrap(),
5717 json!({
5718 "delete": {}
5719 })
5720 );
5721 }
5722 #[test]
5723 fn test_session_additional_directories_serialization() {
5724 assert_eq!(
5725 serde_json::to_value(NewSessionRequest::new("/home/user/project")).unwrap(),
5726 json!({
5727 "cwd": "/home/user/project",
5728 "mcpServers": []
5729 })
5730 );
5731 assert_eq!(
5732 serde_json::to_value(
5733 NewSessionRequest::new("/home/user/project").additional_directories(vec![
5734 PathBuf::from("/home/user/shared-lib"),
5735 PathBuf::from("/home/user/product-docs"),
5736 ])
5737 )
5738 .unwrap(),
5739 json!({
5740 "cwd": "/home/user/project",
5741 "additionalDirectories": [
5742 "/home/user/shared-lib",
5743 "/home/user/product-docs"
5744 ],
5745 "mcpServers": []
5746 })
5747 );
5748 assert_eq!(
5749 serde_json::to_value(SessionInfo::new("sess_abc123", "/home/user/project")).unwrap(),
5750 json!({
5751 "sessionId": "sess_abc123",
5752 "cwd": "/home/user/project"
5753 })
5754 );
5755 assert_eq!(
5756 serde_json::to_value(
5757 SessionInfo::new("sess_abc123", "/home/user/project").additional_directories(vec![
5758 PathBuf::from("/home/user/shared-lib"),
5759 PathBuf::from("/home/user/product-docs"),
5760 ])
5761 )
5762 .unwrap(),
5763 json!({
5764 "sessionId": "sess_abc123",
5765 "cwd": "/home/user/project",
5766 "additionalDirectories": [
5767 "/home/user/shared-lib",
5768 "/home/user/product-docs"
5769 ]
5770 })
5771 );
5772 assert_eq!(
5773 serde_json::from_value::<SessionInfo>(json!({
5774 "sessionId": "sess_abc123",
5775 "cwd": "/home/user/project"
5776 }))
5777 .unwrap()
5778 .additional_directories,
5779 Vec::<PathBuf>::new()
5780 );
5781 }
5782 #[test]
5783 fn test_session_load_capabilities_serialization() {
5784 assert_eq!(
5785 serde_json::to_value(SessionCapabilities::new().load(SessionLoadCapabilities::new()))
5786 .unwrap(),
5787 json!({
5788 "load": {}
5789 })
5790 );
5791 }
5792
5793 #[test]
5794 fn test_session_additional_directories_capabilities_serialization() {
5795 assert_eq!(
5796 serde_json::to_value(
5797 SessionCapabilities::new()
5798 .additional_directories(SessionAdditionalDirectoriesCapabilities::new())
5799 )
5800 .unwrap(),
5801 json!({
5802 "additionalDirectories": {}
5803 })
5804 );
5805 }
5806
5807 #[cfg(feature = "unstable_auth_methods")]
5808 #[test]
5809 fn test_auth_method_env_var_serialization() {
5810 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5811 "api-key",
5812 "API Key",
5813 vec![AuthEnvVar::new("API_KEY")],
5814 ));
5815
5816 let json = serde_json::to_value(&method).unwrap();
5817 assert_eq!(
5818 json,
5819 json!({
5820 "id": "api-key",
5821 "name": "API Key",
5822 "type": "env_var",
5823 "vars": [{"name": "API_KEY"}]
5824 })
5825 );
5826 // secret defaults to true and should be omitted; optional defaults to false and should be omitted
5827 assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
5828 assert!(
5829 !json["vars"][0]
5830 .as_object()
5831 .unwrap()
5832 .contains_key("optional")
5833 );
5834
5835 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5836 match deserialized {
5837 AuthMethod::EnvVar(AuthMethodEnvVar {
5838 id,
5839 name: method_name,
5840 vars,
5841 link,
5842 ..
5843 }) => {
5844 assert_eq!(id.0.as_ref(), "api-key");
5845 assert_eq!(method_name, "API Key");
5846 assert_eq!(vars.len(), 1);
5847 assert_eq!(vars[0].name, "API_KEY");
5848 assert!(vars[0].secret);
5849 assert!(!vars[0].optional);
5850 assert!(link.is_none());
5851 }
5852 _ => panic!("Expected EnvVar variant"),
5853 }
5854 }
5855
5856 #[cfg(feature = "unstable_auth_methods")]
5857 #[test]
5858 fn test_auth_method_env_var_with_link_serialization() {
5859 let method = AuthMethod::EnvVar(
5860 AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
5861 .link("https://example.com/keys"),
5862 );
5863
5864 let json = serde_json::to_value(&method).unwrap();
5865 assert_eq!(
5866 json,
5867 json!({
5868 "id": "api-key",
5869 "name": "API Key",
5870 "type": "env_var",
5871 "vars": [{"name": "API_KEY"}],
5872 "link": "https://example.com/keys"
5873 })
5874 );
5875
5876 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5877 match deserialized {
5878 AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
5879 assert_eq!(link.as_deref(), Some("https://example.com/keys"));
5880 }
5881 _ => panic!("Expected EnvVar variant"),
5882 }
5883 }
5884
5885 #[cfg(feature = "unstable_auth_methods")]
5886 #[test]
5887 fn test_auth_method_env_var_multiple_vars() {
5888 let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
5889 "azure-openai",
5890 "Azure OpenAI",
5891 vec![
5892 AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
5893 AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
5894 .label("Endpoint URL")
5895 .secret(false),
5896 AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
5897 .label("API Version")
5898 .secret(false)
5899 .optional(true),
5900 ],
5901 ));
5902
5903 let json = serde_json::to_value(&method).unwrap();
5904 assert_eq!(
5905 json,
5906 json!({
5907 "id": "azure-openai",
5908 "name": "Azure OpenAI",
5909 "type": "env_var",
5910 "vars": [
5911 {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
5912 {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
5913 {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
5914 ]
5915 })
5916 );
5917
5918 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5919 match deserialized {
5920 AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
5921 assert_eq!(vars.len(), 3);
5922 // First var: secret (default true), not optional (default false)
5923 assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
5924 assert_eq!(vars[0].label.as_deref(), Some("API Key"));
5925 assert!(vars[0].secret);
5926 assert!(!vars[0].optional);
5927 // Second var: not a secret, not optional
5928 assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
5929 assert!(!vars[1].secret);
5930 assert!(!vars[1].optional);
5931 // Third var: not a secret, optional
5932 assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
5933 assert!(!vars[2].secret);
5934 assert!(vars[2].optional);
5935 }
5936 _ => panic!("Expected EnvVar variant"),
5937 }
5938 }
5939
5940 #[cfg(feature = "unstable_auth_methods")]
5941 #[test]
5942 fn test_auth_method_terminal_serialization() {
5943 let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
5944
5945 let json = serde_json::to_value(&method).unwrap();
5946 assert_eq!(
5947 json,
5948 json!({
5949 "id": "tui-auth",
5950 "name": "Terminal Auth",
5951 "type": "terminal"
5952 })
5953 );
5954 // args and env should be omitted when empty
5955 assert!(!json.as_object().unwrap().contains_key("args"));
5956 assert!(!json.as_object().unwrap().contains_key("env"));
5957
5958 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5959 match deserialized {
5960 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5961 assert!(args.is_empty());
5962 assert!(env.is_empty());
5963 }
5964 _ => panic!("Expected Terminal variant"),
5965 }
5966 }
5967
5968 #[cfg(feature = "unstable_auth_methods")]
5969 #[test]
5970 fn test_auth_method_terminal_with_args_and_env_serialization() {
5971 use std::collections::HashMap;
5972
5973 let mut env = HashMap::new();
5974 env.insert("TERM".to_string(), "xterm-256color".to_string());
5975
5976 let method = AuthMethod::Terminal(
5977 AuthMethodTerminal::new("tui-auth", "Terminal Auth")
5978 .args(vec!["--interactive".to_string(), "--color".to_string()])
5979 .env(env),
5980 );
5981
5982 let json = serde_json::to_value(&method).unwrap();
5983 assert_eq!(
5984 json,
5985 json!({
5986 "id": "tui-auth",
5987 "name": "Terminal Auth",
5988 "type": "terminal",
5989 "args": ["--interactive", "--color"],
5990 "env": {
5991 "TERM": "xterm-256color"
5992 }
5993 })
5994 );
5995
5996 let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
5997 match deserialized {
5998 AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
5999 assert_eq!(args, vec!["--interactive", "--color"]);
6000 assert_eq!(env.len(), 1);
6001 assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
6002 }
6003 _ => panic!("Expected Terminal variant"),
6004 }
6005 }
6006
6007 #[cfg(feature = "unstable_boolean_config")]
6008 #[test]
6009 fn test_session_config_option_value_id_serialize() {
6010 let val = SessionConfigOptionValue::value_id("model-1");
6011 let json = serde_json::to_value(&val).unwrap();
6012 // ValueId omits the "type" field (it's the default)
6013 assert_eq!(json, json!({ "value": "model-1" }));
6014 assert!(!json.as_object().unwrap().contains_key("type"));
6015 }
6016
6017 #[cfg(feature = "unstable_boolean_config")]
6018 #[test]
6019 fn test_session_config_option_value_boolean_serialize() {
6020 let val = SessionConfigOptionValue::boolean(true);
6021 let json = serde_json::to_value(&val).unwrap();
6022 assert_eq!(json, json!({ "type": "boolean", "value": true }));
6023 }
6024
6025 #[cfg(feature = "unstable_boolean_config")]
6026 #[test]
6027 fn test_session_config_option_value_deserialize_no_type() {
6028 // Missing "type" should default to ValueId
6029 let json = json!({ "value": "model-1" });
6030 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6031 assert_eq!(val, SessionConfigOptionValue::value_id("model-1"));
6032 assert_eq!(val.as_value_id().unwrap().to_string(), "model-1");
6033 }
6034
6035 #[cfg(feature = "unstable_boolean_config")]
6036 #[test]
6037 fn test_session_config_option_value_deserialize_boolean() {
6038 let json = json!({ "type": "boolean", "value": true });
6039 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6040 assert_eq!(val, SessionConfigOptionValue::boolean(true));
6041 assert_eq!(val.as_bool(), Some(true));
6042 }
6043
6044 #[cfg(feature = "unstable_boolean_config")]
6045 #[test]
6046 fn test_session_config_option_value_deserialize_boolean_false() {
6047 let json = json!({ "type": "boolean", "value": false });
6048 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6049 assert_eq!(val, SessionConfigOptionValue::boolean(false));
6050 assert_eq!(val.as_bool(), Some(false));
6051 }
6052
6053 #[cfg(feature = "unstable_boolean_config")]
6054 #[test]
6055 fn test_session_config_option_value_deserialize_unknown_type_with_string_value() {
6056 // Unknown type with a string value gracefully falls back to ValueId
6057 let json = json!({ "type": "text", "value": "freeform input" });
6058 let val: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6059 assert_eq!(val.as_value_id().unwrap().to_string(), "freeform input");
6060 }
6061
6062 #[cfg(feature = "unstable_boolean_config")]
6063 #[test]
6064 fn test_session_config_option_value_roundtrip_value_id() {
6065 let original = SessionConfigOptionValue::value_id("option-a");
6066 let json = serde_json::to_value(&original).unwrap();
6067 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6068 assert_eq!(original, roundtripped);
6069 }
6070
6071 #[cfg(feature = "unstable_boolean_config")]
6072 #[test]
6073 fn test_session_config_option_value_roundtrip_boolean() {
6074 let original = SessionConfigOptionValue::boolean(false);
6075 let json = serde_json::to_value(&original).unwrap();
6076 let roundtripped: SessionConfigOptionValue = serde_json::from_value(json).unwrap();
6077 assert_eq!(original, roundtripped);
6078 }
6079
6080 #[cfg(feature = "unstable_boolean_config")]
6081 #[test]
6082 fn test_session_config_option_value_type_mismatch_boolean_with_string() {
6083 // type says "boolean" but value is a string — falls to untagged ValueId
6084 let json = json!({ "type": "boolean", "value": "not a bool" });
6085 let result = serde_json::from_value::<SessionConfigOptionValue>(json);
6086 // serde tries Boolean first (fails), then falls to untagged ValueId (succeeds)
6087 assert!(result.is_ok());
6088 assert_eq!(
6089 result.unwrap().as_value_id().unwrap().to_string(),
6090 "not a bool"
6091 );
6092 }
6093
6094 #[cfg(feature = "unstable_boolean_config")]
6095 #[test]
6096 fn test_session_config_option_value_from_impls() {
6097 let from_str: SessionConfigOptionValue = "model-1".into();
6098 assert_eq!(from_str.as_value_id().unwrap().to_string(), "model-1");
6099
6100 let from_id: SessionConfigOptionValue = SessionConfigValueId::new("model-2").into();
6101 assert_eq!(from_id.as_value_id().unwrap().to_string(), "model-2");
6102
6103 let from_bool: SessionConfigOptionValue = true.into();
6104 assert_eq!(from_bool.as_bool(), Some(true));
6105 }
6106
6107 #[cfg(feature = "unstable_boolean_config")]
6108 #[test]
6109 fn test_set_session_config_option_request_value_id() {
6110 let req = SetSessionConfigOptionRequest::new("sess_1", "model", "model-1");
6111 let json = serde_json::to_value(&req).unwrap();
6112 assert_eq!(
6113 json,
6114 json!({
6115 "sessionId": "sess_1",
6116 "configId": "model",
6117 "value": "model-1"
6118 })
6119 );
6120 // No "type" field for value_id
6121 assert!(!json.as_object().unwrap().contains_key("type"));
6122 }
6123
6124 #[cfg(feature = "unstable_boolean_config")]
6125 #[test]
6126 fn test_set_session_config_option_request_boolean() {
6127 let req = SetSessionConfigOptionRequest::new("sess_1", "brave_mode", true);
6128 let json = serde_json::to_value(&req).unwrap();
6129 assert_eq!(
6130 json,
6131 json!({
6132 "sessionId": "sess_1",
6133 "configId": "brave_mode",
6134 "type": "boolean",
6135 "value": true
6136 })
6137 );
6138 }
6139
6140 #[cfg(feature = "unstable_boolean_config")]
6141 #[test]
6142 fn test_set_session_config_option_request_deserialize_no_type() {
6143 // Backwards-compatible: no "type" field → value_id
6144 let json = json!({
6145 "sessionId": "sess_1",
6146 "configId": "model",
6147 "value": "model-1"
6148 });
6149 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6150 assert_eq!(req.session_id.to_string(), "sess_1");
6151 assert_eq!(req.config_id.to_string(), "model");
6152 assert_eq!(req.value.as_value_id().unwrap().to_string(), "model-1");
6153 }
6154
6155 #[cfg(feature = "unstable_boolean_config")]
6156 #[test]
6157 fn test_set_session_config_option_request_deserialize_boolean() {
6158 let json = json!({
6159 "sessionId": "sess_1",
6160 "configId": "brave_mode",
6161 "type": "boolean",
6162 "value": true
6163 });
6164 let req: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6165 assert_eq!(req.value.as_bool(), Some(true));
6166 }
6167
6168 #[cfg(feature = "unstable_boolean_config")]
6169 #[test]
6170 fn test_set_session_config_option_request_roundtrip_value_id() {
6171 let original = SetSessionConfigOptionRequest::new("s", "c", "v");
6172 let json = serde_json::to_value(&original).unwrap();
6173 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6174 assert_eq!(original, roundtripped);
6175 }
6176
6177 #[cfg(feature = "unstable_boolean_config")]
6178 #[test]
6179 fn test_set_session_config_option_request_roundtrip_boolean() {
6180 let original = SetSessionConfigOptionRequest::new("s", "c", false);
6181 let json = serde_json::to_value(&original).unwrap();
6182 let roundtripped: SetSessionConfigOptionRequest = serde_json::from_value(json).unwrap();
6183 assert_eq!(original, roundtripped);
6184 }
6185
6186 #[cfg(feature = "unstable_boolean_config")]
6187 #[test]
6188 fn test_session_config_boolean_serialization() {
6189 let cfg = SessionConfigBoolean::new(true);
6190 let json = serde_json::to_value(&cfg).unwrap();
6191 assert_eq!(json, json!({ "currentValue": true }));
6192
6193 let deserialized: SessionConfigBoolean = serde_json::from_value(json).unwrap();
6194 assert!(deserialized.current_value);
6195 }
6196
6197 #[cfg(feature = "unstable_boolean_config")]
6198 #[test]
6199 fn test_session_config_option_boolean_variant() {
6200 let opt = SessionConfigOption::boolean("brave_mode", "Brave Mode", false)
6201 .description("Skip confirmation prompts")
6202 .meta(test_meta());
6203 assert_eq!(serialized_meta_key_count(&opt), 1);
6204
6205 let json = serde_json::to_value(&opt).unwrap();
6206 assert_eq!(
6207 json,
6208 json!({
6209 "id": "brave_mode",
6210 "name": "Brave Mode",
6211 "description": "Skip confirmation prompts",
6212 "type": "boolean",
6213 "currentValue": false,
6214 "_meta": {
6215 "source": "test"
6216 }
6217 })
6218 );
6219
6220 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6221 assert_eq!(deserialized.id.to_string(), "brave_mode");
6222 assert_eq!(deserialized.name, "Brave Mode");
6223 match deserialized.kind {
6224 SessionConfigKind::Boolean(ref b) => assert!(!b.current_value),
6225 _ => panic!("Expected Boolean kind"),
6226 }
6227 }
6228
6229 #[cfg(feature = "unstable_boolean_config")]
6230 #[test]
6231 fn test_session_config_option_select_still_works() {
6232 // Make sure existing select options are unaffected
6233 let opt = SessionConfigOption::select(
6234 "model",
6235 "Model",
6236 "model-1",
6237 vec![
6238 SessionConfigSelectOption::new("model-1", "Model 1"),
6239 SessionConfigSelectOption::new("model-2", "Model 2"),
6240 ],
6241 )
6242 .meta(test_meta());
6243 assert_eq!(serialized_meta_key_count(&opt), 1);
6244
6245 let json = serde_json::to_value(&opt).unwrap();
6246 assert_eq!(json["type"], "select");
6247 assert_eq!(json["currentValue"], "model-1");
6248 assert_eq!(json["options"].as_array().unwrap().len(), 2);
6249 assert_eq!(json["_meta"]["source"], "test");
6250
6251 let deserialized: SessionConfigOption = serde_json::from_value(json).unwrap();
6252 match deserialized.kind {
6253 SessionConfigKind::Select(ref s) => {
6254 assert_eq!(s.current_value.to_string(), "model-1");
6255 }
6256 _ => panic!("Expected Select kind"),
6257 }
6258 }
6259
6260 #[test]
6261 fn test_session_config_option_unknown_kind_roundtrip() {
6262 let option: SessionConfigOption = serde_json::from_value(json!({
6263 "id": "verbosity",
6264 "name": "Verbosity",
6265 "type": "_slider",
6266 "currentValue": 3,
6267 "min": 0,
6268 "max": 5,
6269 "_meta": {
6270 "source": "test"
6271 }
6272 }))
6273 .unwrap();
6274
6275 assert_eq!(option.id.to_string(), "verbosity");
6276 assert_eq!(option.meta.as_ref().unwrap()["source"], "test");
6277 let SessionConfigKind::Other(unknown) = &option.kind else {
6278 panic!("expected unknown config kind");
6279 };
6280 assert_eq!(unknown.type_, "_slider");
6281 assert_eq!(unknown.fields.get("currentValue"), Some(&json!(3)));
6282 assert!(!unknown.fields.contains_key("_meta"));
6283 assert_eq!(serialized_meta_key_count(&option), 1);
6284
6285 let json = serde_json::to_value(&option).unwrap();
6286 assert_eq!(json["type"], "_slider");
6287 assert_eq!(json["currentValue"], 3);
6288 assert_eq!(json["min"], 0);
6289 assert_eq!(json["max"], 5);
6290 assert_eq!(json["_meta"]["source"], "test");
6291 }
6292
6293 #[test]
6294 fn test_session_config_option_unknown_kind_does_not_duplicate_flattened_meta() {
6295 let mut fields = std::collections::BTreeMap::new();
6296 fields.insert("currentValue".to_string(), json!(3));
6297 fields.insert("_meta".to_string(), json!({ "inner": "ignored" }));
6298
6299 let option = SessionConfigOption::new(
6300 "verbosity",
6301 "Verbosity",
6302 SessionConfigKind::Other(OtherSessionConfigKind::new("_slider", fields)),
6303 )
6304 .meta(test_meta());
6305
6306 let SessionConfigKind::Other(unknown) = &option.kind else {
6307 panic!("expected unknown config kind");
6308 };
6309 assert!(!unknown.fields.contains_key("_meta"));
6310 assert_eq!(serialized_meta_key_count(&option), 1);
6311
6312 let json = serde_json::to_value(&option).unwrap();
6313 assert_eq!(json["type"], "_slider");
6314 assert_eq!(json["currentValue"], 3);
6315 assert_eq!(json["_meta"]["source"], "test");
6316 }
6317
6318 #[test]
6319 fn test_session_config_option_unknown_does_not_hide_malformed_known_kind() {
6320 assert!(
6321 serde_json::from_value::<SessionConfigOption>(json!({
6322 "id": "model",
6323 "name": "Model",
6324 "type": "select"
6325 }))
6326 .is_err()
6327 );
6328 }
6329
6330 #[cfg(feature = "unstable_llm_providers")]
6331 #[test]
6332 fn test_llm_protocol_known_variants() {
6333 assert_eq!(
6334 serde_json::to_value(&LlmProtocol::Anthropic).unwrap(),
6335 json!("anthropic")
6336 );
6337 assert_eq!(
6338 serde_json::to_value(&LlmProtocol::OpenAi).unwrap(),
6339 json!("openai")
6340 );
6341 assert_eq!(
6342 serde_json::to_value(&LlmProtocol::Azure).unwrap(),
6343 json!("azure")
6344 );
6345 assert_eq!(
6346 serde_json::to_value(&LlmProtocol::Vertex).unwrap(),
6347 json!("vertex")
6348 );
6349 assert_eq!(
6350 serde_json::to_value(&LlmProtocol::Bedrock).unwrap(),
6351 json!("bedrock")
6352 );
6353
6354 assert_eq!(
6355 serde_json::from_str::<LlmProtocol>("\"anthropic\"").unwrap(),
6356 LlmProtocol::Anthropic
6357 );
6358 assert_eq!(
6359 serde_json::from_str::<LlmProtocol>("\"openai\"").unwrap(),
6360 LlmProtocol::OpenAi
6361 );
6362 assert_eq!(
6363 serde_json::from_str::<LlmProtocol>("\"azure\"").unwrap(),
6364 LlmProtocol::Azure
6365 );
6366 assert_eq!(
6367 serde_json::from_str::<LlmProtocol>("\"vertex\"").unwrap(),
6368 LlmProtocol::Vertex
6369 );
6370 assert_eq!(
6371 serde_json::from_str::<LlmProtocol>("\"bedrock\"").unwrap(),
6372 LlmProtocol::Bedrock
6373 );
6374 }
6375
6376 #[cfg(feature = "unstable_llm_providers")]
6377 #[test]
6378 fn test_llm_protocol_unknown_variant() {
6379 let unknown: LlmProtocol = serde_json::from_str("\"cohere\"").unwrap();
6380 assert_eq!(unknown, LlmProtocol::Other("cohere".to_string()));
6381
6382 let json = serde_json::to_value(&unknown).unwrap();
6383 assert_eq!(json, json!("cohere"));
6384 }
6385
6386 #[cfg(feature = "unstable_llm_providers")]
6387 #[test]
6388 fn test_provider_current_config_serialization() {
6389 let config =
6390 ProviderCurrentConfig::new(LlmProtocol::Anthropic, "https://api.anthropic.com");
6391
6392 let json = serde_json::to_value(&config).unwrap();
6393 assert_eq!(
6394 json,
6395 json!({
6396 "apiType": "anthropic",
6397 "baseUrl": "https://api.anthropic.com"
6398 })
6399 );
6400
6401 let deserialized: ProviderCurrentConfig = serde_json::from_value(json).unwrap();
6402 assert_eq!(deserialized.api_type, LlmProtocol::Anthropic);
6403 assert_eq!(deserialized.base_url, "https://api.anthropic.com");
6404 }
6405
6406 #[cfg(feature = "unstable_llm_providers")]
6407 #[test]
6408 fn test_provider_info_with_current_config() {
6409 let info = ProviderInfo::new(
6410 "main",
6411 vec![LlmProtocol::Anthropic, LlmProtocol::OpenAi],
6412 true,
6413 Some(ProviderCurrentConfig::new(
6414 LlmProtocol::Anthropic,
6415 "https://api.anthropic.com",
6416 )),
6417 );
6418
6419 let json = serde_json::to_value(&info).unwrap();
6420 assert_eq!(
6421 json,
6422 json!({
6423 "id": "main",
6424 "supported": ["anthropic", "openai"],
6425 "required": true,
6426 "current": {
6427 "apiType": "anthropic",
6428 "baseUrl": "https://api.anthropic.com"
6429 }
6430 })
6431 );
6432
6433 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6434 assert_eq!(deserialized.id, "main");
6435 assert_eq!(deserialized.supported.len(), 2);
6436 assert!(deserialized.required);
6437 assert!(deserialized.current.is_some());
6438 assert_eq!(
6439 deserialized.current.as_ref().unwrap().api_type,
6440 LlmProtocol::Anthropic
6441 );
6442 }
6443
6444 #[cfg(feature = "unstable_llm_providers")]
6445 #[test]
6446 fn test_provider_info_disabled() {
6447 let info = ProviderInfo::new(
6448 "secondary",
6449 vec![LlmProtocol::OpenAi],
6450 false,
6451 None::<ProviderCurrentConfig>,
6452 );
6453
6454 let json = serde_json::to_value(&info).unwrap();
6455 assert_eq!(
6456 json,
6457 json!({
6458 "id": "secondary",
6459 "supported": ["openai"],
6460 "required": false
6461 })
6462 );
6463
6464 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6465 assert_eq!(deserialized.id, "secondary");
6466 assert!(!deserialized.required);
6467 assert!(deserialized.current.is_none());
6468 }
6469
6470 #[cfg(feature = "unstable_llm_providers")]
6471 #[test]
6472 fn test_provider_info_missing_current_defaults_to_none() {
6473 // current is optional; omitting it should decode as None
6474 let json = json!({
6475 "id": "main",
6476 "supported": ["anthropic"],
6477 "required": true
6478 });
6479 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6480 assert!(deserialized.current.is_none());
6481 }
6482
6483 #[cfg(feature = "unstable_llm_providers")]
6484 #[test]
6485 fn test_provider_info_explicit_null_current_decodes_to_none() {
6486 // current: null and an omitted current are equivalent on the wire;
6487 // both must deserialize into None so the disabled state is preserved
6488 // regardless of which form the peer chose to send.
6489 let json = json!({
6490 "id": "main",
6491 "supported": ["anthropic"],
6492 "required": true,
6493 "current": null
6494 });
6495 let deserialized: ProviderInfo = serde_json::from_value(json).unwrap();
6496 assert!(deserialized.current.is_none());
6497 }
6498
6499 #[cfg(feature = "unstable_llm_providers")]
6500 #[test]
6501 fn test_list_providers_response_serialization() {
6502 let response = ListProvidersResponse::new(vec![ProviderInfo::new(
6503 "main",
6504 vec![LlmProtocol::Anthropic],
6505 true,
6506 Some(ProviderCurrentConfig::new(
6507 LlmProtocol::Anthropic,
6508 "https://api.anthropic.com",
6509 )),
6510 )]);
6511
6512 let json = serde_json::to_value(&response).unwrap();
6513 assert_eq!(json["providers"].as_array().unwrap().len(), 1);
6514 assert_eq!(json["providers"][0]["id"], "main");
6515
6516 let deserialized: ListProvidersResponse = serde_json::from_value(json).unwrap();
6517 assert_eq!(deserialized.providers.len(), 1);
6518 }
6519
6520 #[cfg(feature = "unstable_llm_providers")]
6521 #[test]
6522 fn test_set_provider_request_serialization() {
6523 use std::collections::HashMap;
6524
6525 let mut headers = HashMap::new();
6526 headers.insert("Authorization".to_string(), "Bearer sk-test".to_string());
6527
6528 let request =
6529 SetProviderRequest::new("main", LlmProtocol::OpenAi, "https://api.openai.com/v1")
6530 .headers(headers);
6531
6532 let json = serde_json::to_value(&request).unwrap();
6533 assert_eq!(
6534 json,
6535 json!({
6536 "id": "main",
6537 "apiType": "openai",
6538 "baseUrl": "https://api.openai.com/v1",
6539 "headers": {
6540 "Authorization": "Bearer sk-test"
6541 }
6542 })
6543 );
6544
6545 let deserialized: SetProviderRequest = serde_json::from_value(json).unwrap();
6546 assert_eq!(deserialized.id, "main");
6547 assert_eq!(deserialized.api_type, LlmProtocol::OpenAi);
6548 assert_eq!(deserialized.base_url, "https://api.openai.com/v1");
6549 assert_eq!(deserialized.headers.len(), 1);
6550 assert_eq!(
6551 deserialized.headers.get("Authorization").unwrap(),
6552 "Bearer sk-test"
6553 );
6554 }
6555
6556 #[cfg(feature = "unstable_llm_providers")]
6557 #[test]
6558 fn test_set_provider_request_omits_empty_headers() {
6559 let request =
6560 SetProviderRequest::new("main", LlmProtocol::Anthropic, "https://api.anthropic.com");
6561
6562 let json = serde_json::to_value(&request).unwrap();
6563 // headers should be omitted when empty
6564 assert!(!json.as_object().unwrap().contains_key("headers"));
6565 }
6566
6567 #[cfg(feature = "unstable_llm_providers")]
6568 #[test]
6569 fn test_disable_provider_request_serialization() {
6570 let request = DisableProviderRequest::new("secondary");
6571
6572 let json = serde_json::to_value(&request).unwrap();
6573 assert_eq!(json, json!({ "id": "secondary" }));
6574
6575 let deserialized: DisableProviderRequest = serde_json::from_value(json).unwrap();
6576 assert_eq!(deserialized.id, "secondary");
6577 }
6578
6579 #[cfg(feature = "unstable_llm_providers")]
6580 #[test]
6581 fn test_providers_capabilities_serialization() {
6582 let caps = ProvidersCapabilities::new();
6583
6584 let json = serde_json::to_value(&caps).unwrap();
6585 assert_eq!(json, json!({}));
6586
6587 let deserialized: ProvidersCapabilities = serde_json::from_value(json).unwrap();
6588 assert!(deserialized.meta.is_none());
6589 }
6590
6591 #[cfg(feature = "unstable_llm_providers")]
6592 #[test]
6593 fn test_agent_capabilities_with_providers() {
6594 let caps = AgentCapabilities::new().providers(ProvidersCapabilities::new());
6595
6596 let json = serde_json::to_value(&caps).unwrap();
6597 assert_eq!(json["providers"], json!({}));
6598
6599 let deserialized: AgentCapabilities = serde_json::from_value(json).unwrap();
6600 assert!(deserialized.providers.is_some());
6601 }
6602
6603 #[test]
6604 fn test_agent_capabilities_session_is_explicit() {
6605 let json = serde_json::to_value(AgentCapabilities::new()).unwrap();
6606 assert!(json.get("session").is_none());
6607
6608 let caps = AgentCapabilities::new().session(
6609 SessionCapabilities::new()
6610 .prompt(PromptCapabilities::new().image(PromptImageCapabilities::new()))
6611 .mcp(McpCapabilities::new().stdio(McpStdioCapabilities::new()))
6612 .load(SessionLoadCapabilities::new()),
6613 );
6614
6615 assert_eq!(
6616 serde_json::to_value(&caps).unwrap(),
6617 json!({
6618 "auth": {},
6619 "session": {
6620 "prompt": {
6621 "image": {}
6622 },
6623 "mcp": {
6624 "stdio": {}
6625 },
6626 "load": {}
6627 }
6628 })
6629 );
6630
6631 let deserialized: AgentCapabilities = serde_json::from_value(json!({
6632 "session": false
6633 }))
6634 .unwrap();
6635 assert!(deserialized.session.is_none());
6636 }
6637
6638 #[test]
6639 fn test_prompt_capabilities_serialize_supported_content_as_objects() {
6640 let caps = PromptCapabilities::new()
6641 .image(PromptImageCapabilities::new())
6642 .audio(PromptAudioCapabilities::new())
6643 .embedded_context(PromptEmbeddedContextCapabilities::new());
6644
6645 assert_eq!(
6646 serde_json::to_value(&caps).unwrap(),
6647 json!({
6648 "image": {},
6649 "audio": {},
6650 "embeddedContext": {}
6651 })
6652 );
6653
6654 let deserialized: PromptCapabilities = serde_json::from_value(json!({
6655 "image": null,
6656 "audio": false,
6657 "embeddedContext": {}
6658 }))
6659 .unwrap();
6660 assert!(deserialized.image.is_none());
6661 assert!(deserialized.audio.is_none());
6662 assert!(deserialized.embedded_context.is_some());
6663 }
6664
6665 #[test]
6666 fn test_mcp_capabilities_serialize_supported_transports_as_objects() {
6667 let caps = McpCapabilities::new()
6668 .stdio(McpStdioCapabilities::new())
6669 .http(McpHttpCapabilities::new());
6670
6671 assert_eq!(
6672 serde_json::to_value(&caps).unwrap(),
6673 json!({
6674 "stdio": {},
6675 "http": {}
6676 })
6677 );
6678
6679 let deserialized: McpCapabilities = serde_json::from_value(json!({
6680 "stdio": null,
6681 "http": false
6682 }))
6683 .unwrap();
6684 assert!(deserialized.stdio.is_none());
6685 assert!(deserialized.http.is_none());
6686 }
6687
6688 #[cfg(feature = "unstable_mcp_over_acp")]
6689 #[test]
6690 fn test_mcp_capabilities_serialize_acp_support_as_object() {
6691 let caps = McpCapabilities::new().acp(McpAcpCapabilities::new());
6692
6693 assert_eq!(
6694 serde_json::to_value(&caps).unwrap(),
6695 json!({
6696 "acp": {}
6697 })
6698 );
6699 }
6700}