Skip to main content

agent_client_protocol_schema/
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::{path::PathBuf, sync::Arc};
7
8#[cfg(feature = "unstable_auth_methods")]
9use std::collections::HashMap;
10
11use derive_more::{Display, From};
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14
15use crate::{
16    ClientCapabilities, ContentBlock, ExtNotification, ExtRequest, ExtResponse, IntoOption, Meta,
17    ProtocolVersion, SessionId,
18};
19
20// Initialize
21
22/// Request parameters for the initialize method.
23///
24/// Sent by the client to establish connection and negotiate capabilities.
25///
26/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
27#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
28#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
29#[serde(rename_all = "camelCase")]
30#[non_exhaustive]
31pub struct InitializeRequest {
32    /// The latest protocol version supported by the client.
33    pub protocol_version: ProtocolVersion,
34    /// Capabilities supported by the client.
35    #[serde(default)]
36    pub client_capabilities: ClientCapabilities,
37    /// Information about the Client name and version sent to the Agent.
38    ///
39    /// Note: in future versions of the protocol, this will be required.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub client_info: Option<Implementation>,
42    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
43    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
44    /// these keys.
45    ///
46    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
47    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
48    pub meta: Option<Meta>,
49}
50
51impl InitializeRequest {
52    #[must_use]
53    pub fn new(protocol_version: ProtocolVersion) -> Self {
54        Self {
55            protocol_version,
56            client_capabilities: ClientCapabilities::default(),
57            client_info: None,
58            meta: None,
59        }
60    }
61
62    /// Capabilities supported by the client.
63    #[must_use]
64    pub fn client_capabilities(mut self, client_capabilities: ClientCapabilities) -> Self {
65        self.client_capabilities = client_capabilities;
66        self
67    }
68
69    /// Information about the Client name and version sent to the Agent.
70    #[must_use]
71    pub fn client_info(mut self, client_info: impl IntoOption<Implementation>) -> Self {
72        self.client_info = client_info.into_option();
73        self
74    }
75
76    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
77    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
78    /// these keys.
79    ///
80    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
81    #[must_use]
82    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
83        self.meta = meta.into_option();
84        self
85    }
86}
87
88/// Response to the `initialize` method.
89///
90/// Contains the negotiated protocol version and agent capabilities.
91///
92/// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
93#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
94#[schemars(extend("x-side" = "agent", "x-method" = INITIALIZE_METHOD_NAME))]
95#[serde(rename_all = "camelCase")]
96#[non_exhaustive]
97pub struct InitializeResponse {
98    /// The protocol version the client specified if supported by the agent,
99    /// or the latest protocol version supported by the agent.
100    ///
101    /// The client should disconnect, if it doesn't support this version.
102    pub protocol_version: ProtocolVersion,
103    /// Capabilities supported by the agent.
104    #[serde(default)]
105    pub agent_capabilities: AgentCapabilities,
106    /// Authentication methods supported by the agent.
107    #[serde(default)]
108    pub auth_methods: Vec<AuthMethod>,
109    /// Information about the Agent name and version sent to the Client.
110    ///
111    /// Note: in future versions of the protocol, this will be required.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub agent_info: Option<Implementation>,
114    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
115    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
116    /// these keys.
117    ///
118    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
119    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
120    pub meta: Option<Meta>,
121}
122
123impl InitializeResponse {
124    #[must_use]
125    pub fn new(protocol_version: ProtocolVersion) -> Self {
126        Self {
127            protocol_version,
128            agent_capabilities: AgentCapabilities::default(),
129            auth_methods: vec![],
130            agent_info: None,
131            meta: None,
132        }
133    }
134
135    /// Capabilities supported by the agent.
136    #[must_use]
137    pub fn agent_capabilities(mut self, agent_capabilities: AgentCapabilities) -> Self {
138        self.agent_capabilities = agent_capabilities;
139        self
140    }
141
142    /// Authentication methods supported by the agent.
143    #[must_use]
144    pub fn auth_methods(mut self, auth_methods: Vec<AuthMethod>) -> Self {
145        self.auth_methods = auth_methods;
146        self
147    }
148
149    /// Information about the Agent name and version sent to the Client.
150    #[must_use]
151    pub fn agent_info(mut self, agent_info: impl IntoOption<Implementation>) -> Self {
152        self.agent_info = agent_info.into_option();
153        self
154    }
155
156    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
157    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
158    /// these keys.
159    ///
160    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
161    #[must_use]
162    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
163        self.meta = meta.into_option();
164        self
165    }
166}
167
168/// Metadata about the implementation of the client or agent.
169/// Describes the name and version of an MCP implementation, with an optional
170/// title for UI representation.
171#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
172#[serde(rename_all = "camelCase")]
173#[non_exhaustive]
174pub struct Implementation {
175    /// Intended for programmatic or logical use, but can be used as a display
176    /// name fallback if title isn’t present.
177    pub name: String,
178    /// Intended for UI and end-user contexts — optimized to be human-readable
179    /// and easily understood.
180    ///
181    /// If not provided, the name should be used for display.
182    pub title: Option<String>,
183    /// Version of the implementation. Can be displayed to the user or used
184    /// for debugging or metrics purposes. (e.g. "1.0.0").
185    pub version: String,
186    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
187    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
188    /// these keys.
189    ///
190    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
191    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
192    pub meta: Option<Meta>,
193}
194
195impl Implementation {
196    #[must_use]
197    pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
198        Self {
199            name: name.into(),
200            title: None,
201            version: version.into(),
202            meta: None,
203        }
204    }
205
206    /// Intended for UI and end-user contexts — optimized to be human-readable
207    /// and easily understood.
208    ///
209    /// If not provided, the name should be used for display.
210    #[must_use]
211    pub fn title(mut self, title: impl IntoOption<String>) -> Self {
212        self.title = title.into_option();
213        self
214    }
215
216    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
217    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
218    /// these keys.
219    ///
220    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
221    #[must_use]
222    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
223        self.meta = meta.into_option();
224        self
225    }
226}
227
228// Authentication
229
230/// Request parameters for the authenticate method.
231///
232/// Specifies which authentication method to use.
233#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
234#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
235#[serde(rename_all = "camelCase")]
236#[non_exhaustive]
237pub struct AuthenticateRequest {
238    /// The ID of the authentication method to use.
239    /// Must be one of the methods advertised in the initialize response.
240    pub method_id: AuthMethodId,
241    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
242    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
243    /// these keys.
244    ///
245    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
246    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
247    pub meta: Option<Meta>,
248}
249
250impl AuthenticateRequest {
251    #[must_use]
252    pub fn new(method_id: impl Into<AuthMethodId>) -> Self {
253        Self {
254            method_id: method_id.into(),
255            meta: None,
256        }
257    }
258
259    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
260    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
261    /// these keys.
262    ///
263    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
264    #[must_use]
265    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
266        self.meta = meta.into_option();
267        self
268    }
269}
270
271/// Response to the `authenticate` method.
272#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
273#[schemars(extend("x-side" = "agent", "x-method" = AUTHENTICATE_METHOD_NAME))]
274#[serde(rename_all = "camelCase")]
275#[non_exhaustive]
276pub struct AuthenticateResponse {
277    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
278    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
279    /// these keys.
280    ///
281    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
282    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
283    pub meta: Option<Meta>,
284}
285
286impl AuthenticateResponse {
287    #[must_use]
288    pub fn new() -> Self {
289        Self::default()
290    }
291
292    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
293    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
294    /// these keys.
295    ///
296    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
297    #[must_use]
298    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
299        self.meta = meta.into_option();
300        self
301    }
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
305#[serde(transparent)]
306#[from(Arc<str>, String, &'static str)]
307#[non_exhaustive]
308pub struct AuthMethodId(pub Arc<str>);
309
310impl AuthMethodId {
311    #[must_use]
312    pub fn new(id: impl Into<Arc<str>>) -> Self {
313        Self(id.into())
314    }
315}
316
317/// Describes an available authentication method.
318///
319/// The `type` field acts as the discriminator in the serialized JSON form.
320/// When no `type` is present, the method is treated as `agent`.
321#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
322#[serde(tag = "type", rename_all = "snake_case")]
323#[non_exhaustive]
324pub enum AuthMethod {
325    /// **UNSTABLE**
326    ///
327    /// This capability is not part of the spec yet, and may be removed or changed at any point.
328    ///
329    /// User provides a key that the client passes to the agent as an environment variable.
330    #[cfg(feature = "unstable_auth_methods")]
331    EnvVar(AuthMethodEnvVar),
332    /// **UNSTABLE**
333    ///
334    /// This capability is not part of the spec yet, and may be removed or changed at any point.
335    ///
336    /// Client runs an interactive terminal for the user to authenticate via a TUI.
337    #[cfg(feature = "unstable_auth_methods")]
338    Terminal(AuthMethodTerminal),
339    /// Agent handles authentication itself.
340    ///
341    /// This is the default when no `type` is specified.
342    #[serde(untagged)]
343    Agent(AuthMethodAgent),
344}
345
346impl AuthMethod {
347    /// The unique identifier for this authentication method.
348    #[must_use]
349    pub fn id(&self) -> &AuthMethodId {
350        match self {
351            Self::Agent(a) => &a.id,
352            #[cfg(feature = "unstable_auth_methods")]
353            Self::EnvVar(e) => &e.id,
354            #[cfg(feature = "unstable_auth_methods")]
355            Self::Terminal(t) => &t.id,
356        }
357    }
358
359    /// The human-readable name of this authentication method.
360    #[must_use]
361    pub fn name(&self) -> &str {
362        match self {
363            Self::Agent(a) => &a.name,
364            #[cfg(feature = "unstable_auth_methods")]
365            Self::EnvVar(e) => &e.name,
366            #[cfg(feature = "unstable_auth_methods")]
367            Self::Terminal(t) => &t.name,
368        }
369    }
370
371    /// Optional description providing more details about this authentication method.
372    #[must_use]
373    pub fn description(&self) -> Option<&str> {
374        match self {
375            Self::Agent(a) => a.description.as_deref(),
376            #[cfg(feature = "unstable_auth_methods")]
377            Self::EnvVar(e) => e.description.as_deref(),
378            #[cfg(feature = "unstable_auth_methods")]
379            Self::Terminal(t) => t.description.as_deref(),
380        }
381    }
382}
383
384/// Agent handles authentication itself.
385///
386/// This is the default authentication method type.
387#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
388#[serde(rename_all = "camelCase")]
389#[non_exhaustive]
390pub struct AuthMethodAgent {
391    /// Unique identifier for this authentication method.
392    pub id: AuthMethodId,
393    /// Human-readable name of the authentication method.
394    pub name: String,
395    /// Optional description providing more details about this authentication method.
396    #[serde(skip_serializing_if = "Option::is_none")]
397    pub description: Option<String>,
398    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
399    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
400    /// these keys.
401    ///
402    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
403    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
404    pub meta: Option<Meta>,
405}
406
407impl AuthMethodAgent {
408    #[must_use]
409    pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
410        Self {
411            id: id.into(),
412            name: name.into(),
413            description: None,
414            meta: None,
415        }
416    }
417
418    /// Optional description providing more details about this authentication method.
419    #[must_use]
420    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
421        self.description = description.into_option();
422        self
423    }
424
425    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
426    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
427    /// these keys.
428    ///
429    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
430    #[must_use]
431    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
432        self.meta = meta.into_option();
433        self
434    }
435}
436
437/// **UNSTABLE**
438///
439/// This capability is not part of the spec yet, and may be removed or changed at any point.
440///
441/// Environment variable authentication method.
442///
443/// The user provides credentials that the client passes to the agent as environment variables.
444#[cfg(feature = "unstable_auth_methods")]
445#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
446#[serde(rename_all = "camelCase")]
447#[non_exhaustive]
448pub struct AuthMethodEnvVar {
449    /// Unique identifier for this authentication method.
450    pub id: AuthMethodId,
451    /// Human-readable name of the authentication method.
452    pub name: String,
453    /// Optional description providing more details about this authentication method.
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub description: Option<String>,
456    /// The environment variables the client should set.
457    pub vars: Vec<AuthEnvVar>,
458    /// Optional link to a page where the user can obtain their credentials.
459    #[serde(skip_serializing_if = "Option::is_none")]
460    pub link: Option<String>,
461    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
462    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
463    /// these keys.
464    ///
465    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
466    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
467    pub meta: Option<Meta>,
468}
469
470#[cfg(feature = "unstable_auth_methods")]
471impl AuthMethodEnvVar {
472    #[must_use]
473    pub fn new(
474        id: impl Into<AuthMethodId>,
475        name: impl Into<String>,
476        vars: Vec<AuthEnvVar>,
477    ) -> Self {
478        Self {
479            id: id.into(),
480            name: name.into(),
481            description: None,
482            vars,
483            link: None,
484            meta: None,
485        }
486    }
487
488    /// Optional link to a page where the user can obtain their credentials.
489    #[must_use]
490    pub fn link(mut self, link: impl IntoOption<String>) -> Self {
491        self.link = link.into_option();
492        self
493    }
494
495    /// Optional description providing more details about this authentication method.
496    #[must_use]
497    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
498        self.description = description.into_option();
499        self
500    }
501
502    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
503    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
504    /// these keys.
505    ///
506    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
507    #[must_use]
508    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
509        self.meta = meta.into_option();
510        self
511    }
512}
513
514/// **UNSTABLE**
515///
516/// This capability is not part of the spec yet, and may be removed or changed at any point.
517///
518/// Describes a single environment variable for an [`AuthMethodEnvVar`] authentication method.
519#[cfg(feature = "unstable_auth_methods")]
520#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
521#[serde(rename_all = "camelCase")]
522#[non_exhaustive]
523pub struct AuthEnvVar {
524    /// The environment variable name (e.g. `"OPENAI_API_KEY"`).
525    pub name: String,
526    /// Human-readable label for this variable, displayed in client UI.
527    #[serde(skip_serializing_if = "Option::is_none")]
528    pub label: Option<String>,
529    /// Whether this value is a secret (e.g. API key, token).
530    /// Clients should use a password-style input for secret vars.
531    ///
532    /// Defaults to `true`.
533    #[serde(default = "default_true", skip_serializing_if = "is_true")]
534    #[schemars(extend("default" = true))]
535    pub secret: bool,
536    /// Whether this variable is optional.
537    ///
538    /// Defaults to `false`.
539    #[serde(default, skip_serializing_if = "is_false")]
540    #[schemars(extend("default" = false))]
541    pub optional: bool,
542    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
543    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
544    /// these keys.
545    ///
546    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
547    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
548    pub meta: Option<Meta>,
549}
550
551#[cfg(feature = "unstable_auth_methods")]
552fn default_true() -> bool {
553    true
554}
555
556#[cfg(feature = "unstable_auth_methods")]
557#[expect(clippy::trivially_copy_pass_by_ref)]
558fn is_true(v: &bool) -> bool {
559    *v
560}
561
562#[cfg(feature = "unstable_auth_methods")]
563#[expect(clippy::trivially_copy_pass_by_ref)]
564fn is_false(v: &bool) -> bool {
565    !*v
566}
567
568#[cfg(feature = "unstable_auth_methods")]
569impl AuthEnvVar {
570    /// Creates a new auth env var.
571    #[must_use]
572    pub fn new(name: impl Into<String>) -> Self {
573        Self {
574            name: name.into(),
575            label: None,
576            secret: true,
577            optional: false,
578            meta: None,
579        }
580    }
581
582    /// Human-readable label for this variable, displayed in client UI.
583    #[must_use]
584    pub fn label(mut self, label: impl IntoOption<String>) -> Self {
585        self.label = label.into_option();
586        self
587    }
588
589    /// Whether this value is a secret (e.g. API key, token).
590    /// Clients should use a password-style input for secret vars.
591    #[must_use]
592    pub fn secret(mut self, secret: bool) -> Self {
593        self.secret = secret;
594        self
595    }
596
597    /// Whether this variable is optional.
598    #[must_use]
599    pub fn optional(mut self, optional: bool) -> Self {
600        self.optional = optional;
601        self
602    }
603
604    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
605    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
606    /// these keys.
607    ///
608    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
609    #[must_use]
610    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
611        self.meta = meta.into_option();
612        self
613    }
614}
615
616/// **UNSTABLE**
617///
618/// This capability is not part of the spec yet, and may be removed or changed at any point.
619///
620/// Terminal-based authentication method.
621///
622/// The client runs an interactive terminal for the user to authenticate via a TUI.
623#[cfg(feature = "unstable_auth_methods")]
624#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
625#[serde(rename_all = "camelCase")]
626#[non_exhaustive]
627pub struct AuthMethodTerminal {
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    #[serde(skip_serializing_if = "Option::is_none")]
634    pub description: Option<String>,
635    /// Additional arguments to pass when running the agent binary for terminal auth.
636    #[serde(default, skip_serializing_if = "Vec::is_empty")]
637    pub args: Vec<String>,
638    /// Additional environment variables to set when running the agent binary for terminal auth.
639    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
640    pub env: HashMap<String, String>,
641    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
642    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
643    /// these keys.
644    ///
645    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
646    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
647    pub meta: Option<Meta>,
648}
649
650#[cfg(feature = "unstable_auth_methods")]
651impl AuthMethodTerminal {
652    #[must_use]
653    pub fn new(id: impl Into<AuthMethodId>, name: impl Into<String>) -> Self {
654        Self {
655            id: id.into(),
656            name: name.into(),
657            description: None,
658            args: Vec::new(),
659            env: HashMap::new(),
660            meta: None,
661        }
662    }
663
664    /// Additional arguments to pass when running the agent binary for terminal auth.
665    #[must_use]
666    pub fn args(mut self, args: Vec<String>) -> Self {
667        self.args = args;
668        self
669    }
670
671    /// Additional environment variables to set when running the agent binary for terminal auth.
672    #[must_use]
673    pub fn env(mut self, env: HashMap<String, String>) -> Self {
674        self.env = env;
675        self
676    }
677
678    /// Optional description providing more details about this authentication method.
679    #[must_use]
680    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
681        self.description = description.into_option();
682        self
683    }
684
685    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
686    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
687    /// these keys.
688    ///
689    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
690    #[must_use]
691    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
692        self.meta = meta.into_option();
693        self
694    }
695}
696
697// New session
698
699/// Request parameters for creating a new session.
700///
701/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
702#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
703#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
704#[serde(rename_all = "camelCase")]
705#[non_exhaustive]
706pub struct NewSessionRequest {
707    /// The working directory for this session. Must be an absolute path.
708    pub cwd: PathBuf,
709    /// List of MCP (Model Context Protocol) servers the agent should connect to.
710    pub mcp_servers: Vec<McpServer>,
711    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
712    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
713    /// these keys.
714    ///
715    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
716    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
717    pub meta: Option<Meta>,
718}
719
720impl NewSessionRequest {
721    #[must_use]
722    pub fn new(cwd: impl Into<PathBuf>) -> Self {
723        Self {
724            cwd: cwd.into(),
725            mcp_servers: vec![],
726            meta: None,
727        }
728    }
729
730    /// List of MCP (Model Context Protocol) servers the agent should connect to.
731    #[must_use]
732    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
733        self.mcp_servers = mcp_servers;
734        self
735    }
736
737    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
738    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
739    /// these keys.
740    ///
741    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
742    #[must_use]
743    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
744        self.meta = meta.into_option();
745        self
746    }
747}
748
749/// Response from creating a new session.
750///
751/// See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session)
752#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
753#[schemars(extend("x-side" = "agent", "x-method" = SESSION_NEW_METHOD_NAME))]
754#[serde(rename_all = "camelCase")]
755#[non_exhaustive]
756pub struct NewSessionResponse {
757    /// Unique identifier for the created session.
758    ///
759    /// Used in all subsequent requests for this conversation.
760    pub session_id: SessionId,
761    /// Initial mode state if supported by the Agent
762    ///
763    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
764    #[serde(skip_serializing_if = "Option::is_none")]
765    pub modes: Option<SessionModeState>,
766    /// **UNSTABLE**
767    ///
768    /// This capability is not part of the spec yet, and may be removed or changed at any point.
769    ///
770    /// Initial model state if supported by the Agent
771    #[cfg(feature = "unstable_session_model")]
772    #[serde(skip_serializing_if = "Option::is_none")]
773    pub models: Option<SessionModelState>,
774    /// Initial session configuration options if supported by the Agent.
775    #[serde(skip_serializing_if = "Option::is_none")]
776    pub config_options: Option<Vec<SessionConfigOption>>,
777    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
778    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
779    /// these keys.
780    ///
781    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
782    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
783    pub meta: Option<Meta>,
784}
785
786impl NewSessionResponse {
787    #[must_use]
788    pub fn new(session_id: impl Into<SessionId>) -> Self {
789        Self {
790            session_id: session_id.into(),
791            modes: None,
792            #[cfg(feature = "unstable_session_model")]
793            models: None,
794            config_options: None,
795            meta: None,
796        }
797    }
798
799    /// Initial mode state if supported by the Agent
800    ///
801    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
802    #[must_use]
803    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
804        self.modes = modes.into_option();
805        self
806    }
807
808    /// **UNSTABLE**
809    ///
810    /// This capability is not part of the spec yet, and may be removed or changed at any point.
811    ///
812    /// Initial model state if supported by the Agent
813    #[cfg(feature = "unstable_session_model")]
814    #[must_use]
815    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
816        self.models = models.into_option();
817        self
818    }
819
820    /// Initial session configuration options if supported by the Agent.
821    #[must_use]
822    pub fn config_options(
823        mut self,
824        config_options: impl IntoOption<Vec<SessionConfigOption>>,
825    ) -> Self {
826        self.config_options = config_options.into_option();
827        self
828    }
829
830    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
831    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
832    /// these keys.
833    ///
834    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
835    #[must_use]
836    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
837        self.meta = meta.into_option();
838        self
839    }
840}
841
842// Load session
843
844/// Request parameters for loading an existing session.
845///
846/// Only available if the Agent supports the `loadSession` capability.
847///
848/// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
849#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
850#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
851#[serde(rename_all = "camelCase")]
852#[non_exhaustive]
853pub struct LoadSessionRequest {
854    /// List of MCP servers to connect to for this session.
855    pub mcp_servers: Vec<McpServer>,
856    /// The working directory for this session.
857    pub cwd: PathBuf,
858    /// The ID of the session to load.
859    pub session_id: SessionId,
860    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
861    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
862    /// these keys.
863    ///
864    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
865    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
866    pub meta: Option<Meta>,
867}
868
869impl LoadSessionRequest {
870    #[must_use]
871    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
872        Self {
873            mcp_servers: vec![],
874            cwd: cwd.into(),
875            session_id: session_id.into(),
876            meta: None,
877        }
878    }
879
880    /// List of MCP servers to connect to for this session.
881    #[must_use]
882    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
883        self.mcp_servers = mcp_servers;
884        self
885    }
886
887    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
888    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
889    /// these keys.
890    ///
891    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
892    #[must_use]
893    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
894        self.meta = meta.into_option();
895        self
896    }
897}
898
899/// Response from loading an existing session.
900#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
901#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LOAD_METHOD_NAME))]
902#[serde(rename_all = "camelCase")]
903#[non_exhaustive]
904pub struct LoadSessionResponse {
905    /// Initial mode state if supported by the Agent
906    ///
907    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
908    #[serde(default, skip_serializing_if = "Option::is_none")]
909    pub modes: Option<SessionModeState>,
910    /// **UNSTABLE**
911    ///
912    /// This capability is not part of the spec yet, and may be removed or changed at any point.
913    ///
914    /// Initial model state if supported by the Agent
915    #[cfg(feature = "unstable_session_model")]
916    #[serde(default, skip_serializing_if = "Option::is_none")]
917    pub models: Option<SessionModelState>,
918    /// Initial session configuration options if supported by the Agent.
919    #[serde(default, skip_serializing_if = "Option::is_none")]
920    pub config_options: Option<Vec<SessionConfigOption>>,
921    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
922    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
923    /// these keys.
924    ///
925    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
926    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
927    pub meta: Option<Meta>,
928}
929
930impl LoadSessionResponse {
931    #[must_use]
932    pub fn new() -> Self {
933        Self::default()
934    }
935
936    /// Initial mode state if supported by the Agent
937    ///
938    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
939    #[must_use]
940    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
941        self.modes = modes.into_option();
942        self
943    }
944
945    /// **UNSTABLE**
946    ///
947    /// This capability is not part of the spec yet, and may be removed or changed at any point.
948    ///
949    /// Initial model state if supported by the Agent
950    #[cfg(feature = "unstable_session_model")]
951    #[must_use]
952    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
953        self.models = models.into_option();
954        self
955    }
956
957    /// Initial session configuration options if supported by the Agent.
958    #[must_use]
959    pub fn config_options(
960        mut self,
961        config_options: impl IntoOption<Vec<SessionConfigOption>>,
962    ) -> Self {
963        self.config_options = config_options.into_option();
964        self
965    }
966
967    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
968    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
969    /// these keys.
970    ///
971    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
972    #[must_use]
973    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
974        self.meta = meta.into_option();
975        self
976    }
977}
978
979// Fork session
980
981/// **UNSTABLE**
982///
983/// This capability is not part of the spec yet, and may be removed or changed at any point.
984///
985/// Request parameters for forking an existing session.
986///
987/// Creates a new session based on the context of an existing one, allowing
988/// operations like generating summaries without affecting the original session's history.
989///
990/// Only available if the Agent supports the `session.fork` capability.
991#[cfg(feature = "unstable_session_fork")]
992#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
993#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
994#[serde(rename_all = "camelCase")]
995#[non_exhaustive]
996pub struct ForkSessionRequest {
997    /// The ID of the session to fork.
998    pub session_id: SessionId,
999    /// The working directory for this session.
1000    pub cwd: PathBuf,
1001    /// List of MCP servers to connect to for this session.
1002    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1003    pub mcp_servers: Vec<McpServer>,
1004    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1005    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1006    /// these keys.
1007    ///
1008    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1009    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1010    pub meta: Option<Meta>,
1011}
1012
1013#[cfg(feature = "unstable_session_fork")]
1014impl ForkSessionRequest {
1015    #[must_use]
1016    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1017        Self {
1018            session_id: session_id.into(),
1019            cwd: cwd.into(),
1020            mcp_servers: vec![],
1021            meta: None,
1022        }
1023    }
1024
1025    /// List of MCP servers to connect to for this session.
1026    #[must_use]
1027    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1028        self.mcp_servers = mcp_servers;
1029        self
1030    }
1031
1032    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1033    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1034    /// these keys.
1035    ///
1036    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1037    #[must_use]
1038    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1039        self.meta = meta.into_option();
1040        self
1041    }
1042}
1043
1044/// **UNSTABLE**
1045///
1046/// This capability is not part of the spec yet, and may be removed or changed at any point.
1047///
1048/// Response from forking an existing session.
1049#[cfg(feature = "unstable_session_fork")]
1050#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1051#[schemars(extend("x-side" = "agent", "x-method" = SESSION_FORK_METHOD_NAME))]
1052#[serde(rename_all = "camelCase")]
1053#[non_exhaustive]
1054pub struct ForkSessionResponse {
1055    /// Unique identifier for the newly created forked session.
1056    pub session_id: SessionId,
1057    /// Initial mode state if supported by the Agent
1058    ///
1059    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1060    #[serde(skip_serializing_if = "Option::is_none")]
1061    pub modes: Option<SessionModeState>,
1062    /// **UNSTABLE**
1063    ///
1064    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1065    ///
1066    /// Initial model state if supported by the Agent
1067    #[cfg(feature = "unstable_session_model")]
1068    #[serde(skip_serializing_if = "Option::is_none")]
1069    pub models: Option<SessionModelState>,
1070    /// Initial session configuration options if supported by the Agent.
1071    #[serde(skip_serializing_if = "Option::is_none")]
1072    pub config_options: Option<Vec<SessionConfigOption>>,
1073    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1074    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1075    /// these keys.
1076    ///
1077    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1078    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1079    pub meta: Option<Meta>,
1080}
1081
1082#[cfg(feature = "unstable_session_fork")]
1083impl ForkSessionResponse {
1084    #[must_use]
1085    pub fn new(session_id: impl Into<SessionId>) -> Self {
1086        Self {
1087            session_id: session_id.into(),
1088            modes: None,
1089            #[cfg(feature = "unstable_session_model")]
1090            models: None,
1091            config_options: None,
1092            meta: None,
1093        }
1094    }
1095
1096    /// Initial mode state if supported by the Agent
1097    ///
1098    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1099    #[must_use]
1100    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1101        self.modes = modes.into_option();
1102        self
1103    }
1104
1105    /// **UNSTABLE**
1106    ///
1107    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1108    ///
1109    /// Initial model state if supported by the Agent
1110    #[cfg(feature = "unstable_session_model")]
1111    #[must_use]
1112    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1113        self.models = models.into_option();
1114        self
1115    }
1116
1117    /// Initial session configuration options if supported by the Agent.
1118    #[must_use]
1119    pub fn config_options(
1120        mut self,
1121        config_options: impl IntoOption<Vec<SessionConfigOption>>,
1122    ) -> Self {
1123        self.config_options = config_options.into_option();
1124        self
1125    }
1126
1127    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1128    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1129    /// these keys.
1130    ///
1131    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1132    #[must_use]
1133    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1134        self.meta = meta.into_option();
1135        self
1136    }
1137}
1138
1139// Resume session
1140
1141/// **UNSTABLE**
1142///
1143/// This capability is not part of the spec yet, and may be removed or changed at any point.
1144///
1145/// Request parameters for resuming an existing session.
1146///
1147/// Resumes an existing session without returning previous messages (unlike `session/load`).
1148/// This is useful for agents that can resume sessions but don't implement full session loading.
1149///
1150/// Only available if the Agent supports the `session.resume` capability.
1151#[cfg(feature = "unstable_session_resume")]
1152#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1153#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1154#[serde(rename_all = "camelCase")]
1155#[non_exhaustive]
1156pub struct ResumeSessionRequest {
1157    /// The ID of the session to resume.
1158    pub session_id: SessionId,
1159    /// The working directory for this session.
1160    pub cwd: PathBuf,
1161    /// List of MCP servers to connect to for this session.
1162    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1163    pub mcp_servers: Vec<McpServer>,
1164    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1165    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1166    /// these keys.
1167    ///
1168    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1169    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1170    pub meta: Option<Meta>,
1171}
1172
1173#[cfg(feature = "unstable_session_resume")]
1174impl ResumeSessionRequest {
1175    #[must_use]
1176    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1177        Self {
1178            session_id: session_id.into(),
1179            cwd: cwd.into(),
1180            mcp_servers: vec![],
1181            meta: None,
1182        }
1183    }
1184
1185    /// List of MCP servers to connect to for this session.
1186    #[must_use]
1187    pub fn mcp_servers(mut self, mcp_servers: Vec<McpServer>) -> Self {
1188        self.mcp_servers = mcp_servers;
1189        self
1190    }
1191
1192    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1193    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1194    /// these keys.
1195    ///
1196    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1197    #[must_use]
1198    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1199        self.meta = meta.into_option();
1200        self
1201    }
1202}
1203
1204/// **UNSTABLE**
1205///
1206/// This capability is not part of the spec yet, and may be removed or changed at any point.
1207///
1208/// Response from resuming an existing session.
1209#[cfg(feature = "unstable_session_resume")]
1210#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1211#[schemars(extend("x-side" = "agent", "x-method" = SESSION_RESUME_METHOD_NAME))]
1212#[serde(rename_all = "camelCase")]
1213#[non_exhaustive]
1214pub struct ResumeSessionResponse {
1215    /// Initial mode state if supported by the Agent
1216    ///
1217    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1218    #[serde(default, skip_serializing_if = "Option::is_none")]
1219    pub modes: Option<SessionModeState>,
1220    /// **UNSTABLE**
1221    ///
1222    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1223    ///
1224    /// Initial model state if supported by the Agent
1225    #[cfg(feature = "unstable_session_model")]
1226    #[serde(default, skip_serializing_if = "Option::is_none")]
1227    pub models: Option<SessionModelState>,
1228    /// Initial session configuration options if supported by the Agent.
1229    #[serde(default, skip_serializing_if = "Option::is_none")]
1230    pub config_options: Option<Vec<SessionConfigOption>>,
1231    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1232    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1233    /// these keys.
1234    ///
1235    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1236    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1237    pub meta: Option<Meta>,
1238}
1239
1240#[cfg(feature = "unstable_session_resume")]
1241impl ResumeSessionResponse {
1242    #[must_use]
1243    pub fn new() -> Self {
1244        Self::default()
1245    }
1246
1247    /// Initial mode state if supported by the Agent
1248    ///
1249    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1250    #[must_use]
1251    pub fn modes(mut self, modes: impl IntoOption<SessionModeState>) -> Self {
1252        self.modes = modes.into_option();
1253        self
1254    }
1255
1256    /// **UNSTABLE**
1257    ///
1258    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1259    ///
1260    /// Initial model state if supported by the Agent
1261    #[cfg(feature = "unstable_session_model")]
1262    #[must_use]
1263    pub fn models(mut self, models: impl IntoOption<SessionModelState>) -> Self {
1264        self.models = models.into_option();
1265        self
1266    }
1267
1268    /// Initial session configuration options if supported by the Agent.
1269    #[must_use]
1270    pub fn config_options(
1271        mut self,
1272        config_options: impl IntoOption<Vec<SessionConfigOption>>,
1273    ) -> Self {
1274        self.config_options = config_options.into_option();
1275        self
1276    }
1277
1278    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1279    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1280    /// these keys.
1281    ///
1282    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1283    #[must_use]
1284    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1285        self.meta = meta.into_option();
1286        self
1287    }
1288}
1289
1290// Stop session
1291
1292/// **UNSTABLE**
1293///
1294/// This capability is not part of the spec yet, and may be removed or changed at any point.
1295///
1296/// Request parameters for stopping an active session.
1297///
1298/// If supported, the agent **must** cancel any ongoing work related to the session
1299/// (treat it as if `session/cancel` was called) and then free up any resources
1300/// associated with the session.
1301///
1302/// Only available if the Agent supports the `session.stop` capability.
1303#[cfg(feature = "unstable_session_stop")]
1304#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1305#[schemars(extend("x-side" = "agent", "x-method" = SESSION_STOP_METHOD_NAME))]
1306#[serde(rename_all = "camelCase")]
1307#[non_exhaustive]
1308pub struct StopSessionRequest {
1309    /// The ID of the session to stop.
1310    pub session_id: SessionId,
1311    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1312    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1313    /// these keys.
1314    ///
1315    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1316    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1317    pub meta: Option<Meta>,
1318}
1319
1320#[cfg(feature = "unstable_session_stop")]
1321impl StopSessionRequest {
1322    #[must_use]
1323    pub fn new(session_id: impl Into<SessionId>) -> Self {
1324        Self {
1325            session_id: session_id.into(),
1326            meta: None,
1327        }
1328    }
1329
1330    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1331    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1332    /// these keys.
1333    ///
1334    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1335    #[must_use]
1336    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1337        self.meta = meta.into_option();
1338        self
1339    }
1340}
1341
1342/// **UNSTABLE**
1343///
1344/// This capability is not part of the spec yet, and may be removed or changed at any point.
1345///
1346/// Response from stopping a session.
1347#[cfg(feature = "unstable_session_stop")]
1348#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1349#[schemars(extend("x-side" = "agent", "x-method" = SESSION_STOP_METHOD_NAME))]
1350#[serde(rename_all = "camelCase")]
1351#[non_exhaustive]
1352pub struct StopSessionResponse {
1353    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1354    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1355    /// these keys.
1356    ///
1357    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1358    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1359    pub meta: Option<Meta>,
1360}
1361
1362#[cfg(feature = "unstable_session_stop")]
1363impl StopSessionResponse {
1364    #[must_use]
1365    pub fn new() -> Self {
1366        Self::default()
1367    }
1368
1369    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1370    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1371    /// these keys.
1372    ///
1373    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1374    #[must_use]
1375    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1376        self.meta = meta.into_option();
1377        self
1378    }
1379}
1380
1381// List sessions
1382
1383/// **UNSTABLE**
1384///
1385/// This capability is not part of the spec yet, and may be removed or changed at any point.
1386///
1387/// Request parameters for listing existing sessions.
1388///
1389/// Only available if the Agent supports the `listSessions` capability.
1390#[cfg(feature = "unstable_session_list")]
1391#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1392#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1393#[serde(rename_all = "camelCase")]
1394#[non_exhaustive]
1395pub struct ListSessionsRequest {
1396    /// Filter sessions by working directory. Must be an absolute path.
1397    #[serde(skip_serializing_if = "Option::is_none")]
1398    pub cwd: Option<PathBuf>,
1399    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
1400    #[serde(skip_serializing_if = "Option::is_none")]
1401    pub cursor: Option<String>,
1402    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1403    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1404    /// these keys.
1405    ///
1406    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1407    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1408    pub meta: Option<Meta>,
1409}
1410
1411#[cfg(feature = "unstable_session_list")]
1412impl ListSessionsRequest {
1413    #[must_use]
1414    pub fn new() -> Self {
1415        Self::default()
1416    }
1417
1418    /// Filter sessions by working directory. Must be an absolute path.
1419    #[must_use]
1420    pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1421        self.cwd = cwd.into_option();
1422        self
1423    }
1424
1425    /// Opaque cursor token from a previous response's nextCursor field for cursor-based pagination
1426    #[must_use]
1427    pub fn cursor(mut self, cursor: impl IntoOption<String>) -> Self {
1428        self.cursor = cursor.into_option();
1429        self
1430    }
1431
1432    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1433    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1434    /// these keys.
1435    ///
1436    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1437    #[must_use]
1438    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1439        self.meta = meta.into_option();
1440        self
1441    }
1442}
1443
1444/// **UNSTABLE**
1445///
1446/// This capability is not part of the spec yet, and may be removed or changed at any point.
1447///
1448/// Response from listing sessions.
1449#[cfg(feature = "unstable_session_list")]
1450#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1451#[schemars(extend("x-side" = "agent", "x-method" = SESSION_LIST_METHOD_NAME))]
1452#[serde(rename_all = "camelCase")]
1453#[non_exhaustive]
1454pub struct ListSessionsResponse {
1455    /// Array of session information objects
1456    pub sessions: Vec<SessionInfo>,
1457    /// Opaque cursor token. If present, pass this in the next request's cursor parameter
1458    /// to fetch the next page. If absent, there are no more results.
1459    #[serde(skip_serializing_if = "Option::is_none")]
1460    pub next_cursor: Option<String>,
1461    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1462    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1463    /// these keys.
1464    ///
1465    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1466    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1467    pub meta: Option<Meta>,
1468}
1469
1470#[cfg(feature = "unstable_session_list")]
1471impl ListSessionsResponse {
1472    #[must_use]
1473    pub fn new(sessions: Vec<SessionInfo>) -> Self {
1474        Self {
1475            sessions,
1476            next_cursor: None,
1477            meta: None,
1478        }
1479    }
1480
1481    #[must_use]
1482    pub fn next_cursor(mut self, next_cursor: impl IntoOption<String>) -> Self {
1483        self.next_cursor = next_cursor.into_option();
1484        self
1485    }
1486
1487    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1488    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1489    /// these keys.
1490    ///
1491    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1492    #[must_use]
1493    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1494        self.meta = meta.into_option();
1495        self
1496    }
1497}
1498
1499/// **UNSTABLE**
1500///
1501/// This capability is not part of the spec yet, and may be removed or changed at any point.
1502///
1503/// Information about a session returned by session/list
1504#[cfg(feature = "unstable_session_list")]
1505#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1506#[serde(rename_all = "camelCase")]
1507#[non_exhaustive]
1508pub struct SessionInfo {
1509    /// Unique identifier for the session
1510    pub session_id: SessionId,
1511    /// The working directory for this session. Must be an absolute path.
1512    pub cwd: PathBuf,
1513    /// Human-readable title for the session
1514    #[serde(skip_serializing_if = "Option::is_none")]
1515    pub title: Option<String>,
1516    /// ISO 8601 timestamp of last activity
1517    #[serde(skip_serializing_if = "Option::is_none")]
1518    pub updated_at: Option<String>,
1519    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1520    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1521    /// these keys.
1522    ///
1523    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1524    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1525    pub meta: Option<Meta>,
1526}
1527
1528#[cfg(feature = "unstable_session_list")]
1529impl SessionInfo {
1530    #[must_use]
1531    pub fn new(session_id: impl Into<SessionId>, cwd: impl Into<PathBuf>) -> Self {
1532        Self {
1533            session_id: session_id.into(),
1534            cwd: cwd.into(),
1535            title: None,
1536            updated_at: None,
1537            meta: None,
1538        }
1539    }
1540
1541    /// Human-readable title for the session
1542    #[must_use]
1543    pub fn title(mut self, title: impl IntoOption<String>) -> Self {
1544        self.title = title.into_option();
1545        self
1546    }
1547
1548    /// ISO 8601 timestamp of last activity
1549    #[must_use]
1550    pub fn updated_at(mut self, updated_at: impl IntoOption<String>) -> Self {
1551        self.updated_at = updated_at.into_option();
1552        self
1553    }
1554
1555    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1556    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1557    /// these keys.
1558    ///
1559    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1560    #[must_use]
1561    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1562        self.meta = meta.into_option();
1563        self
1564    }
1565}
1566
1567// Session modes
1568
1569/// The set of modes and the one currently active.
1570#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1571#[serde(rename_all = "camelCase")]
1572#[non_exhaustive]
1573pub struct SessionModeState {
1574    /// The current mode the Agent is in.
1575    pub current_mode_id: SessionModeId,
1576    /// The set of modes that the Agent can operate in
1577    pub available_modes: Vec<SessionMode>,
1578    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1579    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1580    /// these keys.
1581    ///
1582    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1583    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1584    pub meta: Option<Meta>,
1585}
1586
1587impl SessionModeState {
1588    #[must_use]
1589    pub fn new(
1590        current_mode_id: impl Into<SessionModeId>,
1591        available_modes: Vec<SessionMode>,
1592    ) -> Self {
1593        Self {
1594            current_mode_id: current_mode_id.into(),
1595            available_modes,
1596            meta: None,
1597        }
1598    }
1599
1600    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1601    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1602    /// these keys.
1603    ///
1604    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1605    #[must_use]
1606    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1607        self.meta = meta.into_option();
1608        self
1609    }
1610}
1611
1612/// A mode the agent can operate in.
1613///
1614/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
1615#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1616#[serde(rename_all = "camelCase")]
1617#[non_exhaustive]
1618pub struct SessionMode {
1619    pub id: SessionModeId,
1620    pub name: String,
1621    #[serde(default, skip_serializing_if = "Option::is_none")]
1622    pub description: Option<String>,
1623    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1624    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1625    /// these keys.
1626    ///
1627    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1628    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1629    pub meta: Option<Meta>,
1630}
1631
1632impl SessionMode {
1633    #[must_use]
1634    pub fn new(id: impl Into<SessionModeId>, name: impl Into<String>) -> Self {
1635        Self {
1636            id: id.into(),
1637            name: name.into(),
1638            description: None,
1639            meta: None,
1640        }
1641    }
1642
1643    #[must_use]
1644    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1645        self.description = description.into_option();
1646        self
1647    }
1648
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    #[must_use]
1655    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1656        self.meta = meta.into_option();
1657        self
1658    }
1659}
1660
1661/// Unique identifier for a Session Mode.
1662#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1663#[serde(transparent)]
1664#[from(Arc<str>, String, &'static str)]
1665#[non_exhaustive]
1666pub struct SessionModeId(pub Arc<str>);
1667
1668impl SessionModeId {
1669    #[must_use]
1670    pub fn new(id: impl Into<Arc<str>>) -> Self {
1671        Self(id.into())
1672    }
1673}
1674
1675/// Request parameters for setting a session mode.
1676#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1677#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
1678#[serde(rename_all = "camelCase")]
1679#[non_exhaustive]
1680pub struct SetSessionModeRequest {
1681    /// The ID of the session to set the mode for.
1682    pub session_id: SessionId,
1683    /// The ID of the mode to set.
1684    pub mode_id: SessionModeId,
1685    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1686    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1687    /// these keys.
1688    ///
1689    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1690    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1691    pub meta: Option<Meta>,
1692}
1693
1694impl SetSessionModeRequest {
1695    #[must_use]
1696    pub fn new(session_id: impl Into<SessionId>, mode_id: impl Into<SessionModeId>) -> Self {
1697        Self {
1698            session_id: session_id.into(),
1699            mode_id: mode_id.into(),
1700            meta: None,
1701        }
1702    }
1703
1704    #[must_use]
1705    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1706        self.meta = meta.into_option();
1707        self
1708    }
1709}
1710
1711/// Response to `session/set_mode` method.
1712#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1713#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODE_METHOD_NAME))]
1714#[serde(rename_all = "camelCase")]
1715#[non_exhaustive]
1716pub struct SetSessionModeResponse {
1717    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1718    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1719    /// these keys.
1720    ///
1721    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1722    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1723    pub meta: Option<Meta>,
1724}
1725
1726impl SetSessionModeResponse {
1727    #[must_use]
1728    pub fn new() -> Self {
1729        Self::default()
1730    }
1731
1732    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1733    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1734    /// these keys.
1735    ///
1736    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1737    #[must_use]
1738    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1739        self.meta = meta.into_option();
1740        self
1741    }
1742}
1743
1744// Session config options
1745
1746/// Unique identifier for a session configuration option.
1747#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1748#[serde(transparent)]
1749#[from(Arc<str>, String, &'static str)]
1750#[non_exhaustive]
1751pub struct SessionConfigId(pub Arc<str>);
1752
1753impl SessionConfigId {
1754    #[must_use]
1755    pub fn new(id: impl Into<Arc<str>>) -> Self {
1756        Self(id.into())
1757    }
1758}
1759
1760/// Unique identifier for a session configuration option value.
1761#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1762#[serde(transparent)]
1763#[from(Arc<str>, String, &'static str)]
1764#[non_exhaustive]
1765pub struct SessionConfigValueId(pub Arc<str>);
1766
1767impl SessionConfigValueId {
1768    #[must_use]
1769    pub fn new(id: impl Into<Arc<str>>) -> Self {
1770        Self(id.into())
1771    }
1772}
1773
1774/// Unique identifier for a session configuration option value group.
1775#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, From, Display)]
1776#[serde(transparent)]
1777#[from(Arc<str>, String, &'static str)]
1778#[non_exhaustive]
1779pub struct SessionConfigGroupId(pub Arc<str>);
1780
1781impl SessionConfigGroupId {
1782    #[must_use]
1783    pub fn new(id: impl Into<Arc<str>>) -> Self {
1784        Self(id.into())
1785    }
1786}
1787
1788/// A possible value for a session configuration option.
1789#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1790#[serde(rename_all = "camelCase")]
1791#[non_exhaustive]
1792pub struct SessionConfigSelectOption {
1793    /// Unique identifier for this option value.
1794    pub value: SessionConfigValueId,
1795    /// Human-readable label for this option value.
1796    pub name: String,
1797    /// Optional description for this option value.
1798    #[serde(default, skip_serializing_if = "Option::is_none")]
1799    pub description: Option<String>,
1800    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1801    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1802    /// these keys.
1803    ///
1804    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1805    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1806    pub meta: Option<Meta>,
1807}
1808
1809impl SessionConfigSelectOption {
1810    #[must_use]
1811    pub fn new(value: impl Into<SessionConfigValueId>, name: impl Into<String>) -> Self {
1812        Self {
1813            value: value.into(),
1814            name: name.into(),
1815            description: None,
1816            meta: None,
1817        }
1818    }
1819
1820    #[must_use]
1821    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
1822        self.description = description.into_option();
1823        self
1824    }
1825
1826    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1827    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1828    /// these keys.
1829    ///
1830    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1831    #[must_use]
1832    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1833        self.meta = meta.into_option();
1834        self
1835    }
1836}
1837
1838/// A group of possible values for a session configuration option.
1839#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1840#[serde(rename_all = "camelCase")]
1841#[non_exhaustive]
1842pub struct SessionConfigSelectGroup {
1843    /// Unique identifier for this group.
1844    pub group: SessionConfigGroupId,
1845    /// Human-readable label for this group.
1846    pub name: String,
1847    /// The set of option values in this group.
1848    pub options: Vec<SessionConfigSelectOption>,
1849    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1850    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1851    /// these keys.
1852    ///
1853    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1854    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1855    pub meta: Option<Meta>,
1856}
1857
1858impl SessionConfigSelectGroup {
1859    #[must_use]
1860    pub fn new(
1861        group: impl Into<SessionConfigGroupId>,
1862        name: impl Into<String>,
1863        options: Vec<SessionConfigSelectOption>,
1864    ) -> Self {
1865        Self {
1866            group: group.into(),
1867            name: name.into(),
1868            options,
1869            meta: None,
1870        }
1871    }
1872
1873    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1874    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1875    /// these keys.
1876    ///
1877    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1878    #[must_use]
1879    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1880        self.meta = meta.into_option();
1881        self
1882    }
1883}
1884
1885/// Possible values for a session configuration option.
1886#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1887#[serde(untagged)]
1888#[non_exhaustive]
1889pub enum SessionConfigSelectOptions {
1890    /// A flat list of options with no grouping.
1891    Ungrouped(Vec<SessionConfigSelectOption>),
1892    /// A list of options grouped under headers.
1893    Grouped(Vec<SessionConfigSelectGroup>),
1894}
1895
1896impl From<Vec<SessionConfigSelectOption>> for SessionConfigSelectOptions {
1897    fn from(options: Vec<SessionConfigSelectOption>) -> Self {
1898        SessionConfigSelectOptions::Ungrouped(options)
1899    }
1900}
1901
1902impl From<Vec<SessionConfigSelectGroup>> for SessionConfigSelectOptions {
1903    fn from(groups: Vec<SessionConfigSelectGroup>) -> Self {
1904        SessionConfigSelectOptions::Grouped(groups)
1905    }
1906}
1907
1908/// A single-value selector (dropdown) session configuration option payload.
1909#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1910#[serde(rename_all = "camelCase")]
1911#[non_exhaustive]
1912pub struct SessionConfigSelect {
1913    /// The currently selected value.
1914    pub current_value: SessionConfigValueId,
1915    /// The set of selectable options.
1916    pub options: SessionConfigSelectOptions,
1917}
1918
1919impl SessionConfigSelect {
1920    #[must_use]
1921    pub fn new(
1922        current_value: impl Into<SessionConfigValueId>,
1923        options: impl Into<SessionConfigSelectOptions>,
1924    ) -> Self {
1925        Self {
1926            current_value: current_value.into(),
1927            options: options.into(),
1928        }
1929    }
1930}
1931
1932/// Semantic category for a session configuration option.
1933///
1934/// This is intended to help Clients distinguish broadly common selectors (e.g. model selector vs
1935/// session mode selector vs thought/reasoning level) for UX purposes (keyboard shortcuts, icons,
1936/// placement). It MUST NOT be required for correctness. Clients MUST handle missing or unknown
1937/// categories gracefully.
1938///
1939/// Category names beginning with `_` are free for custom use, like other ACP extension methods.
1940/// Category names that do not begin with `_` are reserved for the ACP spec.
1941#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1942#[serde(rename_all = "snake_case")]
1943#[non_exhaustive]
1944pub enum SessionConfigOptionCategory {
1945    /// Session mode selector.
1946    Mode,
1947    /// Model selector.
1948    Model,
1949    /// Thought/reasoning level selector.
1950    ThoughtLevel,
1951    /// Unknown / uncategorized selector.
1952    #[serde(untagged)]
1953    Other(String),
1954}
1955
1956/// Type-specific session configuration option payload.
1957#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1958#[serde(tag = "type", rename_all = "snake_case")]
1959#[schemars(extend("discriminator" = {"propertyName": "type"}))]
1960#[non_exhaustive]
1961pub enum SessionConfigKind {
1962    /// Single-value selector (dropdown).
1963    Select(SessionConfigSelect),
1964}
1965
1966/// A session configuration option selector and its current state.
1967#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1968#[serde(rename_all = "camelCase")]
1969#[non_exhaustive]
1970pub struct SessionConfigOption {
1971    /// Unique identifier for the configuration option.
1972    pub id: SessionConfigId,
1973    /// Human-readable label for the option.
1974    pub name: String,
1975    /// Optional description for the Client to display to the user.
1976    #[serde(default, skip_serializing_if = "Option::is_none")]
1977    pub description: Option<String>,
1978    /// Optional semantic category for this option (UX only).
1979    #[serde(default, skip_serializing_if = "Option::is_none")]
1980    pub category: Option<SessionConfigOptionCategory>,
1981    /// Type-specific fields for this configuration option.
1982    #[serde(flatten)]
1983    pub kind: SessionConfigKind,
1984    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1985    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1986    /// these keys.
1987    ///
1988    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1989    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
1990    pub meta: Option<Meta>,
1991}
1992
1993impl SessionConfigOption {
1994    #[must_use]
1995    pub fn new(
1996        id: impl Into<SessionConfigId>,
1997        name: impl Into<String>,
1998        kind: SessionConfigKind,
1999    ) -> Self {
2000        Self {
2001            id: id.into(),
2002            name: name.into(),
2003            description: None,
2004            category: None,
2005            kind,
2006            meta: None,
2007        }
2008    }
2009
2010    #[must_use]
2011    pub fn select(
2012        id: impl Into<SessionConfigId>,
2013        name: impl Into<String>,
2014        current_value: impl Into<SessionConfigValueId>,
2015        options: impl Into<SessionConfigSelectOptions>,
2016    ) -> Self {
2017        Self::new(
2018            id,
2019            name,
2020            SessionConfigKind::Select(SessionConfigSelect::new(current_value, options)),
2021        )
2022    }
2023
2024    #[must_use]
2025    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2026        self.description = description.into_option();
2027        self
2028    }
2029
2030    #[must_use]
2031    pub fn category(mut self, category: impl IntoOption<SessionConfigOptionCategory>) -> Self {
2032        self.category = category.into_option();
2033        self
2034    }
2035
2036    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2037    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2038    /// these keys.
2039    ///
2040    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2041    #[must_use]
2042    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2043        self.meta = meta.into_option();
2044        self
2045    }
2046}
2047
2048/// Request parameters for setting a session configuration option.
2049#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2050#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2051#[serde(rename_all = "camelCase")]
2052#[non_exhaustive]
2053pub struct SetSessionConfigOptionRequest {
2054    /// The ID of the session to set the configuration option for.
2055    pub session_id: SessionId,
2056    /// The ID of the configuration option to set.
2057    pub config_id: SessionConfigId,
2058    /// The ID of the configuration option value to set.
2059    pub value: SessionConfigValueId,
2060    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2061    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2062    /// these keys.
2063    ///
2064    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2065    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2066    pub meta: Option<Meta>,
2067}
2068
2069impl SetSessionConfigOptionRequest {
2070    #[must_use]
2071    pub fn new(
2072        session_id: impl Into<SessionId>,
2073        config_id: impl Into<SessionConfigId>,
2074        value: impl Into<SessionConfigValueId>,
2075    ) -> Self {
2076        Self {
2077            session_id: session_id.into(),
2078            config_id: config_id.into(),
2079            value: value.into(),
2080            meta: None,
2081        }
2082    }
2083
2084    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2085    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2086    /// these keys.
2087    ///
2088    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2089    #[must_use]
2090    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2091        self.meta = meta.into_option();
2092        self
2093    }
2094}
2095
2096/// Response to `session/set_config_option` method.
2097#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2098#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_CONFIG_OPTION_METHOD_NAME))]
2099#[serde(rename_all = "camelCase")]
2100#[non_exhaustive]
2101pub struct SetSessionConfigOptionResponse {
2102    /// The full set of configuration options and their current values.
2103    pub config_options: Vec<SessionConfigOption>,
2104    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2105    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2106    /// these keys.
2107    ///
2108    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2109    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2110    pub meta: Option<Meta>,
2111}
2112
2113impl SetSessionConfigOptionResponse {
2114    #[must_use]
2115    pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
2116        Self {
2117            config_options,
2118            meta: None,
2119        }
2120    }
2121
2122    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2123    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2124    /// these keys.
2125    ///
2126    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2127    #[must_use]
2128    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2129        self.meta = meta.into_option();
2130        self
2131    }
2132}
2133
2134// MCP
2135
2136/// Configuration for connecting to an MCP (Model Context Protocol) server.
2137///
2138/// MCP servers provide tools and context that the agent can use when
2139/// processing prompts.
2140///
2141/// See protocol docs: [MCP Servers](https://agentclientprotocol.com/protocol/session-setup#mcp-servers)
2142#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2143#[serde(tag = "type", rename_all = "snake_case")]
2144#[non_exhaustive]
2145pub enum McpServer {
2146    /// HTTP transport configuration
2147    ///
2148    /// Only available when the Agent capabilities indicate `mcp_capabilities.http` is `true`.
2149    Http(McpServerHttp),
2150    /// SSE transport configuration
2151    ///
2152    /// Only available when the Agent capabilities indicate `mcp_capabilities.sse` is `true`.
2153    Sse(McpServerSse),
2154    /// Stdio transport configuration
2155    ///
2156    /// All Agents MUST support this transport.
2157    #[serde(untagged)]
2158    Stdio(McpServerStdio),
2159}
2160
2161/// HTTP transport configuration for MCP.
2162#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2163#[serde(rename_all = "camelCase")]
2164#[non_exhaustive]
2165pub struct McpServerHttp {
2166    /// Human-readable name identifying this MCP server.
2167    pub name: String,
2168    /// URL to the MCP server.
2169    pub url: String,
2170    /// HTTP headers to set when making requests to the MCP server.
2171    pub headers: Vec<HttpHeader>,
2172    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2173    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2174    /// these keys.
2175    ///
2176    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2177    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2178    pub meta: Option<Meta>,
2179}
2180
2181impl McpServerHttp {
2182    #[must_use]
2183    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2184        Self {
2185            name: name.into(),
2186            url: url.into(),
2187            headers: Vec::new(),
2188            meta: None,
2189        }
2190    }
2191
2192    /// HTTP headers to set when making requests to the MCP server.
2193    #[must_use]
2194    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2195        self.headers = headers;
2196        self
2197    }
2198
2199    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2200    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2201    /// these keys.
2202    ///
2203    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2204    #[must_use]
2205    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2206        self.meta = meta.into_option();
2207        self
2208    }
2209}
2210
2211/// SSE transport configuration for MCP.
2212#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2213#[serde(rename_all = "camelCase")]
2214#[non_exhaustive]
2215pub struct McpServerSse {
2216    /// Human-readable name identifying this MCP server.
2217    pub name: String,
2218    /// URL to the MCP server.
2219    pub url: String,
2220    /// HTTP headers to set when making requests to the MCP server.
2221    pub headers: Vec<HttpHeader>,
2222    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2223    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2224    /// these keys.
2225    ///
2226    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2227    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2228    pub meta: Option<Meta>,
2229}
2230
2231impl McpServerSse {
2232    #[must_use]
2233    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
2234        Self {
2235            name: name.into(),
2236            url: url.into(),
2237            headers: Vec::new(),
2238            meta: None,
2239        }
2240    }
2241
2242    /// HTTP headers to set when making requests to the MCP server.
2243    #[must_use]
2244    pub fn headers(mut self, headers: Vec<HttpHeader>) -> Self {
2245        self.headers = headers;
2246        self
2247    }
2248
2249    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2250    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2251    /// these keys.
2252    ///
2253    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2254    #[must_use]
2255    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2256        self.meta = meta.into_option();
2257        self
2258    }
2259}
2260
2261/// Stdio transport configuration for MCP.
2262#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2263#[serde(rename_all = "camelCase")]
2264#[non_exhaustive]
2265pub struct McpServerStdio {
2266    /// Human-readable name identifying this MCP server.
2267    pub name: String,
2268    /// Path to the MCP server executable.
2269    pub command: PathBuf,
2270    /// Command-line arguments to pass to the MCP server.
2271    pub args: Vec<String>,
2272    /// Environment variables to set when launching the MCP server.
2273    pub env: Vec<EnvVariable>,
2274    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2275    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2276    /// these keys.
2277    ///
2278    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2279    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2280    pub meta: Option<Meta>,
2281}
2282
2283impl McpServerStdio {
2284    #[must_use]
2285    pub fn new(name: impl Into<String>, command: impl Into<PathBuf>) -> Self {
2286        Self {
2287            name: name.into(),
2288            command: command.into(),
2289            args: Vec::new(),
2290            env: Vec::new(),
2291            meta: None,
2292        }
2293    }
2294
2295    /// Command-line arguments to pass to the MCP server.
2296    #[must_use]
2297    pub fn args(mut self, args: Vec<String>) -> Self {
2298        self.args = args;
2299        self
2300    }
2301
2302    /// Environment variables to set when launching the MCP server.
2303    #[must_use]
2304    pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
2305        self.env = env;
2306        self
2307    }
2308
2309    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2310    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2311    /// these keys.
2312    ///
2313    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2314    #[must_use]
2315    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2316        self.meta = meta.into_option();
2317        self
2318    }
2319}
2320
2321/// An environment variable to set when launching an MCP server.
2322#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2323#[serde(rename_all = "camelCase")]
2324#[non_exhaustive]
2325pub struct EnvVariable {
2326    /// The name of the environment variable.
2327    pub name: String,
2328    /// The value to set for the environment variable.
2329    pub value: String,
2330    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2331    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2332    /// these keys.
2333    ///
2334    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2335    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2336    pub meta: Option<Meta>,
2337}
2338
2339impl EnvVariable {
2340    #[must_use]
2341    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2342        Self {
2343            name: name.into(),
2344            value: value.into(),
2345            meta: None,
2346        }
2347    }
2348
2349    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2350    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2351    /// these keys.
2352    ///
2353    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2354    #[must_use]
2355    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2356        self.meta = meta.into_option();
2357        self
2358    }
2359}
2360
2361/// An HTTP header to set when making requests to the MCP server.
2362#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2363#[serde(rename_all = "camelCase")]
2364#[non_exhaustive]
2365pub struct HttpHeader {
2366    /// The name of the HTTP header.
2367    pub name: String,
2368    /// The value to set for the HTTP header.
2369    pub value: String,
2370    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2371    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2372    /// these keys.
2373    ///
2374    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2375    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2376    pub meta: Option<Meta>,
2377}
2378
2379impl HttpHeader {
2380    #[must_use]
2381    pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
2382        Self {
2383            name: name.into(),
2384            value: value.into(),
2385            meta: None,
2386        }
2387    }
2388
2389    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2390    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2391    /// these keys.
2392    ///
2393    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2394    #[must_use]
2395    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2396        self.meta = meta.into_option();
2397        self
2398    }
2399}
2400
2401// Prompt
2402
2403/// Request parameters for sending a user prompt to the agent.
2404///
2405/// Contains the user's message and any additional context.
2406///
2407/// See protocol docs: [User Message](https://agentclientprotocol.com/protocol/prompt-turn#1-user-message)
2408#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
2409#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
2410#[serde(rename_all = "camelCase")]
2411#[non_exhaustive]
2412pub struct PromptRequest {
2413    /// The ID of the session to send this user message to
2414    pub session_id: SessionId,
2415    /// **UNSTABLE**
2416    ///
2417    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2418    ///
2419    /// A client-generated unique identifier for this user message.
2420    ///
2421    /// If provided, the Agent SHOULD echo this value as `userMessageId` in the
2422    /// [`PromptResponse`] to confirm it was recorded.
2423    /// Both clients and agents MUST use UUID format for message IDs.
2424    #[cfg(feature = "unstable_message_id")]
2425    #[serde(skip_serializing_if = "Option::is_none")]
2426    pub message_id: Option<String>,
2427    /// The blocks of content that compose the user's message.
2428    ///
2429    /// As a baseline, the Agent MUST support [`ContentBlock::Text`] and [`ContentBlock::ResourceLink`],
2430    /// while other variants are optionally enabled via [`PromptCapabilities`].
2431    ///
2432    /// The Client MUST adapt its interface according to [`PromptCapabilities`].
2433    ///
2434    /// The client MAY include referenced pieces of context as either
2435    /// [`ContentBlock::Resource`] or [`ContentBlock::ResourceLink`].
2436    ///
2437    /// When available, [`ContentBlock::Resource`] is preferred
2438    /// as it avoids extra round-trips and allows the message to include
2439    /// pieces of context from sources the agent may not have access to.
2440    pub prompt: Vec<ContentBlock>,
2441    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2442    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2443    /// these keys.
2444    ///
2445    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2446    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2447    pub meta: Option<Meta>,
2448}
2449
2450impl PromptRequest {
2451    #[must_use]
2452    pub fn new(session_id: impl Into<SessionId>, prompt: Vec<ContentBlock>) -> Self {
2453        Self {
2454            session_id: session_id.into(),
2455            #[cfg(feature = "unstable_message_id")]
2456            message_id: None,
2457            prompt,
2458            meta: None,
2459        }
2460    }
2461
2462    /// **UNSTABLE**
2463    ///
2464    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2465    ///
2466    /// A client-generated unique identifier for this user message.
2467    ///
2468    /// If provided, the Agent SHOULD echo this value as `userMessageId` in the
2469    /// [`PromptResponse`] to confirm it was recorded.
2470    /// Both clients and agents MUST use UUID format for message IDs.
2471    #[cfg(feature = "unstable_message_id")]
2472    #[must_use]
2473    pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
2474        self.message_id = message_id.into_option();
2475        self
2476    }
2477
2478    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2479    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2480    /// these keys.
2481    ///
2482    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2483    #[must_use]
2484    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2485        self.meta = meta.into_option();
2486        self
2487    }
2488}
2489
2490/// Response from processing a user prompt.
2491///
2492/// See protocol docs: [Check for Completion](https://agentclientprotocol.com/protocol/prompt-turn#4-check-for-completion)
2493#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2494#[schemars(extend("x-side" = "agent", "x-method" = SESSION_PROMPT_METHOD_NAME))]
2495#[serde(rename_all = "camelCase")]
2496#[non_exhaustive]
2497pub struct PromptResponse {
2498    /// **UNSTABLE**
2499    ///
2500    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2501    ///
2502    /// The acknowledged user message ID.
2503    ///
2504    /// If the client provided a `messageId` in the [`PromptRequest`], the agent echoes it here
2505    /// to confirm it was recorded. If the client did not provide one, the agent MAY assign one
2506    /// and return it here. Absence of this field indicates the agent did not record a message ID.
2507    #[cfg(feature = "unstable_message_id")]
2508    #[serde(skip_serializing_if = "Option::is_none")]
2509    pub user_message_id: Option<String>,
2510    /// Indicates why the agent stopped processing the turn.
2511    pub stop_reason: StopReason,
2512    /// **UNSTABLE**
2513    ///
2514    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2515    ///
2516    /// Token usage for this turn (optional).
2517    #[cfg(feature = "unstable_session_usage")]
2518    #[serde(skip_serializing_if = "Option::is_none")]
2519    pub usage: Option<Usage>,
2520    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2521    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2522    /// these keys.
2523    ///
2524    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2525    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2526    pub meta: Option<Meta>,
2527}
2528
2529impl PromptResponse {
2530    #[must_use]
2531    pub fn new(stop_reason: StopReason) -> Self {
2532        Self {
2533            #[cfg(feature = "unstable_message_id")]
2534            user_message_id: None,
2535            stop_reason,
2536            #[cfg(feature = "unstable_session_usage")]
2537            usage: None,
2538            meta: None,
2539        }
2540    }
2541
2542    /// **UNSTABLE**
2543    ///
2544    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2545    ///
2546    /// The acknowledged user message ID.
2547    ///
2548    /// If the client provided a `messageId` in the [`PromptRequest`], the agent echoes it here
2549    /// to confirm it was recorded. If the client did not provide one, the agent MAY assign one
2550    /// and return it here. Absence of this field indicates the agent did not record a message ID.
2551    #[cfg(feature = "unstable_message_id")]
2552    #[must_use]
2553    pub fn user_message_id(mut self, user_message_id: impl IntoOption<String>) -> Self {
2554        self.user_message_id = user_message_id.into_option();
2555        self
2556    }
2557
2558    /// **UNSTABLE**
2559    ///
2560    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2561    ///
2562    /// Token usage for this turn.
2563    #[cfg(feature = "unstable_session_usage")]
2564    #[must_use]
2565    pub fn usage(mut self, usage: impl IntoOption<Usage>) -> Self {
2566        self.usage = usage.into_option();
2567        self
2568    }
2569
2570    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2571    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2572    /// these keys.
2573    ///
2574    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2575    #[must_use]
2576    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2577        self.meta = meta.into_option();
2578        self
2579    }
2580}
2581
2582/// Reasons why an agent stops processing a prompt turn.
2583///
2584/// See protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-turn#stop-reasons)
2585#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
2586#[serde(rename_all = "snake_case")]
2587#[non_exhaustive]
2588pub enum StopReason {
2589    /// The turn ended successfully.
2590    EndTurn,
2591    /// The turn ended because the agent reached the maximum number of tokens.
2592    MaxTokens,
2593    /// The turn ended because the agent reached the maximum number of allowed
2594    /// agent requests between user turns.
2595    MaxTurnRequests,
2596    /// The turn ended because the agent refused to continue. The user prompt
2597    /// and everything that comes after it won't be included in the next
2598    /// prompt, so this should be reflected in the UI.
2599    Refusal,
2600    /// The turn was cancelled by the client via `session/cancel`.
2601    ///
2602    /// This stop reason MUST be returned when the client sends a `session/cancel`
2603    /// notification, even if the cancellation causes exceptions in underlying operations.
2604    /// Agents should catch these exceptions and return this semantically meaningful
2605    /// response to confirm successful cancellation.
2606    Cancelled,
2607}
2608
2609/// **UNSTABLE**
2610///
2611/// This capability is not part of the spec yet, and may be removed or changed at any point.
2612///
2613/// Token usage information for a prompt turn.
2614#[cfg(feature = "unstable_session_usage")]
2615#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2616#[serde(rename_all = "camelCase")]
2617#[non_exhaustive]
2618pub struct Usage {
2619    /// Sum of all token types across session.
2620    pub total_tokens: u64,
2621    /// Total input tokens across all turns.
2622    pub input_tokens: u64,
2623    /// Total output tokens across all turns.
2624    pub output_tokens: u64,
2625    /// Total thought/reasoning tokens
2626    #[serde(skip_serializing_if = "Option::is_none")]
2627    pub thought_tokens: Option<u64>,
2628    /// Total cache read tokens.
2629    #[serde(skip_serializing_if = "Option::is_none")]
2630    pub cached_read_tokens: Option<u64>,
2631    /// Total cache write tokens.
2632    #[serde(skip_serializing_if = "Option::is_none")]
2633    pub cached_write_tokens: Option<u64>,
2634}
2635
2636#[cfg(feature = "unstable_session_usage")]
2637impl Usage {
2638    #[must_use]
2639    pub fn new(total_tokens: u64, input_tokens: u64, output_tokens: u64) -> Self {
2640        Self {
2641            total_tokens,
2642            input_tokens,
2643            output_tokens,
2644            thought_tokens: None,
2645            cached_read_tokens: None,
2646            cached_write_tokens: None,
2647        }
2648    }
2649
2650    /// Total thought/reasoning tokens
2651    #[must_use]
2652    pub fn thought_tokens(mut self, thought_tokens: impl IntoOption<u64>) -> Self {
2653        self.thought_tokens = thought_tokens.into_option();
2654        self
2655    }
2656
2657    /// Total cache read tokens.
2658    #[must_use]
2659    pub fn cached_read_tokens(mut self, cached_read_tokens: impl IntoOption<u64>) -> Self {
2660        self.cached_read_tokens = cached_read_tokens.into_option();
2661        self
2662    }
2663
2664    /// Total cache write tokens.
2665    #[must_use]
2666    pub fn cached_write_tokens(mut self, cached_write_tokens: impl IntoOption<u64>) -> Self {
2667        self.cached_write_tokens = cached_write_tokens.into_option();
2668        self
2669    }
2670}
2671
2672// Model
2673
2674/// **UNSTABLE**
2675///
2676/// This capability is not part of the spec yet, and may be removed or changed at any point.
2677///
2678/// The set of models and the one currently active.
2679#[cfg(feature = "unstable_session_model")]
2680#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2681#[serde(rename_all = "camelCase")]
2682#[non_exhaustive]
2683pub struct SessionModelState {
2684    /// The current model the Agent is in.
2685    pub current_model_id: ModelId,
2686    /// The set of models that the Agent can use
2687    pub available_models: Vec<ModelInfo>,
2688    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2689    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2690    /// these keys.
2691    ///
2692    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2693    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2694    pub meta: Option<Meta>,
2695}
2696
2697#[cfg(feature = "unstable_session_model")]
2698impl SessionModelState {
2699    #[must_use]
2700    pub fn new(current_model_id: impl Into<ModelId>, available_models: Vec<ModelInfo>) -> Self {
2701        Self {
2702            current_model_id: current_model_id.into(),
2703            available_models,
2704            meta: None,
2705        }
2706    }
2707
2708    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2709    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2710    /// these keys.
2711    ///
2712    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2713    #[must_use]
2714    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2715        self.meta = meta.into_option();
2716        self
2717    }
2718}
2719
2720/// **UNSTABLE**
2721///
2722/// This capability is not part of the spec yet, and may be removed or changed at any point.
2723///
2724/// A unique identifier for a model.
2725#[cfg(feature = "unstable_session_model")]
2726#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
2727#[serde(transparent)]
2728#[from(Arc<str>, String, &'static str)]
2729#[non_exhaustive]
2730pub struct ModelId(pub Arc<str>);
2731
2732#[cfg(feature = "unstable_session_model")]
2733impl ModelId {
2734    #[must_use]
2735    pub fn new(id: impl Into<Arc<str>>) -> Self {
2736        Self(id.into())
2737    }
2738}
2739
2740/// **UNSTABLE**
2741///
2742/// This capability is not part of the spec yet, and may be removed or changed at any point.
2743///
2744/// Information about a selectable model.
2745#[cfg(feature = "unstable_session_model")]
2746#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2747#[serde(rename_all = "camelCase")]
2748#[non_exhaustive]
2749pub struct ModelInfo {
2750    /// Unique identifier for the model.
2751    pub model_id: ModelId,
2752    /// Human-readable name of the model.
2753    pub name: String,
2754    /// Optional description of the model.
2755    #[serde(default, skip_serializing_if = "Option::is_none")]
2756    pub description: Option<String>,
2757    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2758    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2759    /// these keys.
2760    ///
2761    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2762    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2763    pub meta: Option<Meta>,
2764}
2765
2766#[cfg(feature = "unstable_session_model")]
2767impl ModelInfo {
2768    #[must_use]
2769    pub fn new(model_id: impl Into<ModelId>, name: impl Into<String>) -> Self {
2770        Self {
2771            model_id: model_id.into(),
2772            name: name.into(),
2773            description: None,
2774            meta: None,
2775        }
2776    }
2777
2778    /// Optional description of the model.
2779    #[must_use]
2780    pub fn description(mut self, description: impl IntoOption<String>) -> Self {
2781        self.description = description.into_option();
2782        self
2783    }
2784
2785    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2786    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2787    /// these keys.
2788    ///
2789    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2790    #[must_use]
2791    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2792        self.meta = meta.into_option();
2793        self
2794    }
2795}
2796
2797/// **UNSTABLE**
2798///
2799/// This capability is not part of the spec yet, and may be removed or changed at any point.
2800///
2801/// Request parameters for setting a session model.
2802#[cfg(feature = "unstable_session_model")]
2803#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2804#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
2805#[serde(rename_all = "camelCase")]
2806#[non_exhaustive]
2807pub struct SetSessionModelRequest {
2808    /// The ID of the session to set the model for.
2809    pub session_id: SessionId,
2810    /// The ID of the model to set.
2811    pub model_id: ModelId,
2812    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2813    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2814    /// these keys.
2815    ///
2816    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2817    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2818    pub meta: Option<Meta>,
2819}
2820
2821#[cfg(feature = "unstable_session_model")]
2822impl SetSessionModelRequest {
2823    #[must_use]
2824    pub fn new(session_id: impl Into<SessionId>, model_id: impl Into<ModelId>) -> Self {
2825        Self {
2826            session_id: session_id.into(),
2827            model_id: model_id.into(),
2828            meta: None,
2829        }
2830    }
2831
2832    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2833    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2834    /// these keys.
2835    ///
2836    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2837    #[must_use]
2838    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2839        self.meta = meta.into_option();
2840        self
2841    }
2842}
2843
2844/// **UNSTABLE**
2845///
2846/// This capability is not part of the spec yet, and may be removed or changed at any point.
2847///
2848/// Response to `session/set_model` method.
2849#[cfg(feature = "unstable_session_model")]
2850#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2851#[schemars(extend("x-side" = "agent", "x-method" = SESSION_SET_MODEL_METHOD_NAME))]
2852#[serde(rename_all = "camelCase")]
2853#[non_exhaustive]
2854pub struct SetSessionModelResponse {
2855    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2856    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2857    /// these keys.
2858    ///
2859    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2860    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2861    pub meta: Option<Meta>,
2862}
2863
2864#[cfg(feature = "unstable_session_model")]
2865impl SetSessionModelResponse {
2866    #[must_use]
2867    pub fn new() -> Self {
2868        Self::default()
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// Capabilities
2884
2885/// Capabilities supported by the agent.
2886///
2887/// Advertised during initialization to inform the client about
2888/// available features and content types.
2889///
2890/// See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities)
2891#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2892#[serde(rename_all = "camelCase")]
2893#[non_exhaustive]
2894pub struct AgentCapabilities {
2895    /// Whether the agent supports `session/load`.
2896    #[serde(default)]
2897    pub load_session: bool,
2898    /// Prompt capabilities supported by the agent.
2899    #[serde(default)]
2900    pub prompt_capabilities: PromptCapabilities,
2901    /// MCP capabilities supported by the agent.
2902    #[serde(default)]
2903    pub mcp_capabilities: McpCapabilities,
2904    #[serde(default)]
2905    pub session_capabilities: SessionCapabilities,
2906    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2907    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2908    /// these keys.
2909    ///
2910    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2911    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
2912    pub meta: Option<Meta>,
2913}
2914
2915impl AgentCapabilities {
2916    #[must_use]
2917    pub fn new() -> Self {
2918        Self::default()
2919    }
2920
2921    /// Whether the agent supports `session/load`.
2922    #[must_use]
2923    pub fn load_session(mut self, load_session: bool) -> Self {
2924        self.load_session = load_session;
2925        self
2926    }
2927
2928    /// Prompt capabilities supported by the agent.
2929    #[must_use]
2930    pub fn prompt_capabilities(mut self, prompt_capabilities: PromptCapabilities) -> Self {
2931        self.prompt_capabilities = prompt_capabilities;
2932        self
2933    }
2934
2935    /// MCP capabilities supported by the agent.
2936    #[must_use]
2937    pub fn mcp_capabilities(mut self, mcp_capabilities: McpCapabilities) -> Self {
2938        self.mcp_capabilities = mcp_capabilities;
2939        self
2940    }
2941
2942    /// Session capabilities supported by the agent.
2943    #[must_use]
2944    pub fn session_capabilities(mut self, session_capabilities: SessionCapabilities) -> Self {
2945        self.session_capabilities = session_capabilities;
2946        self
2947    }
2948
2949    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2950    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2951    /// these keys.
2952    ///
2953    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2954    #[must_use]
2955    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2956        self.meta = meta.into_option();
2957        self
2958    }
2959}
2960
2961/// Session capabilities supported by the agent.
2962///
2963/// As a baseline, all Agents **MUST** support `session/new`, `session/prompt`, `session/cancel`, and `session/update`.
2964///
2965/// Optionally, they **MAY** support other session methods and notifications by specifying additional capabilities.
2966///
2967/// Note: `session/load` is still handled by the top-level `load_session` capability. This will be unified in future versions of the protocol.
2968///
2969/// See protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)
2970#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2971#[non_exhaustive]
2972pub struct SessionCapabilities {
2973    /// **UNSTABLE**
2974    ///
2975    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2976    ///
2977    /// Whether the agent supports `session/list`.
2978    #[cfg(feature = "unstable_session_list")]
2979    #[serde(skip_serializing_if = "Option::is_none")]
2980    pub list: Option<SessionListCapabilities>,
2981    /// **UNSTABLE**
2982    ///
2983    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2984    ///
2985    /// Whether the agent supports `session/fork`.
2986    #[cfg(feature = "unstable_session_fork")]
2987    #[serde(skip_serializing_if = "Option::is_none")]
2988    pub fork: Option<SessionForkCapabilities>,
2989    /// **UNSTABLE**
2990    ///
2991    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2992    ///
2993    /// Whether the agent supports `session/resume`.
2994    #[cfg(feature = "unstable_session_resume")]
2995    #[serde(skip_serializing_if = "Option::is_none")]
2996    pub resume: Option<SessionResumeCapabilities>,
2997    /// **UNSTABLE**
2998    ///
2999    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3000    ///
3001    /// Whether the agent supports `session/stop`.
3002    #[cfg(feature = "unstable_session_stop")]
3003    #[serde(skip_serializing_if = "Option::is_none")]
3004    pub stop: Option<SessionStopCapabilities>,
3005    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3006    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3007    /// these keys.
3008    ///
3009    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3010    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3011    pub meta: Option<Meta>,
3012}
3013
3014impl SessionCapabilities {
3015    #[must_use]
3016    pub fn new() -> Self {
3017        Self::default()
3018    }
3019
3020    #[cfg(feature = "unstable_session_list")]
3021    /// Whether the agent supports `session/list`.
3022    #[must_use]
3023    pub fn list(mut self, list: impl IntoOption<SessionListCapabilities>) -> Self {
3024        self.list = list.into_option();
3025        self
3026    }
3027
3028    #[cfg(feature = "unstable_session_fork")]
3029    /// Whether the agent supports `session/fork`.
3030    #[must_use]
3031    pub fn fork(mut self, fork: impl IntoOption<SessionForkCapabilities>) -> Self {
3032        self.fork = fork.into_option();
3033        self
3034    }
3035
3036    #[cfg(feature = "unstable_session_resume")]
3037    /// Whether the agent supports `session/resume`.
3038    #[must_use]
3039    pub fn resume(mut self, resume: impl IntoOption<SessionResumeCapabilities>) -> Self {
3040        self.resume = resume.into_option();
3041        self
3042    }
3043
3044    #[cfg(feature = "unstable_session_stop")]
3045    /// Whether the agent supports `session/stop`.
3046    #[must_use]
3047    pub fn stop(mut self, stop: impl IntoOption<SessionStopCapabilities>) -> Self {
3048        self.stop = stop.into_option();
3049        self
3050    }
3051
3052    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3053    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3054    /// these keys.
3055    ///
3056    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3057    #[must_use]
3058    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3059        self.meta = meta.into_option();
3060        self
3061    }
3062}
3063
3064/// Capabilities for the `session/list` method.
3065///
3066/// By supplying `{}` it means that the agent supports listing of sessions.
3067///
3068/// Further capabilities can be added in the future for other means of filtering or searching the list.
3069#[cfg(feature = "unstable_session_list")]
3070#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3071#[non_exhaustive]
3072pub struct SessionListCapabilities {
3073    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3074    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3075    /// these keys.
3076    ///
3077    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3078    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3079    pub meta: Option<Meta>,
3080}
3081
3082#[cfg(feature = "unstable_session_list")]
3083impl SessionListCapabilities {
3084    #[must_use]
3085    pub fn new() -> Self {
3086        Self::default()
3087    }
3088    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3089    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3090    /// these keys.
3091    ///
3092    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3093    #[must_use]
3094    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3095        self.meta = meta.into_option();
3096        self
3097    }
3098}
3099
3100/// **UNSTABLE**
3101///
3102/// This capability is not part of the spec yet, and may be removed or changed at any point.
3103///
3104/// Capabilities for the `session/fork` method.
3105///
3106/// By supplying `{}` it means that the agent supports forking of sessions.
3107#[cfg(feature = "unstable_session_fork")]
3108#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3109#[non_exhaustive]
3110pub struct SessionForkCapabilities {
3111    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3112    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3113    /// these keys.
3114    ///
3115    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3116    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3117    pub meta: Option<Meta>,
3118}
3119
3120#[cfg(feature = "unstable_session_fork")]
3121impl SessionForkCapabilities {
3122    #[must_use]
3123    pub fn new() -> Self {
3124        Self::default()
3125    }
3126
3127    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3128    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3129    /// these keys.
3130    ///
3131    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3132    #[must_use]
3133    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3134        self.meta = meta.into_option();
3135        self
3136    }
3137}
3138
3139/// **UNSTABLE**
3140///
3141/// This capability is not part of the spec yet, and may be removed or changed at any point.
3142///
3143/// Capabilities for the `session/resume` method.
3144///
3145/// By supplying `{}` it means that the agent supports resuming of sessions.
3146#[cfg(feature = "unstable_session_resume")]
3147#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3148#[non_exhaustive]
3149pub struct SessionResumeCapabilities {
3150    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3151    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3152    /// these keys.
3153    ///
3154    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3155    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3156    pub meta: Option<Meta>,
3157}
3158
3159#[cfg(feature = "unstable_session_resume")]
3160impl SessionResumeCapabilities {
3161    #[must_use]
3162    pub fn new() -> Self {
3163        Self::default()
3164    }
3165
3166    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3167    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3168    /// these keys.
3169    ///
3170    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3171    #[must_use]
3172    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3173        self.meta = meta.into_option();
3174        self
3175    }
3176}
3177
3178/// **UNSTABLE**
3179///
3180/// This capability is not part of the spec yet, and may be removed or changed at any point.
3181///
3182/// Capabilities for the `session/stop` method.
3183///
3184/// By supplying `{}` it means that the agent supports stopping of sessions.
3185#[cfg(feature = "unstable_session_stop")]
3186#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3187#[non_exhaustive]
3188pub struct SessionStopCapabilities {
3189    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3190    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3191    /// these keys.
3192    ///
3193    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3194    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3195    pub meta: Option<Meta>,
3196}
3197
3198#[cfg(feature = "unstable_session_stop")]
3199impl SessionStopCapabilities {
3200    #[must_use]
3201    pub fn new() -> Self {
3202        Self::default()
3203    }
3204
3205    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3206    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3207    /// these keys.
3208    ///
3209    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3210    #[must_use]
3211    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3212        self.meta = meta.into_option();
3213        self
3214    }
3215}
3216
3217/// Prompt capabilities supported by the agent in `session/prompt` requests.
3218///
3219/// Baseline agent functionality requires support for [`ContentBlock::Text`]
3220/// and [`ContentBlock::ResourceLink`] in prompt requests.
3221///
3222/// Other variants must be explicitly opted in to.
3223/// Capabilities for different types of content in prompt requests.
3224///
3225/// Indicates which content types beyond the baseline (text and resource links)
3226/// the agent can process.
3227///
3228/// See protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)
3229#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3230#[serde(rename_all = "camelCase")]
3231#[non_exhaustive]
3232pub struct PromptCapabilities {
3233    /// Agent supports [`ContentBlock::Image`].
3234    #[serde(default)]
3235    pub image: bool,
3236    /// Agent supports [`ContentBlock::Audio`].
3237    #[serde(default)]
3238    pub audio: bool,
3239    /// Agent supports embedded context in `session/prompt` requests.
3240    ///
3241    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
3242    /// in prompt requests for pieces of context that are referenced in the message.
3243    #[serde(default)]
3244    pub embedded_context: bool,
3245    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3246    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3247    /// these keys.
3248    ///
3249    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3250    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3251    pub meta: Option<Meta>,
3252}
3253
3254impl PromptCapabilities {
3255    #[must_use]
3256    pub fn new() -> Self {
3257        Self::default()
3258    }
3259
3260    /// Agent supports [`ContentBlock::Image`].
3261    #[must_use]
3262    pub fn image(mut self, image: bool) -> Self {
3263        self.image = image;
3264        self
3265    }
3266
3267    /// Agent supports [`ContentBlock::Audio`].
3268    #[must_use]
3269    pub fn audio(mut self, audio: bool) -> Self {
3270        self.audio = audio;
3271        self
3272    }
3273
3274    /// Agent supports embedded context in `session/prompt` requests.
3275    ///
3276    /// When enabled, the Client is allowed to include [`ContentBlock::Resource`]
3277    /// in prompt requests for pieces of context that are referenced in the message.
3278    #[must_use]
3279    pub fn embedded_context(mut self, embedded_context: bool) -> Self {
3280        self.embedded_context = embedded_context;
3281        self
3282    }
3283
3284    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3285    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3286    /// these keys.
3287    ///
3288    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3289    #[must_use]
3290    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3291        self.meta = meta.into_option();
3292        self
3293    }
3294}
3295
3296/// MCP capabilities supported by the agent
3297#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3298#[serde(rename_all = "camelCase")]
3299#[non_exhaustive]
3300pub struct McpCapabilities {
3301    /// Agent supports [`McpServer::Http`].
3302    #[serde(default)]
3303    pub http: bool,
3304    /// Agent supports [`McpServer::Sse`].
3305    #[serde(default)]
3306    pub sse: bool,
3307    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3308    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3309    /// these keys.
3310    ///
3311    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3312    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3313    pub meta: Option<Meta>,
3314}
3315
3316impl McpCapabilities {
3317    #[must_use]
3318    pub fn new() -> Self {
3319        Self::default()
3320    }
3321
3322    /// Agent supports [`McpServer::Http`].
3323    #[must_use]
3324    pub fn http(mut self, http: bool) -> Self {
3325        self.http = http;
3326        self
3327    }
3328
3329    /// Agent supports [`McpServer::Sse`].
3330    #[must_use]
3331    pub fn sse(mut self, sse: bool) -> Self {
3332        self.sse = sse;
3333        self
3334    }
3335
3336    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3337    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3338    /// these keys.
3339    ///
3340    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3341    #[must_use]
3342    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3343        self.meta = meta.into_option();
3344        self
3345    }
3346}
3347
3348// Method schema
3349
3350/// Names of all methods that agents handle.
3351///
3352/// Provides a centralized definition of method names used in the protocol.
3353#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
3354#[non_exhaustive]
3355pub struct AgentMethodNames {
3356    /// Method for initializing the connection.
3357    pub initialize: &'static str,
3358    /// Method for authenticating with the agent.
3359    pub authenticate: &'static str,
3360    /// Method for creating a new session.
3361    pub session_new: &'static str,
3362    /// Method for loading an existing session.
3363    pub session_load: &'static str,
3364    /// Method for setting the mode for a session.
3365    pub session_set_mode: &'static str,
3366    /// Method for setting a configuration option for a session.
3367    pub session_set_config_option: &'static str,
3368    /// Method for sending a prompt to the agent.
3369    pub session_prompt: &'static str,
3370    /// Notification for cancelling operations.
3371    pub session_cancel: &'static str,
3372    /// Method for selecting a model for a given session.
3373    #[cfg(feature = "unstable_session_model")]
3374    pub session_set_model: &'static str,
3375    /// Method for listing existing sessions.
3376    #[cfg(feature = "unstable_session_list")]
3377    pub session_list: &'static str,
3378    /// Method for forking an existing session.
3379    #[cfg(feature = "unstable_session_fork")]
3380    pub session_fork: &'static str,
3381    /// Method for resuming an existing session.
3382    #[cfg(feature = "unstable_session_resume")]
3383    pub session_resume: &'static str,
3384    /// Method for stopping an active session.
3385    #[cfg(feature = "unstable_session_stop")]
3386    pub session_stop: &'static str,
3387}
3388
3389/// Constant containing all agent method names.
3390pub const AGENT_METHOD_NAMES: AgentMethodNames = AgentMethodNames {
3391    initialize: INITIALIZE_METHOD_NAME,
3392    authenticate: AUTHENTICATE_METHOD_NAME,
3393    session_new: SESSION_NEW_METHOD_NAME,
3394    session_load: SESSION_LOAD_METHOD_NAME,
3395    session_set_mode: SESSION_SET_MODE_METHOD_NAME,
3396    session_set_config_option: SESSION_SET_CONFIG_OPTION_METHOD_NAME,
3397    session_prompt: SESSION_PROMPT_METHOD_NAME,
3398    session_cancel: SESSION_CANCEL_METHOD_NAME,
3399    #[cfg(feature = "unstable_session_model")]
3400    session_set_model: SESSION_SET_MODEL_METHOD_NAME,
3401    #[cfg(feature = "unstable_session_list")]
3402    session_list: SESSION_LIST_METHOD_NAME,
3403    #[cfg(feature = "unstable_session_fork")]
3404    session_fork: SESSION_FORK_METHOD_NAME,
3405    #[cfg(feature = "unstable_session_resume")]
3406    session_resume: SESSION_RESUME_METHOD_NAME,
3407    #[cfg(feature = "unstable_session_stop")]
3408    session_stop: SESSION_STOP_METHOD_NAME,
3409};
3410
3411/// Method name for the initialize request.
3412pub(crate) const INITIALIZE_METHOD_NAME: &str = "initialize";
3413/// Method name for the authenticate request.
3414pub(crate) const AUTHENTICATE_METHOD_NAME: &str = "authenticate";
3415/// Method name for creating a new session.
3416pub(crate) const SESSION_NEW_METHOD_NAME: &str = "session/new";
3417/// Method name for loading an existing session.
3418pub(crate) const SESSION_LOAD_METHOD_NAME: &str = "session/load";
3419/// Method name for setting the mode for a session.
3420pub(crate) const SESSION_SET_MODE_METHOD_NAME: &str = "session/set_mode";
3421/// Method name for setting a configuration option for a session.
3422pub(crate) const SESSION_SET_CONFIG_OPTION_METHOD_NAME: &str = "session/set_config_option";
3423/// Method name for sending a prompt.
3424pub(crate) const SESSION_PROMPT_METHOD_NAME: &str = "session/prompt";
3425/// Method name for the cancel notification.
3426pub(crate) const SESSION_CANCEL_METHOD_NAME: &str = "session/cancel";
3427/// Method name for selecting a model for a given session.
3428#[cfg(feature = "unstable_session_model")]
3429pub(crate) const SESSION_SET_MODEL_METHOD_NAME: &str = "session/set_model";
3430/// Method name for listing existing sessions.
3431#[cfg(feature = "unstable_session_list")]
3432pub(crate) const SESSION_LIST_METHOD_NAME: &str = "session/list";
3433/// Method name for forking an existing session.
3434#[cfg(feature = "unstable_session_fork")]
3435pub(crate) const SESSION_FORK_METHOD_NAME: &str = "session/fork";
3436/// Method name for resuming an existing session.
3437#[cfg(feature = "unstable_session_resume")]
3438pub(crate) const SESSION_RESUME_METHOD_NAME: &str = "session/resume";
3439/// Method name for stopping an active session.
3440#[cfg(feature = "unstable_session_stop")]
3441pub(crate) const SESSION_STOP_METHOD_NAME: &str = "session/stop";
3442
3443/// All possible requests that a client can send to an agent.
3444///
3445/// This enum is used internally for routing RPC requests. You typically won't need
3446/// to use this directly - instead, use the methods on the [`Agent`] trait.
3447///
3448/// This enum encompasses all method calls from client to agent.
3449#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
3450#[serde(untagged)]
3451#[schemars(inline)]
3452#[non_exhaustive]
3453pub enum ClientRequest {
3454    /// Establishes the connection with a client and negotiates protocol capabilities.
3455    ///
3456    /// This method is called once at the beginning of the connection to:
3457    /// - Negotiate the protocol version to use
3458    /// - Exchange capability information between client and agent
3459    /// - Determine available authentication methods
3460    ///
3461    /// The agent should respond with its supported protocol version and capabilities.
3462    ///
3463    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
3464    InitializeRequest(InitializeRequest),
3465    /// Authenticates the client using the specified authentication method.
3466    ///
3467    /// Called when the agent requires authentication before allowing session creation.
3468    /// The client provides the authentication method ID that was advertised during initialization.
3469    ///
3470    /// After successful authentication, the client can proceed to create sessions with
3471    /// `new_session` without receiving an `auth_required` error.
3472    ///
3473    /// See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization)
3474    AuthenticateRequest(AuthenticateRequest),
3475    /// Creates a new conversation session with the agent.
3476    ///
3477    /// Sessions represent independent conversation contexts with their own history and state.
3478    ///
3479    /// The agent should:
3480    /// - Create a new session context
3481    /// - Connect to any specified MCP servers
3482    /// - Return a unique session ID for future requests
3483    ///
3484    /// May return an `auth_required` error if the agent requires authentication.
3485    ///
3486    /// See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup)
3487    NewSessionRequest(NewSessionRequest),
3488    /// Loads an existing session to resume a previous conversation.
3489    ///
3490    /// This method is only available if the agent advertises the `loadSession` capability.
3491    ///
3492    /// The agent should:
3493    /// - Restore the session context and conversation history
3494    /// - Connect to the specified MCP servers
3495    /// - Stream the entire conversation history back to the client via notifications
3496    ///
3497    /// See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions)
3498    LoadSessionRequest(LoadSessionRequest),
3499    #[cfg(feature = "unstable_session_list")]
3500    /// **UNSTABLE**
3501    ///
3502    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3503    ///
3504    /// Lists existing sessions known to the agent.
3505    ///
3506    /// This method is only available if the agent advertises the `listSessions` capability.
3507    ///
3508    /// The agent should return metadata about sessions with optional filtering and pagination support.
3509    ListSessionsRequest(ListSessionsRequest),
3510    #[cfg(feature = "unstable_session_fork")]
3511    /// **UNSTABLE**
3512    ///
3513    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3514    ///
3515    /// Forks an existing session to create a new independent session.
3516    ///
3517    /// This method is only available if the agent advertises the `session.fork` capability.
3518    ///
3519    /// The agent should create a new session with the same conversation context as the
3520    /// original, allowing operations like generating summaries without affecting the
3521    /// original session's history.
3522    ForkSessionRequest(ForkSessionRequest),
3523    #[cfg(feature = "unstable_session_resume")]
3524    /// **UNSTABLE**
3525    ///
3526    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3527    ///
3528    /// Resumes an existing session without returning previous messages.
3529    ///
3530    /// This method is only available if the agent advertises the `session.resume` capability.
3531    ///
3532    /// The agent should resume the session context, allowing the conversation to continue
3533    /// without replaying the message history (unlike `session/load`).
3534    ResumeSessionRequest(ResumeSessionRequest),
3535    #[cfg(feature = "unstable_session_stop")]
3536    /// **UNSTABLE**
3537    ///
3538    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3539    ///
3540    /// Stops an active session and frees up any resources associated with it.
3541    ///
3542    /// This method is only available if the agent advertises the `session.stop` capability.
3543    ///
3544    /// The agent must cancel any ongoing work (as if `session/cancel` was called)
3545    /// and then free up any resources associated with the session.
3546    StopSessionRequest(StopSessionRequest),
3547    /// Sets the current mode for a session.
3548    ///
3549    /// Allows switching between different agent modes (e.g., "ask", "architect", "code")
3550    /// that affect system prompts, tool availability, and permission behaviors.
3551    ///
3552    /// The mode must be one of the modes advertised in `availableModes` during session
3553    /// creation or loading. Agents may also change modes autonomously and notify the
3554    /// client via `current_mode_update` notifications.
3555    ///
3556    /// This method can be called at any time during a session, whether the Agent is
3557    /// idle or actively generating a response.
3558    ///
3559    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
3560    SetSessionModeRequest(SetSessionModeRequest),
3561    /// Sets the current value for a session configuration option.
3562    SetSessionConfigOptionRequest(SetSessionConfigOptionRequest),
3563    /// Processes a user prompt within a session.
3564    ///
3565    /// This method handles the whole lifecycle of a prompt:
3566    /// - Receives user messages with optional context (files, images, etc.)
3567    /// - Processes the prompt using language models
3568    /// - Reports language model content and tool calls to the Clients
3569    /// - Requests permission to run tools
3570    /// - Executes any requested tool calls
3571    /// - Returns when the turn is complete with a stop reason
3572    ///
3573    /// See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn)
3574    PromptRequest(PromptRequest),
3575    #[cfg(feature = "unstable_session_model")]
3576    /// **UNSTABLE**
3577    ///
3578    /// This capability is not part of the spec yet, and may be removed or changed at any point.
3579    ///
3580    /// Select a model for a given session.
3581    SetSessionModelRequest(SetSessionModelRequest),
3582    /// Handles extension method requests from the client.
3583    ///
3584    /// Extension methods provide a way to add custom functionality while maintaining
3585    /// protocol compatibility.
3586    ///
3587    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3588    ExtMethodRequest(ExtRequest),
3589}
3590
3591impl ClientRequest {
3592    /// Returns the corresponding method name of the request.
3593    #[must_use]
3594    pub fn method(&self) -> &str {
3595        match self {
3596            Self::InitializeRequest(_) => AGENT_METHOD_NAMES.initialize,
3597            Self::AuthenticateRequest(_) => AGENT_METHOD_NAMES.authenticate,
3598            Self::NewSessionRequest(_) => AGENT_METHOD_NAMES.session_new,
3599            Self::LoadSessionRequest(_) => AGENT_METHOD_NAMES.session_load,
3600            #[cfg(feature = "unstable_session_list")]
3601            Self::ListSessionsRequest(_) => AGENT_METHOD_NAMES.session_list,
3602            #[cfg(feature = "unstable_session_fork")]
3603            Self::ForkSessionRequest(_) => AGENT_METHOD_NAMES.session_fork,
3604            #[cfg(feature = "unstable_session_resume")]
3605            Self::ResumeSessionRequest(_) => AGENT_METHOD_NAMES.session_resume,
3606            #[cfg(feature = "unstable_session_stop")]
3607            Self::StopSessionRequest(_) => AGENT_METHOD_NAMES.session_stop,
3608            Self::SetSessionModeRequest(_) => AGENT_METHOD_NAMES.session_set_mode,
3609            Self::SetSessionConfigOptionRequest(_) => AGENT_METHOD_NAMES.session_set_config_option,
3610            Self::PromptRequest(_) => AGENT_METHOD_NAMES.session_prompt,
3611            #[cfg(feature = "unstable_session_model")]
3612            Self::SetSessionModelRequest(_) => AGENT_METHOD_NAMES.session_set_model,
3613            Self::ExtMethodRequest(ext_request) => &ext_request.method,
3614        }
3615    }
3616}
3617
3618/// All possible responses that an agent can send to a client.
3619///
3620/// This enum is used internally for routing RPC responses. You typically won't need
3621/// to use this directly - the responses are handled automatically by the connection.
3622///
3623/// These are responses to the corresponding `ClientRequest` variants.
3624#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
3625#[serde(untagged)]
3626#[schemars(inline)]
3627#[non_exhaustive]
3628#[allow(clippy::large_enum_variant)]
3629pub enum AgentResponse {
3630    InitializeResponse(InitializeResponse),
3631    AuthenticateResponse(#[serde(default)] AuthenticateResponse),
3632    NewSessionResponse(NewSessionResponse),
3633    LoadSessionResponse(#[serde(default)] LoadSessionResponse),
3634    #[cfg(feature = "unstable_session_list")]
3635    ListSessionsResponse(ListSessionsResponse),
3636    #[cfg(feature = "unstable_session_fork")]
3637    ForkSessionResponse(ForkSessionResponse),
3638    #[cfg(feature = "unstable_session_resume")]
3639    ResumeSessionResponse(#[serde(default)] ResumeSessionResponse),
3640    #[cfg(feature = "unstable_session_stop")]
3641    StopSessionResponse(#[serde(default)] StopSessionResponse),
3642    SetSessionModeResponse(#[serde(default)] SetSessionModeResponse),
3643    SetSessionConfigOptionResponse(SetSessionConfigOptionResponse),
3644    PromptResponse(PromptResponse),
3645    #[cfg(feature = "unstable_session_model")]
3646    SetSessionModelResponse(#[serde(default)] SetSessionModelResponse),
3647    ExtMethodResponse(ExtResponse),
3648}
3649
3650/// All possible notifications that a client can send to an agent.
3651///
3652/// This enum is used internally for routing RPC notifications. You typically won't need
3653/// to use this directly - use the notification methods on the [`Agent`] trait instead.
3654///
3655/// Notifications do not expect a response.
3656#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
3657#[serde(untagged)]
3658#[schemars(inline)]
3659#[non_exhaustive]
3660pub enum ClientNotification {
3661    /// Cancels ongoing operations for a session.
3662    ///
3663    /// This is a notification sent by the client to cancel an ongoing prompt turn.
3664    ///
3665    /// Upon receiving this notification, the Agent SHOULD:
3666    /// - Stop all language model requests as soon as possible
3667    /// - Abort all tool call invocations in progress
3668    /// - Send any pending `session/update` notifications
3669    /// - Respond to the original `session/prompt` request with `StopReason::Cancelled`
3670    ///
3671    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
3672    CancelNotification(CancelNotification),
3673    /// Handles extension notifications from the client.
3674    ///
3675    /// Extension notifications provide a way to send one-way messages for custom functionality
3676    /// while maintaining protocol compatibility.
3677    ///
3678    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3679    ExtNotification(ExtNotification),
3680}
3681
3682impl ClientNotification {
3683    /// Returns the corresponding method name of the notification.
3684    #[must_use]
3685    pub fn method(&self) -> &str {
3686        match self {
3687            Self::CancelNotification(_) => AGENT_METHOD_NAMES.session_cancel,
3688            Self::ExtNotification(ext_notification) => &ext_notification.method,
3689        }
3690    }
3691}
3692
3693/// Notification to cancel ongoing operations for a session.
3694///
3695/// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
3696#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
3697#[schemars(extend("x-side" = "agent", "x-method" = SESSION_CANCEL_METHOD_NAME))]
3698#[serde(rename_all = "camelCase")]
3699#[non_exhaustive]
3700pub struct CancelNotification {
3701    /// The ID of the session to cancel operations for.
3702    pub session_id: SessionId,
3703    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3704    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3705    /// these keys.
3706    ///
3707    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3708    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
3709    pub meta: Option<Meta>,
3710}
3711
3712impl CancelNotification {
3713    #[must_use]
3714    pub fn new(session_id: impl Into<SessionId>) -> Self {
3715        Self {
3716            session_id: session_id.into(),
3717            meta: None,
3718        }
3719    }
3720
3721    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
3722    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
3723    /// these keys.
3724    ///
3725    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
3726    #[must_use]
3727    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
3728        self.meta = meta.into_option();
3729        self
3730    }
3731}
3732
3733#[cfg(test)]
3734mod test_serialization {
3735    use super::*;
3736    use serde_json::json;
3737
3738    #[test]
3739    fn test_mcp_server_stdio_serialization() {
3740        let server = McpServer::Stdio(
3741            McpServerStdio::new("test-server", "/usr/bin/server")
3742                .args(vec!["--port".to_string(), "3000".to_string()])
3743                .env(vec![EnvVariable::new("API_KEY", "secret123")]),
3744        );
3745
3746        let json = serde_json::to_value(&server).unwrap();
3747        assert_eq!(
3748            json,
3749            json!({
3750                "name": "test-server",
3751                "command": "/usr/bin/server",
3752                "args": ["--port", "3000"],
3753                "env": [
3754                    {
3755                        "name": "API_KEY",
3756                        "value": "secret123"
3757                    }
3758                ]
3759            })
3760        );
3761
3762        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3763        match deserialized {
3764            McpServer::Stdio(McpServerStdio {
3765                name,
3766                command,
3767                args,
3768                env,
3769                meta: _,
3770            }) => {
3771                assert_eq!(name, "test-server");
3772                assert_eq!(command, PathBuf::from("/usr/bin/server"));
3773                assert_eq!(args, vec!["--port", "3000"]);
3774                assert_eq!(env.len(), 1);
3775                assert_eq!(env[0].name, "API_KEY");
3776                assert_eq!(env[0].value, "secret123");
3777            }
3778            _ => panic!("Expected Stdio variant"),
3779        }
3780    }
3781
3782    #[test]
3783    fn test_mcp_server_http_serialization() {
3784        let server = McpServer::Http(
3785            McpServerHttp::new("http-server", "https://api.example.com").headers(vec![
3786                HttpHeader::new("Authorization", "Bearer token123"),
3787                HttpHeader::new("Content-Type", "application/json"),
3788            ]),
3789        );
3790
3791        let json = serde_json::to_value(&server).unwrap();
3792        assert_eq!(
3793            json,
3794            json!({
3795                "type": "http",
3796                "name": "http-server",
3797                "url": "https://api.example.com",
3798                "headers": [
3799                    {
3800                        "name": "Authorization",
3801                        "value": "Bearer token123"
3802                    },
3803                    {
3804                        "name": "Content-Type",
3805                        "value": "application/json"
3806                    }
3807                ]
3808            })
3809        );
3810
3811        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3812        match deserialized {
3813            McpServer::Http(McpServerHttp {
3814                name,
3815                url,
3816                headers,
3817                meta: _,
3818            }) => {
3819                assert_eq!(name, "http-server");
3820                assert_eq!(url, "https://api.example.com");
3821                assert_eq!(headers.len(), 2);
3822                assert_eq!(headers[0].name, "Authorization");
3823                assert_eq!(headers[0].value, "Bearer token123");
3824                assert_eq!(headers[1].name, "Content-Type");
3825                assert_eq!(headers[1].value, "application/json");
3826            }
3827            _ => panic!("Expected Http variant"),
3828        }
3829    }
3830
3831    #[test]
3832    fn test_mcp_server_sse_serialization() {
3833        let server = McpServer::Sse(
3834            McpServerSse::new("sse-server", "https://sse.example.com/events")
3835                .headers(vec![HttpHeader::new("X-API-Key", "apikey456")]),
3836        );
3837
3838        let json = serde_json::to_value(&server).unwrap();
3839        assert_eq!(
3840            json,
3841            json!({
3842                "type": "sse",
3843                "name": "sse-server",
3844                "url": "https://sse.example.com/events",
3845                "headers": [
3846                    {
3847                        "name": "X-API-Key",
3848                        "value": "apikey456"
3849                    }
3850                ]
3851            })
3852        );
3853
3854        let deserialized: McpServer = serde_json::from_value(json).unwrap();
3855        match deserialized {
3856            McpServer::Sse(McpServerSse {
3857                name,
3858                url,
3859                headers,
3860                meta: _,
3861            }) => {
3862                assert_eq!(name, "sse-server");
3863                assert_eq!(url, "https://sse.example.com/events");
3864                assert_eq!(headers.len(), 1);
3865                assert_eq!(headers[0].name, "X-API-Key");
3866                assert_eq!(headers[0].value, "apikey456");
3867            }
3868            _ => panic!("Expected Sse variant"),
3869        }
3870    }
3871
3872    #[test]
3873    fn test_session_config_option_category_known_variants() {
3874        // Test serialization of known variants
3875        assert_eq!(
3876            serde_json::to_value(&SessionConfigOptionCategory::Mode).unwrap(),
3877            json!("mode")
3878        );
3879        assert_eq!(
3880            serde_json::to_value(&SessionConfigOptionCategory::Model).unwrap(),
3881            json!("model")
3882        );
3883        assert_eq!(
3884            serde_json::to_value(&SessionConfigOptionCategory::ThoughtLevel).unwrap(),
3885            json!("thought_level")
3886        );
3887
3888        // Test deserialization of known variants
3889        assert_eq!(
3890            serde_json::from_str::<SessionConfigOptionCategory>("\"mode\"").unwrap(),
3891            SessionConfigOptionCategory::Mode
3892        );
3893        assert_eq!(
3894            serde_json::from_str::<SessionConfigOptionCategory>("\"model\"").unwrap(),
3895            SessionConfigOptionCategory::Model
3896        );
3897        assert_eq!(
3898            serde_json::from_str::<SessionConfigOptionCategory>("\"thought_level\"").unwrap(),
3899            SessionConfigOptionCategory::ThoughtLevel
3900        );
3901    }
3902
3903    #[test]
3904    fn test_session_config_option_category_unknown_variants() {
3905        // Test that unknown strings are captured in Other variant
3906        let unknown: SessionConfigOptionCategory =
3907            serde_json::from_str("\"some_future_category\"").unwrap();
3908        assert_eq!(
3909            unknown,
3910            SessionConfigOptionCategory::Other("some_future_category".to_string())
3911        );
3912
3913        // Test round-trip of unknown category
3914        let json = serde_json::to_value(&unknown).unwrap();
3915        assert_eq!(json, json!("some_future_category"));
3916    }
3917
3918    #[test]
3919    fn test_session_config_option_category_custom_categories() {
3920        // Category names beginning with `_` are free for custom use
3921        let custom: SessionConfigOptionCategory =
3922            serde_json::from_str("\"_my_custom_category\"").unwrap();
3923        assert_eq!(
3924            custom,
3925            SessionConfigOptionCategory::Other("_my_custom_category".to_string())
3926        );
3927
3928        // Test round-trip preserves the custom category name
3929        let json = serde_json::to_value(&custom).unwrap();
3930        assert_eq!(json, json!("_my_custom_category"));
3931
3932        // Deserialize back and verify
3933        let deserialized: SessionConfigOptionCategory = serde_json::from_value(json).unwrap();
3934        assert_eq!(
3935            deserialized,
3936            SessionConfigOptionCategory::Other("_my_custom_category".to_string()),
3937        );
3938    }
3939
3940    #[test]
3941    fn test_auth_method_agent_serialization() {
3942        let method = AuthMethod::Agent(AuthMethodAgent::new("default-auth", "Default Auth"));
3943
3944        let json = serde_json::to_value(&method).unwrap();
3945        assert_eq!(
3946            json,
3947            json!({
3948                "id": "default-auth",
3949                "name": "Default Auth"
3950            })
3951        );
3952        // description should be omitted when None
3953        assert!(!json.as_object().unwrap().contains_key("description"));
3954        // Agent variant should not emit a `type` field (backward compat)
3955        assert!(!json.as_object().unwrap().contains_key("type"));
3956
3957        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
3958        match deserialized {
3959            AuthMethod::Agent(AuthMethodAgent { id, name, .. }) => {
3960                assert_eq!(id.0.as_ref(), "default-auth");
3961                assert_eq!(name, "Default Auth");
3962            }
3963            #[cfg(feature = "unstable_auth_methods")]
3964            _ => panic!("Expected Agent variant"),
3965        }
3966    }
3967
3968    #[test]
3969    fn test_auth_method_explicit_agent_deserialization() {
3970        // An explicit `"type": "agent"` should also deserialize to Agent
3971        let json = json!({
3972            "id": "agent-auth",
3973            "name": "Agent Auth",
3974            "type": "agent"
3975        });
3976
3977        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
3978        assert!(matches!(deserialized, AuthMethod::Agent(_)));
3979    }
3980
3981    #[cfg(feature = "unstable_auth_methods")]
3982    #[test]
3983    fn test_auth_method_env_var_serialization() {
3984        let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
3985            "api-key",
3986            "API Key",
3987            vec![AuthEnvVar::new("API_KEY")],
3988        ));
3989
3990        let json = serde_json::to_value(&method).unwrap();
3991        assert_eq!(
3992            json,
3993            json!({
3994                "id": "api-key",
3995                "name": "API Key",
3996                "type": "env_var",
3997                "vars": [{"name": "API_KEY"}]
3998            })
3999        );
4000        // secret defaults to true and should be omitted; optional defaults to false and should be omitted
4001        assert!(!json["vars"][0].as_object().unwrap().contains_key("secret"));
4002        assert!(
4003            !json["vars"][0]
4004                .as_object()
4005                .unwrap()
4006                .contains_key("optional")
4007        );
4008
4009        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
4010        match deserialized {
4011            AuthMethod::EnvVar(AuthMethodEnvVar {
4012                id,
4013                name: method_name,
4014                vars,
4015                link,
4016                ..
4017            }) => {
4018                assert_eq!(id.0.as_ref(), "api-key");
4019                assert_eq!(method_name, "API Key");
4020                assert_eq!(vars.len(), 1);
4021                assert_eq!(vars[0].name, "API_KEY");
4022                assert!(vars[0].secret);
4023                assert!(!vars[0].optional);
4024                assert!(link.is_none());
4025            }
4026            _ => panic!("Expected EnvVar variant"),
4027        }
4028    }
4029
4030    #[cfg(feature = "unstable_auth_methods")]
4031    #[test]
4032    fn test_auth_method_env_var_with_link_serialization() {
4033        let method = AuthMethod::EnvVar(
4034            AuthMethodEnvVar::new("api-key", "API Key", vec![AuthEnvVar::new("API_KEY")])
4035                .link("https://example.com/keys"),
4036        );
4037
4038        let json = serde_json::to_value(&method).unwrap();
4039        assert_eq!(
4040            json,
4041            json!({
4042                "id": "api-key",
4043                "name": "API Key",
4044                "type": "env_var",
4045                "vars": [{"name": "API_KEY"}],
4046                "link": "https://example.com/keys"
4047            })
4048        );
4049
4050        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
4051        match deserialized {
4052            AuthMethod::EnvVar(AuthMethodEnvVar { link, .. }) => {
4053                assert_eq!(link.as_deref(), Some("https://example.com/keys"));
4054            }
4055            _ => panic!("Expected EnvVar variant"),
4056        }
4057    }
4058
4059    #[cfg(feature = "unstable_auth_methods")]
4060    #[test]
4061    fn test_auth_method_env_var_multiple_vars() {
4062        let method = AuthMethod::EnvVar(AuthMethodEnvVar::new(
4063            "azure-openai",
4064            "Azure OpenAI",
4065            vec![
4066                AuthEnvVar::new("AZURE_OPENAI_API_KEY").label("API Key"),
4067                AuthEnvVar::new("AZURE_OPENAI_ENDPOINT")
4068                    .label("Endpoint URL")
4069                    .secret(false),
4070                AuthEnvVar::new("AZURE_OPENAI_API_VERSION")
4071                    .label("API Version")
4072                    .secret(false)
4073                    .optional(true),
4074            ],
4075        ));
4076
4077        let json = serde_json::to_value(&method).unwrap();
4078        assert_eq!(
4079            json,
4080            json!({
4081                "id": "azure-openai",
4082                "name": "Azure OpenAI",
4083                "type": "env_var",
4084                "vars": [
4085                    {"name": "AZURE_OPENAI_API_KEY", "label": "API Key"},
4086                    {"name": "AZURE_OPENAI_ENDPOINT", "label": "Endpoint URL", "secret": false},
4087                    {"name": "AZURE_OPENAI_API_VERSION", "label": "API Version", "secret": false, "optional": true}
4088                ]
4089            })
4090        );
4091
4092        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
4093        match deserialized {
4094            AuthMethod::EnvVar(AuthMethodEnvVar { vars, .. }) => {
4095                assert_eq!(vars.len(), 3);
4096                // First var: secret (default true), not optional (default false)
4097                assert_eq!(vars[0].name, "AZURE_OPENAI_API_KEY");
4098                assert_eq!(vars[0].label.as_deref(), Some("API Key"));
4099                assert!(vars[0].secret);
4100                assert!(!vars[0].optional);
4101                // Second var: not a secret, not optional
4102                assert_eq!(vars[1].name, "AZURE_OPENAI_ENDPOINT");
4103                assert!(!vars[1].secret);
4104                assert!(!vars[1].optional);
4105                // Third var: not a secret, optional
4106                assert_eq!(vars[2].name, "AZURE_OPENAI_API_VERSION");
4107                assert!(!vars[2].secret);
4108                assert!(vars[2].optional);
4109            }
4110            _ => panic!("Expected EnvVar variant"),
4111        }
4112    }
4113
4114    #[cfg(feature = "unstable_auth_methods")]
4115    #[test]
4116    fn test_auth_method_terminal_serialization() {
4117        let method = AuthMethod::Terminal(AuthMethodTerminal::new("tui-auth", "Terminal Auth"));
4118
4119        let json = serde_json::to_value(&method).unwrap();
4120        assert_eq!(
4121            json,
4122            json!({
4123                "id": "tui-auth",
4124                "name": "Terminal Auth",
4125                "type": "terminal"
4126            })
4127        );
4128        // args and env should be omitted when empty
4129        assert!(!json.as_object().unwrap().contains_key("args"));
4130        assert!(!json.as_object().unwrap().contains_key("env"));
4131
4132        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
4133        match deserialized {
4134            AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
4135                assert!(args.is_empty());
4136                assert!(env.is_empty());
4137            }
4138            _ => panic!("Expected Terminal variant"),
4139        }
4140    }
4141
4142    #[cfg(feature = "unstable_auth_methods")]
4143    #[test]
4144    fn test_auth_method_terminal_with_args_and_env_serialization() {
4145        use std::collections::HashMap;
4146
4147        let mut env = HashMap::new();
4148        env.insert("TERM".to_string(), "xterm-256color".to_string());
4149
4150        let method = AuthMethod::Terminal(
4151            AuthMethodTerminal::new("tui-auth", "Terminal Auth")
4152                .args(vec!["--interactive".to_string(), "--color".to_string()])
4153                .env(env),
4154        );
4155
4156        let json = serde_json::to_value(&method).unwrap();
4157        assert_eq!(
4158            json,
4159            json!({
4160                "id": "tui-auth",
4161                "name": "Terminal Auth",
4162                "type": "terminal",
4163                "args": ["--interactive", "--color"],
4164                "env": {
4165                    "TERM": "xterm-256color"
4166                }
4167            })
4168        );
4169
4170        let deserialized: AuthMethod = serde_json::from_value(json).unwrap();
4171        match deserialized {
4172            AuthMethod::Terminal(AuthMethodTerminal { args, env, .. }) => {
4173                assert_eq!(args, vec!["--interactive", "--color"]);
4174                assert_eq!(env.len(), 1);
4175                assert_eq!(env.get("TERM").unwrap(), "xterm-256color");
4176            }
4177            _ => panic!("Expected Terminal variant"),
4178        }
4179    }
4180}