Skip to main content

agent_client_protocol_schema/v1/
client.rs

1//! Methods and notifications the client handles/receives.
2//!
3//! This module defines the Client trait and all associated types for implementing
4//! a client that interacts with AI coding agents via the Agent Client Protocol (ACP).
5
6use std::{path::PathBuf, sync::Arc};
7
8use derive_more::{Display, From};
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
12
13#[cfg(feature = "unstable_elicitation")]
14use super::{
15    CompleteElicitationNotification, CreateElicitationRequest, CreateElicitationResponse,
16    ElicitationCapabilities,
17};
18use crate::{IntoMaybeUndefined, IntoOption, MaybeUndefined, SkipListener};
19
20use super::{
21    ContentBlock, EnvVariable, ExtNotification, ExtRequest, ExtResponse, Meta, Plan,
22    SessionConfigOption, SessionId, SessionModeId, ToolCall, ToolCallUpdate,
23};
24#[cfg(feature = "unstable_plan_operations")]
25use super::{PlanCapabilities, PlanRemoved, PlanUpdate};
26
27#[cfg(feature = "unstable_mcp_over_acp")]
28use super::mcp::{
29    ConnectMcpRequest, ConnectMcpResponse, DisconnectMcpRequest, DisconnectMcpResponse,
30    MCP_CONNECT_METHOD_NAME, MCP_DISCONNECT_METHOD_NAME, MCP_MESSAGE_METHOD_NAME,
31    MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
32};
33
34#[cfg(feature = "unstable_nes")]
35use super::{ClientNesCapabilities, PositionEncodingKind};
36
37// Session updates
38
39/// Notification containing a session update from the agent.
40///
41/// Used to stream real-time progress and results during prompt processing.
42///
43/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
44#[skip_serializing_none]
45#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
46#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
47#[serde(rename_all = "camelCase")]
48#[non_exhaustive]
49pub struct SessionNotification {
50    /// The ID of the session this update pertains to.
51    pub session_id: SessionId,
52    /// The actual update content.
53    pub update: SessionUpdate,
54    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
55    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
56    /// these keys.
57    ///
58    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
59    #[serde(rename = "_meta")]
60    pub meta: Option<Meta>,
61}
62
63impl SessionNotification {
64    /// Builds [`SessionNotification`] with the required notification fields set; optional fields start unset or empty.
65    #[must_use]
66    pub fn new(session_id: impl Into<SessionId>, update: SessionUpdate) -> Self {
67        Self {
68            session_id: session_id.into(),
69            update,
70            meta: None,
71        }
72    }
73
74    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
75    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
76    /// these keys.
77    ///
78    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
79    #[must_use]
80    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
81        self.meta = meta.into_option();
82        self
83    }
84}
85
86/// Different types of updates that can be sent during session processing.
87///
88/// These updates provide real-time feedback about the agent's progress.
89///
90/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
91#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
92#[serde(tag = "sessionUpdate", rename_all = "snake_case")]
93#[schemars(extend("discriminator" = {"propertyName": "sessionUpdate"}))]
94#[non_exhaustive]
95pub enum SessionUpdate {
96    /// A chunk of the user's message being streamed.
97    UserMessageChunk(ContentChunk),
98    /// A chunk of the agent's response being streamed.
99    AgentMessageChunk(ContentChunk),
100    /// A chunk of the agent's internal reasoning being streamed.
101    AgentThoughtChunk(ContentChunk),
102    /// Notification that a new tool call has been initiated.
103    ToolCall(ToolCall),
104    /// Update on the status or results of a tool call.
105    ToolCallUpdate(ToolCallUpdate),
106    /// The agent's execution plan for complex tasks.
107    /// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
108    Plan(Plan),
109    /// **UNSTABLE**
110    ///
111    /// This capability is not part of the spec yet, and may be removed or changed at any point.
112    ///
113    /// A content update for a plan identified by ID.
114    #[cfg(feature = "unstable_plan_operations")]
115    PlanUpdate(PlanUpdate),
116    /// **UNSTABLE**
117    ///
118    /// This capability is not part of the spec yet, and may be removed or changed at any point.
119    ///
120    /// Removal notice for a plan identified by ID.
121    #[cfg(feature = "unstable_plan_operations")]
122    PlanRemoved(PlanRemoved),
123    /// Available commands are ready or have changed
124    AvailableCommandsUpdate(AvailableCommandsUpdate),
125    /// The current mode of the session has changed
126    ///
127    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
128    CurrentModeUpdate(CurrentModeUpdate),
129    /// Session configuration options have been updated.
130    ConfigOptionUpdate(ConfigOptionUpdate),
131    /// Session metadata has been updated (title, timestamps, custom metadata)
132    SessionInfoUpdate(SessionInfoUpdate),
133    /// Context window and cost update for the session.
134    UsageUpdate(UsageUpdate),
135}
136
137/// The current mode of the session has changed
138///
139/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
140#[skip_serializing_none]
141#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
142#[serde(rename_all = "camelCase")]
143#[non_exhaustive]
144pub struct CurrentModeUpdate {
145    /// The ID of the current mode
146    pub current_mode_id: SessionModeId,
147    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
148    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
149    /// these keys.
150    ///
151    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
152    #[serde(rename = "_meta")]
153    pub meta: Option<Meta>,
154}
155
156impl CurrentModeUpdate {
157    /// Builds [`CurrentModeUpdate`] with the required fields set; optional fields start unset or empty.
158    #[must_use]
159    pub fn new(current_mode_id: impl Into<SessionModeId>) -> Self {
160        Self {
161            current_mode_id: current_mode_id.into(),
162            meta: None,
163        }
164    }
165
166    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
167    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
168    /// these keys.
169    ///
170    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
171    #[must_use]
172    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
173        self.meta = meta.into_option();
174        self
175    }
176}
177
178/// Session configuration options have been updated.
179#[serde_as]
180#[skip_serializing_none]
181#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
182#[serde(rename_all = "camelCase")]
183#[non_exhaustive]
184pub struct ConfigOptionUpdate {
185    /// The full set of configuration options and their current values.
186    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
187    #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
188    pub config_options: Vec<SessionConfigOption>,
189    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
190    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
191    /// these keys.
192    ///
193    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
194    #[serde(rename = "_meta")]
195    pub meta: Option<Meta>,
196}
197
198impl ConfigOptionUpdate {
199    /// Builds [`ConfigOptionUpdate`] with the required fields set; optional fields start unset or empty.
200    #[must_use]
201    pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
202        Self {
203            config_options,
204            meta: None,
205        }
206    }
207
208    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
209    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
210    /// these keys.
211    ///
212    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
213    #[must_use]
214    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
215        self.meta = meta.into_option();
216        self
217    }
218}
219
220/// Update to session metadata. All fields are optional to support partial updates.
221///
222/// Agents send this notification to update session information like title or custom metadata.
223/// This allows clients to display dynamic session names and track session state changes.
224#[skip_serializing_none]
225#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
226#[serde(rename_all = "camelCase")]
227#[non_exhaustive]
228pub struct SessionInfoUpdate {
229    /// Human-readable title for the session. Set to null to clear.
230    #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
231    pub title: MaybeUndefined<String>,
232    /// ISO 8601 timestamp of last activity. Set to null to clear.
233    #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
234    pub updated_at: MaybeUndefined<String>,
235    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
236    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
237    /// these keys.
238    ///
239    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
240    #[serde(rename = "_meta")]
241    pub meta: Option<Meta>,
242}
243
244impl SessionInfoUpdate {
245    /// Builds [`SessionInfoUpdate`] with the required fields set; optional fields start unset or empty.
246    #[must_use]
247    pub fn new() -> Self {
248        Self::default()
249    }
250
251    /// Human-readable title for the session. Set to null to clear.
252    #[must_use]
253    pub fn title(mut self, title: impl IntoMaybeUndefined<String>) -> Self {
254        self.title = title.into_maybe_undefined();
255        self
256    }
257
258    /// ISO 8601 timestamp of last activity. Set to null to clear.
259    #[must_use]
260    pub fn updated_at(mut self, updated_at: impl IntoMaybeUndefined<String>) -> Self {
261        self.updated_at = updated_at.into_maybe_undefined();
262        self
263    }
264
265    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
266    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
267    /// these keys.
268    ///
269    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
270    #[must_use]
271    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
272        self.meta = meta.into_option();
273        self
274    }
275}
276
277/// Context window and cost update for a session.
278#[serde_as]
279#[skip_serializing_none]
280#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
281#[serde(rename_all = "camelCase")]
282#[non_exhaustive]
283pub struct UsageUpdate {
284    /// Tokens currently in context.
285    pub used: u64,
286    /// Total context window size in tokens.
287    pub size: u64,
288    /// Cumulative session cost (optional).
289    #[serde_as(deserialize_as = "DefaultOnError")]
290    #[schemars(extend("x-deserialize-default-on-error" = true))]
291    #[serde(default)]
292    pub cost: Option<Cost>,
293    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
294    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
295    /// these keys.
296    ///
297    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
298    #[serde(rename = "_meta")]
299    pub meta: Option<Meta>,
300}
301
302impl UsageUpdate {
303    /// Builds [`UsageUpdate`] with the required fields set; optional fields start unset or empty.
304    #[must_use]
305    pub fn new(used: u64, size: u64) -> Self {
306        Self {
307            used,
308            size,
309            cost: None,
310            meta: None,
311        }
312    }
313
314    /// Cumulative session cost (optional).
315    #[must_use]
316    pub fn cost(mut self, cost: impl IntoOption<Cost>) -> Self {
317        self.cost = cost.into_option();
318        self
319    }
320
321    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
322    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
323    /// these keys.
324    ///
325    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
326    #[must_use]
327    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
328        self.meta = meta.into_option();
329        self
330    }
331}
332
333/// Cost information for a session.
334#[skip_serializing_none]
335#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
336#[serde(rename_all = "camelCase")]
337#[non_exhaustive]
338pub struct Cost {
339    /// Total cumulative cost for session.
340    pub amount: f64,
341    /// ISO 4217 currency code (e.g., "USD", "EUR").
342    pub currency: String,
343    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
344    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
345    /// these keys.
346    ///
347    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
348    #[serde(rename = "_meta")]
349    pub meta: Option<Meta>,
350}
351
352impl Cost {
353    /// Builds [`Cost`] with the required fields set; optional fields start unset or empty.
354    #[must_use]
355    pub fn new(amount: f64, currency: impl Into<String>) -> Self {
356        Self {
357            amount,
358            currency: currency.into(),
359            meta: None,
360        }
361    }
362
363    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
364    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
365    /// these keys.
366    ///
367    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
368    #[must_use]
369    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
370        self.meta = meta.into_option();
371        self
372    }
373}
374
375/// A streamed item of content
376#[skip_serializing_none]
377#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
378#[serde(rename_all = "camelCase")]
379#[non_exhaustive]
380pub struct ContentChunk {
381    /// A single item of content
382    pub content: ContentBlock,
383    /// A unique identifier for the message this chunk belongs to.
384    ///
385    /// All chunks belonging to the same message share the same `messageId`.
386    /// A change in `messageId` indicates a new message has started.
387    pub message_id: Option<MessageId>,
388    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
389    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
390    /// these keys.
391    ///
392    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
393    #[serde(rename = "_meta")]
394    pub meta: Option<Meta>,
395}
396
397impl ContentChunk {
398    /// Builds [`ContentChunk`] with the required fields set; optional fields start unset or empty.
399    #[must_use]
400    pub fn new(content: ContentBlock) -> Self {
401        Self {
402            content,
403            message_id: None,
404            meta: None,
405        }
406    }
407
408    /// A unique identifier for the message this chunk belongs to.
409    ///
410    /// All chunks belonging to the same message share the same `messageId`.
411    /// A change in `messageId` indicates a new message has started.
412    #[must_use]
413    pub fn message_id(mut self, message_id: impl IntoOption<MessageId>) -> Self {
414        self.message_id = message_id.into_option();
415        self
416    }
417
418    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
419    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
420    /// these keys.
421    ///
422    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
423    #[must_use]
424    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
425        self.meta = meta.into_option();
426        self
427    }
428}
429
430/// Unique identifier for a message within a session.
431#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
432#[serde(transparent)]
433#[from(Arc<str>, String, &'static str)]
434#[non_exhaustive]
435pub struct MessageId(pub Arc<str>);
436
437impl MessageId {
438    /// Wraps a protocol string as a typed [`MessageId`].
439    #[must_use]
440    pub fn new(id: impl Into<Arc<str>>) -> Self {
441        Self(id.into())
442    }
443}
444
445impl IntoOption<MessageId> for &str {
446    fn into_option(self) -> Option<MessageId> {
447        Some(MessageId::new(self))
448    }
449}
450
451/// Available commands are ready or have changed
452#[serde_as]
453#[skip_serializing_none]
454#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
455#[serde(rename_all = "camelCase")]
456#[non_exhaustive]
457pub struct AvailableCommandsUpdate {
458    /// Commands the agent can execute
459    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
460    #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
461    pub available_commands: Vec<AvailableCommand>,
462    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
463    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
464    /// these keys.
465    ///
466    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
467    #[serde(rename = "_meta")]
468    pub meta: Option<Meta>,
469}
470
471impl AvailableCommandsUpdate {
472    /// Builds [`AvailableCommandsUpdate`] with the required fields set; optional fields start unset or empty.
473    #[must_use]
474    pub fn new(available_commands: Vec<AvailableCommand>) -> Self {
475        Self {
476            available_commands,
477            meta: None,
478        }
479    }
480
481    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
482    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
483    /// these keys.
484    ///
485    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
486    #[must_use]
487    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
488        self.meta = meta.into_option();
489        self
490    }
491}
492
493/// Information about a command.
494#[serde_as]
495#[skip_serializing_none]
496#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
497#[serde(rename_all = "camelCase")]
498#[non_exhaustive]
499pub struct AvailableCommand {
500    /// Command name (e.g., `create_plan`, `research_codebase`).
501    pub name: String,
502    /// Human-readable description of what the command does.
503    pub description: String,
504    /// Input for the command if required
505    #[serde_as(deserialize_as = "DefaultOnError")]
506    #[schemars(extend("x-deserialize-default-on-error" = true))]
507    #[serde(default)]
508    pub input: Option<AvailableCommandInput>,
509    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
510    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
511    /// these keys.
512    ///
513    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
514    #[serde(rename = "_meta")]
515    pub meta: Option<Meta>,
516}
517
518impl AvailableCommand {
519    /// Builds [`AvailableCommand`] with the required fields set; optional fields start unset or empty.
520    #[must_use]
521    pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
522        Self {
523            name: name.into(),
524            description: description.into(),
525            input: None,
526            meta: None,
527        }
528    }
529
530    /// Input for the command if required
531    #[must_use]
532    pub fn input(mut self, input: impl IntoOption<AvailableCommandInput>) -> Self {
533        self.input = input.into_option();
534        self
535    }
536
537    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
538    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
539    /// these keys.
540    ///
541    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
542    #[must_use]
543    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
544        self.meta = meta.into_option();
545        self
546    }
547}
548
549/// The input specification for a command.
550#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
551#[serde(untagged, rename_all = "camelCase")]
552#[non_exhaustive]
553pub enum AvailableCommandInput {
554    /// All text that was typed after the command name is provided as input.
555    Unstructured(UnstructuredCommandInput),
556}
557
558/// All text that was typed after the command name is provided as input.
559#[skip_serializing_none]
560#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
561#[serde(rename_all = "camelCase")]
562#[non_exhaustive]
563pub struct UnstructuredCommandInput {
564    /// A hint to display when the input hasn't been provided yet
565    pub hint: String,
566    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
567    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
568    /// these keys.
569    ///
570    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
571    #[serde(rename = "_meta")]
572    pub meta: Option<Meta>,
573}
574
575impl UnstructuredCommandInput {
576    /// Builds [`UnstructuredCommandInput`] with the required fields set; optional fields start unset or empty.
577    #[must_use]
578    pub fn new(hint: impl Into<String>) -> Self {
579        Self {
580            hint: hint.into(),
581            meta: None,
582        }
583    }
584
585    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
586    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
587    /// these keys.
588    ///
589    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
590    #[must_use]
591    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
592        self.meta = meta.into_option();
593        self
594    }
595}
596
597// Permission
598
599/// Request for user permission to execute a tool call.
600///
601/// Sent when the agent needs authorization before performing a sensitive operation.
602///
603/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
604#[skip_serializing_none]
605#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
606#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
607#[serde(rename_all = "camelCase")]
608#[non_exhaustive]
609pub struct RequestPermissionRequest {
610    /// The session ID for this request.
611    pub session_id: SessionId,
612    /// Details about the tool call requiring permission.
613    pub tool_call: ToolCallUpdate,
614    /// Available permission options for the user to choose from.
615    pub options: Vec<PermissionOption>,
616    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
617    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
618    /// these keys.
619    ///
620    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
621    #[serde(rename = "_meta")]
622    pub meta: Option<Meta>,
623}
624
625impl RequestPermissionRequest {
626    /// Builds [`RequestPermissionRequest`] with the required request fields set; optional fields start unset or empty.
627    #[must_use]
628    pub fn new(
629        session_id: impl Into<SessionId>,
630        tool_call: ToolCallUpdate,
631        options: Vec<PermissionOption>,
632    ) -> Self {
633        Self {
634            session_id: session_id.into(),
635            tool_call,
636            options,
637            meta: None,
638        }
639    }
640
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    #[must_use]
647    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
648        self.meta = meta.into_option();
649        self
650    }
651}
652
653/// An option presented to the user when requesting permission.
654#[skip_serializing_none]
655#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
656#[serde(rename_all = "camelCase")]
657#[non_exhaustive]
658pub struct PermissionOption {
659    /// Unique identifier for this permission option.
660    pub option_id: PermissionOptionId,
661    /// Human-readable label to display to the user.
662    pub name: String,
663    /// Hint about the nature of this permission option.
664    pub kind: PermissionOptionKind,
665    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
666    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
667    /// these keys.
668    ///
669    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
670    #[serde(rename = "_meta")]
671    pub meta: Option<Meta>,
672}
673
674impl PermissionOption {
675    /// Builds [`PermissionOption`] with the required fields set; optional fields start unset or empty.
676    #[must_use]
677    pub fn new(
678        option_id: impl Into<PermissionOptionId>,
679        name: impl Into<String>,
680        kind: PermissionOptionKind,
681    ) -> Self {
682        Self {
683            option_id: option_id.into(),
684            name: name.into(),
685            kind,
686            meta: None,
687        }
688    }
689
690    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
691    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
692    /// these keys.
693    ///
694    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
695    #[must_use]
696    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
697        self.meta = meta.into_option();
698        self
699    }
700}
701
702/// Unique identifier for a permission option.
703#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
704#[serde(transparent)]
705#[from(Arc<str>, String, &'static str)]
706#[non_exhaustive]
707pub struct PermissionOptionId(pub Arc<str>);
708
709impl PermissionOptionId {
710    /// Wraps a protocol string as a typed [`PermissionOptionId`].
711    #[must_use]
712    pub fn new(id: impl Into<Arc<str>>) -> Self {
713        Self(id.into())
714    }
715}
716
717/// The type of permission option being presented to the user.
718///
719/// Helps clients choose appropriate icons and UI treatment.
720#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
721#[serde(rename_all = "snake_case")]
722#[non_exhaustive]
723pub enum PermissionOptionKind {
724    /// Allow this operation only this time.
725    AllowOnce,
726    /// Allow this operation and remember the choice.
727    AllowAlways,
728    /// Reject this operation only this time.
729    RejectOnce,
730    /// Reject this operation and remember the choice.
731    RejectAlways,
732}
733
734/// Response to a permission request.
735#[skip_serializing_none]
736#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
737#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
738#[serde(rename_all = "camelCase")]
739#[non_exhaustive]
740pub struct RequestPermissionResponse {
741    /// The user's decision on the permission request.
742    // This extra-level is unfortunately needed because the output must be an object
743    pub outcome: RequestPermissionOutcome,
744    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
745    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
746    /// these keys.
747    ///
748    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
749    #[serde(rename = "_meta")]
750    pub meta: Option<Meta>,
751}
752
753impl RequestPermissionResponse {
754    /// Builds [`RequestPermissionResponse`] with the required response fields set; optional fields start unset or empty.
755    #[must_use]
756    pub fn new(outcome: RequestPermissionOutcome) -> Self {
757        Self {
758            outcome,
759            meta: None,
760        }
761    }
762
763    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
764    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
765    /// these keys.
766    ///
767    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
768    #[must_use]
769    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
770        self.meta = meta.into_option();
771        self
772    }
773}
774
775/// The outcome of a permission request.
776#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
777#[serde(tag = "outcome", rename_all = "snake_case")]
778#[schemars(extend("discriminator" = {"propertyName": "outcome"}))]
779#[non_exhaustive]
780pub enum RequestPermissionOutcome {
781    /// The prompt turn was cancelled before the user responded.
782    ///
783    /// When a client sends a `session/cancel` notification to cancel an ongoing
784    /// prompt turn, it MUST respond to all pending `session/request_permission`
785    /// requests with this `Cancelled` outcome.
786    ///
787    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
788    Cancelled,
789    /// The user selected one of the provided options.
790    #[serde(rename_all = "camelCase")]
791    Selected(SelectedPermissionOutcome),
792}
793
794/// The user selected one of the provided options.
795#[skip_serializing_none]
796#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
797#[serde(rename_all = "camelCase")]
798#[non_exhaustive]
799pub struct SelectedPermissionOutcome {
800    /// The ID of the option the user selected.
801    pub option_id: PermissionOptionId,
802    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
803    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
804    /// these keys.
805    ///
806    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
807    #[serde(rename = "_meta")]
808    pub meta: Option<Meta>,
809}
810
811impl SelectedPermissionOutcome {
812    /// Builds [`SelectedPermissionOutcome`] with the required fields set; optional fields start unset or empty.
813    #[must_use]
814    pub fn new(option_id: impl Into<PermissionOptionId>) -> Self {
815        Self {
816            option_id: option_id.into(),
817            meta: None,
818        }
819    }
820
821    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
822    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
823    /// these keys.
824    ///
825    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
826    #[must_use]
827    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
828        self.meta = meta.into_option();
829        self
830    }
831}
832
833// Write text file
834
835/// Request to write content to a text file.
836///
837/// Only available if the client supports the `fs.writeTextFile` capability.
838#[skip_serializing_none]
839#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
840#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
841#[serde(rename_all = "camelCase")]
842#[non_exhaustive]
843pub struct WriteTextFileRequest {
844    /// The session ID for this request.
845    pub session_id: SessionId,
846    /// Absolute path to the file to write.
847    pub path: PathBuf,
848    /// The text content to write to the file.
849    pub content: String,
850    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
851    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
852    /// these keys.
853    ///
854    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
855    #[serde(rename = "_meta")]
856    pub meta: Option<Meta>,
857}
858
859impl WriteTextFileRequest {
860    /// Builds [`WriteTextFileRequest`] with the required request fields set; optional fields start unset or empty.
861    #[must_use]
862    pub fn new(
863        session_id: impl Into<SessionId>,
864        path: impl Into<PathBuf>,
865        content: impl Into<String>,
866    ) -> Self {
867        Self {
868            session_id: session_id.into(),
869            path: path.into(),
870            content: content.into(),
871            meta: None,
872        }
873    }
874
875    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
876    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
877    /// these keys.
878    ///
879    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
880    #[must_use]
881    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
882        self.meta = meta.into_option();
883        self
884    }
885}
886
887/// Response to `fs/write_text_file`
888#[skip_serializing_none]
889#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
890#[serde(rename_all = "camelCase")]
891#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
892#[non_exhaustive]
893pub struct WriteTextFileResponse {
894    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
895    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
896    /// these keys.
897    ///
898    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
899    #[serde(rename = "_meta")]
900    pub meta: Option<Meta>,
901}
902
903impl WriteTextFileResponse {
904    /// Builds [`WriteTextFileResponse`] with the required response fields set; optional fields start unset or empty.
905    #[must_use]
906    pub fn new() -> Self {
907        Self::default()
908    }
909
910    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
911    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
912    /// these keys.
913    ///
914    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
915    #[must_use]
916    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
917        self.meta = meta.into_option();
918        self
919    }
920}
921
922// Read text file
923
924/// Request to read content from a text file.
925///
926/// Only available if the client supports the `fs.readTextFile` capability.
927#[skip_serializing_none]
928#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
929#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
930#[serde(rename_all = "camelCase")]
931#[non_exhaustive]
932pub struct ReadTextFileRequest {
933    /// The session ID for this request.
934    pub session_id: SessionId,
935    /// Absolute path to the file to read.
936    pub path: PathBuf,
937    /// Line number to start reading from (1-based).
938    pub line: Option<u32>,
939    /// Maximum number of lines to read.
940    pub limit: Option<u32>,
941    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
942    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
943    /// these keys.
944    ///
945    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
946    #[serde(rename = "_meta")]
947    pub meta: Option<Meta>,
948}
949
950impl ReadTextFileRequest {
951    /// Builds [`ReadTextFileRequest`] with the required request fields set; optional fields start unset or empty.
952    #[must_use]
953    pub fn new(session_id: impl Into<SessionId>, path: impl Into<PathBuf>) -> Self {
954        Self {
955            session_id: session_id.into(),
956            path: path.into(),
957            line: None,
958            limit: None,
959            meta: None,
960        }
961    }
962
963    /// Line number to start reading from (1-based).
964    #[must_use]
965    pub fn line(mut self, line: impl IntoOption<u32>) -> Self {
966        self.line = line.into_option();
967        self
968    }
969
970    /// Maximum number of lines to read.
971    #[must_use]
972    pub fn limit(mut self, limit: impl IntoOption<u32>) -> Self {
973        self.limit = limit.into_option();
974        self
975    }
976
977    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
978    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
979    /// these keys.
980    ///
981    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
982    #[must_use]
983    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
984        self.meta = meta.into_option();
985        self
986    }
987}
988
989/// Response containing the contents of a text file.
990#[skip_serializing_none]
991#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
992#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
993#[serde(rename_all = "camelCase")]
994#[non_exhaustive]
995pub struct ReadTextFileResponse {
996    /// Content payload returned by this response.
997    pub content: String,
998    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
999    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1000    /// these keys.
1001    ///
1002    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1003    #[serde(rename = "_meta")]
1004    pub meta: Option<Meta>,
1005}
1006
1007impl ReadTextFileResponse {
1008    /// Builds [`ReadTextFileResponse`] with the required response fields set; optional fields start unset or empty.
1009    #[must_use]
1010    pub fn new(content: impl Into<String>) -> Self {
1011        Self {
1012            content: content.into(),
1013            meta: None,
1014        }
1015    }
1016
1017    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1018    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1019    /// these keys.
1020    ///
1021    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1022    #[must_use]
1023    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1024        self.meta = meta.into_option();
1025        self
1026    }
1027}
1028
1029// Terminals
1030
1031/// Typed identifier used for terminal values on the wire.
1032#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
1033#[serde(transparent)]
1034#[from(Arc<str>, String, &'static str)]
1035#[non_exhaustive]
1036pub struct TerminalId(pub Arc<str>);
1037
1038impl TerminalId {
1039    /// Wraps a protocol string as a typed [`TerminalId`].
1040    #[must_use]
1041    pub fn new(id: impl Into<Arc<str>>) -> Self {
1042        Self(id.into())
1043    }
1044}
1045
1046/// Request to create a new terminal and execute a command.
1047#[skip_serializing_none]
1048#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1049#[serde(rename_all = "camelCase")]
1050#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1051#[non_exhaustive]
1052pub struct CreateTerminalRequest {
1053    /// The session ID for this request.
1054    pub session_id: SessionId,
1055    /// The command to execute.
1056    pub command: String,
1057    /// Array of command arguments.
1058    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1059    pub args: Vec<String>,
1060    /// Environment variables for the command.
1061    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1062    pub env: Vec<EnvVariable>,
1063    /// Working directory for the command (absolute path).
1064    pub cwd: Option<PathBuf>,
1065    /// Maximum number of output bytes to retain.
1066    ///
1067    /// When the limit is exceeded, the Client truncates from the beginning of the output
1068    /// to stay within the limit.
1069    ///
1070    /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1071    /// string output, even if this means the retained output is slightly less than the
1072    /// specified limit.
1073    pub output_byte_limit: Option<u64>,
1074    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1075    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1076    /// these keys.
1077    ///
1078    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1079    #[serde(rename = "_meta")]
1080    pub meta: Option<Meta>,
1081}
1082
1083impl CreateTerminalRequest {
1084    /// Builds [`CreateTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1085    #[must_use]
1086    pub fn new(session_id: impl Into<SessionId>, command: impl Into<String>) -> Self {
1087        Self {
1088            session_id: session_id.into(),
1089            command: command.into(),
1090            args: Vec::new(),
1091            env: Vec::new(),
1092            cwd: None,
1093            output_byte_limit: None,
1094            meta: None,
1095        }
1096    }
1097
1098    /// Array of command arguments.
1099    #[must_use]
1100    pub fn args(mut self, args: Vec<String>) -> Self {
1101        self.args = args;
1102        self
1103    }
1104
1105    /// Environment variables for the command.
1106    #[must_use]
1107    pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
1108        self.env = env;
1109        self
1110    }
1111
1112    /// Working directory for the command (absolute path).
1113    #[must_use]
1114    pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1115        self.cwd = cwd.into_option();
1116        self
1117    }
1118
1119    /// Maximum number of output bytes to retain.
1120    ///
1121    /// When the limit is exceeded, the Client truncates from the beginning of the output
1122    /// to stay within the limit.
1123    ///
1124    /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1125    /// string output, even if this means the retained output is slightly less than the
1126    /// specified limit.
1127    #[must_use]
1128    pub fn output_byte_limit(mut self, output_byte_limit: impl IntoOption<u64>) -> Self {
1129        self.output_byte_limit = output_byte_limit.into_option();
1130        self
1131    }
1132
1133    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1134    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1135    /// these keys.
1136    ///
1137    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1138    #[must_use]
1139    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1140        self.meta = meta.into_option();
1141        self
1142    }
1143}
1144
1145/// Response containing the ID of the created terminal.
1146#[skip_serializing_none]
1147#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1148#[serde(rename_all = "camelCase")]
1149#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1150#[non_exhaustive]
1151pub struct CreateTerminalResponse {
1152    /// The unique identifier for the created terminal.
1153    pub terminal_id: TerminalId,
1154    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1155    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1156    /// these keys.
1157    ///
1158    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1159    #[serde(rename = "_meta")]
1160    pub meta: Option<Meta>,
1161}
1162
1163impl CreateTerminalResponse {
1164    /// Builds [`CreateTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1165    #[must_use]
1166    pub fn new(terminal_id: impl Into<TerminalId>) -> Self {
1167        Self {
1168            terminal_id: terminal_id.into(),
1169            meta: None,
1170        }
1171    }
1172
1173    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1174    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1175    /// these keys.
1176    ///
1177    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1178    #[must_use]
1179    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1180        self.meta = meta.into_option();
1181        self
1182    }
1183}
1184
1185/// Request to get the current output and status of a terminal.
1186#[skip_serializing_none]
1187#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1188#[serde(rename_all = "camelCase")]
1189#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1190#[non_exhaustive]
1191pub struct TerminalOutputRequest {
1192    /// The session ID for this request.
1193    pub session_id: SessionId,
1194    /// The ID of the terminal to get output from.
1195    pub terminal_id: TerminalId,
1196    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1197    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1198    /// these keys.
1199    ///
1200    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1201    #[serde(rename = "_meta")]
1202    pub meta: Option<Meta>,
1203}
1204
1205impl TerminalOutputRequest {
1206    /// Builds [`TerminalOutputRequest`] with the required request fields set; optional fields start unset or empty.
1207    #[must_use]
1208    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1209        Self {
1210            session_id: session_id.into(),
1211            terminal_id: terminal_id.into(),
1212            meta: None,
1213        }
1214    }
1215
1216    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1217    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1218    /// these keys.
1219    ///
1220    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1221    #[must_use]
1222    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1223        self.meta = meta.into_option();
1224        self
1225    }
1226}
1227
1228/// Response containing the terminal output and exit status.
1229#[skip_serializing_none]
1230#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1231#[serde(rename_all = "camelCase")]
1232#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1233#[non_exhaustive]
1234pub struct TerminalOutputResponse {
1235    /// The terminal output captured so far.
1236    pub output: String,
1237    /// Whether the output was truncated due to byte limits.
1238    pub truncated: bool,
1239    /// Exit status if the command has completed.
1240    pub exit_status: Option<TerminalExitStatus>,
1241    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1242    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1243    /// these keys.
1244    ///
1245    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1246    #[serde(rename = "_meta")]
1247    pub meta: Option<Meta>,
1248}
1249
1250impl TerminalOutputResponse {
1251    /// Builds [`TerminalOutputResponse`] with the required response fields set; optional fields start unset or empty.
1252    #[must_use]
1253    pub fn new(output: impl Into<String>, truncated: bool) -> Self {
1254        Self {
1255            output: output.into(),
1256            truncated,
1257            exit_status: None,
1258            meta: None,
1259        }
1260    }
1261
1262    /// Exit status if the command has completed.
1263    #[must_use]
1264    pub fn exit_status(mut self, exit_status: impl IntoOption<TerminalExitStatus>) -> Self {
1265        self.exit_status = exit_status.into_option();
1266        self
1267    }
1268
1269    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1270    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1271    /// these keys.
1272    ///
1273    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1274    #[must_use]
1275    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1276        self.meta = meta.into_option();
1277        self
1278    }
1279}
1280
1281/// Request to release a terminal and free its resources.
1282#[skip_serializing_none]
1283#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1284#[serde(rename_all = "camelCase")]
1285#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1286#[non_exhaustive]
1287pub struct ReleaseTerminalRequest {
1288    /// The session ID for this request.
1289    pub session_id: SessionId,
1290    /// The ID of the terminal to release.
1291    pub terminal_id: TerminalId,
1292    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1293    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1294    /// these keys.
1295    ///
1296    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1297    #[serde(rename = "_meta")]
1298    pub meta: Option<Meta>,
1299}
1300
1301impl ReleaseTerminalRequest {
1302    /// Builds [`ReleaseTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1303    #[must_use]
1304    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1305        Self {
1306            session_id: session_id.into(),
1307            terminal_id: terminal_id.into(),
1308            meta: None,
1309        }
1310    }
1311
1312    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1313    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1314    /// these keys.
1315    ///
1316    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1317    #[must_use]
1318    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1319        self.meta = meta.into_option();
1320        self
1321    }
1322}
1323
1324/// Response to terminal/release method
1325#[skip_serializing_none]
1326#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1327#[serde(rename_all = "camelCase")]
1328#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1329#[non_exhaustive]
1330pub struct ReleaseTerminalResponse {
1331    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1332    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1333    /// these keys.
1334    ///
1335    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1336    #[serde(rename = "_meta")]
1337    pub meta: Option<Meta>,
1338}
1339
1340impl ReleaseTerminalResponse {
1341    /// Builds [`ReleaseTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1342    #[must_use]
1343    pub fn new() -> Self {
1344        Self::default()
1345    }
1346
1347    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1348    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1349    /// these keys.
1350    ///
1351    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1352    #[must_use]
1353    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1354        self.meta = meta.into_option();
1355        self
1356    }
1357}
1358
1359/// Request to kill a terminal without releasing it.
1360#[skip_serializing_none]
1361#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1362#[serde(rename_all = "camelCase")]
1363#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1364#[non_exhaustive]
1365pub struct KillTerminalRequest {
1366    /// The session ID for this request.
1367    pub session_id: SessionId,
1368    /// The ID of the terminal to kill.
1369    pub terminal_id: TerminalId,
1370    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1371    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1372    /// these keys.
1373    ///
1374    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1375    #[serde(rename = "_meta")]
1376    pub meta: Option<Meta>,
1377}
1378
1379impl KillTerminalRequest {
1380    /// Builds [`KillTerminalRequest`] with the required request fields set; optional fields start unset or empty.
1381    #[must_use]
1382    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1383        Self {
1384            session_id: session_id.into(),
1385            terminal_id: terminal_id.into(),
1386            meta: None,
1387        }
1388    }
1389
1390    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1391    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1392    /// these keys.
1393    ///
1394    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1395    #[must_use]
1396    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1397        self.meta = meta.into_option();
1398        self
1399    }
1400}
1401
1402/// Response to `terminal/kill` method
1403#[skip_serializing_none]
1404#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1405#[serde(rename_all = "camelCase")]
1406#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1407#[non_exhaustive]
1408pub struct KillTerminalResponse {
1409    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1410    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1411    /// these keys.
1412    ///
1413    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1414    #[serde(rename = "_meta")]
1415    pub meta: Option<Meta>,
1416}
1417
1418impl KillTerminalResponse {
1419    /// Builds [`KillTerminalResponse`] with the required response fields set; optional fields start unset or empty.
1420    #[must_use]
1421    pub fn new() -> Self {
1422        Self::default()
1423    }
1424
1425    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1426    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1427    /// these keys.
1428    ///
1429    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1430    #[must_use]
1431    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1432        self.meta = meta.into_option();
1433        self
1434    }
1435}
1436
1437/// Request to wait for a terminal command to exit.
1438#[skip_serializing_none]
1439#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1440#[serde(rename_all = "camelCase")]
1441#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1442#[non_exhaustive]
1443pub struct WaitForTerminalExitRequest {
1444    /// The session ID for this request.
1445    pub session_id: SessionId,
1446    /// The ID of the terminal to wait for.
1447    pub terminal_id: TerminalId,
1448    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1449    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1450    /// these keys.
1451    ///
1452    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1453    #[serde(rename = "_meta")]
1454    pub meta: Option<Meta>,
1455}
1456
1457impl WaitForTerminalExitRequest {
1458    /// Builds [`WaitForTerminalExitRequest`] with the required request fields set; optional fields start unset or empty.
1459    #[must_use]
1460    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1461        Self {
1462            session_id: session_id.into(),
1463            terminal_id: terminal_id.into(),
1464            meta: None,
1465        }
1466    }
1467
1468    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1469    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1470    /// these keys.
1471    ///
1472    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1473    #[must_use]
1474    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1475        self.meta = meta.into_option();
1476        self
1477    }
1478}
1479
1480/// Response containing the exit status of a terminal command.
1481#[skip_serializing_none]
1482#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1483#[serde(rename_all = "camelCase")]
1484#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1485#[non_exhaustive]
1486pub struct WaitForTerminalExitResponse {
1487    /// The exit status of the terminal command.
1488    #[serde(flatten)]
1489    pub exit_status: TerminalExitStatus,
1490    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1491    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1492    /// these keys.
1493    ///
1494    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1495    #[serde(rename = "_meta")]
1496    pub meta: Option<Meta>,
1497}
1498
1499impl WaitForTerminalExitResponse {
1500    /// Builds [`WaitForTerminalExitResponse`] with the required response fields set; optional fields start unset or empty.
1501    #[must_use]
1502    pub fn new(exit_status: TerminalExitStatus) -> Self {
1503        Self {
1504            exit_status,
1505            meta: None,
1506        }
1507    }
1508
1509    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1510    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1511    /// these keys.
1512    ///
1513    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1514    #[must_use]
1515    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1516        self.meta = meta.into_option();
1517        self
1518    }
1519}
1520
1521/// Exit status of a terminal command.
1522#[skip_serializing_none]
1523#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1524#[serde(rename_all = "camelCase")]
1525#[non_exhaustive]
1526pub struct TerminalExitStatus {
1527    /// The process exit code (may be null if terminated by signal).
1528    pub exit_code: Option<u32>,
1529    /// The signal that terminated the process (may be null if exited normally).
1530    pub signal: Option<String>,
1531    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1532    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1533    /// these keys.
1534    ///
1535    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1536    #[serde(rename = "_meta")]
1537    pub meta: Option<Meta>,
1538}
1539
1540impl TerminalExitStatus {
1541    /// Builds [`TerminalExitStatus`] with the required fields set; optional fields start unset or empty.
1542    #[must_use]
1543    pub fn new() -> Self {
1544        Self::default()
1545    }
1546
1547    /// The process exit code (may be null if terminated by signal).
1548    #[must_use]
1549    pub fn exit_code(mut self, exit_code: impl IntoOption<u32>) -> Self {
1550        self.exit_code = exit_code.into_option();
1551        self
1552    }
1553
1554    /// The signal that terminated the process (may be null if exited normally).
1555    #[must_use]
1556    pub fn signal(mut self, signal: impl IntoOption<String>) -> Self {
1557        self.signal = signal.into_option();
1558        self
1559    }
1560
1561    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1562    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1563    /// these keys.
1564    ///
1565    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1566    #[must_use]
1567    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1568        self.meta = meta.into_option();
1569        self
1570    }
1571}
1572
1573// Capabilities
1574
1575/// Capabilities supported by the client.
1576///
1577/// Advertised during initialization to inform the agent about
1578/// available features and methods.
1579///
1580/// See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities)
1581#[serde_as]
1582#[skip_serializing_none]
1583#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1584#[serde(rename_all = "camelCase")]
1585#[non_exhaustive]
1586pub struct ClientCapabilities {
1587    /// File system capabilities supported by the client.
1588    /// Determines which file operations the agent can request.
1589    #[serde(default)]
1590    pub fs: FileSystemCapabilities,
1591    /// Whether the Client support all `terminal/*` methods.
1592    #[serde(default)]
1593    pub terminal: bool,
1594    /// **UNSTABLE**
1595    ///
1596    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1597    ///
1598    /// Session-related capabilities supported by the client.
1599    #[cfg(feature = "unstable_boolean_config")]
1600    #[serde_as(deserialize_as = "DefaultOnError")]
1601    #[schemars(extend("x-deserialize-default-on-error" = true))]
1602    #[serde(default)]
1603    pub session: Option<ClientSessionCapabilities>,
1604    /// **UNSTABLE**
1605    ///
1606    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1607    ///
1608    /// Whether the client supports `plan_update` and `plan_removed` session updates.
1609    ///
1610    /// Optional. Omitted means the client does not advertise support.
1611    /// Supplying `{}` means the client can receive both update types.
1612    #[cfg(feature = "unstable_plan_operations")]
1613    #[serde_as(deserialize_as = "DefaultOnError")]
1614    #[schemars(extend("x-deserialize-default-on-error" = true))]
1615    #[serde(default)]
1616    pub plan: Option<PlanCapabilities>,
1617    /// **UNSTABLE**
1618    ///
1619    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1620    ///
1621    /// Authentication capabilities supported by the client.
1622    /// Determines which authentication method types the agent may include
1623    /// in its `InitializeResponse`.
1624    #[cfg(feature = "unstable_auth_methods")]
1625    #[serde(default)]
1626    pub auth: AuthCapabilities,
1627    /// **UNSTABLE**
1628    ///
1629    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1630    ///
1631    /// Elicitation capabilities supported by the client.
1632    /// Determines which elicitation modes the agent may use.
1633    #[cfg(feature = "unstable_elicitation")]
1634    #[serde_as(deserialize_as = "DefaultOnError")]
1635    #[schemars(extend("x-deserialize-default-on-error" = true))]
1636    #[serde(default)]
1637    pub elicitation: Option<ElicitationCapabilities>,
1638    /// **UNSTABLE**
1639    ///
1640    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1641    ///
1642    /// NES (Next Edit Suggestions) capabilities supported by the client.
1643    #[cfg(feature = "unstable_nes")]
1644    #[serde_as(deserialize_as = "DefaultOnError")]
1645    #[schemars(extend("x-deserialize-default-on-error" = true))]
1646    #[serde(default)]
1647    pub nes: Option<ClientNesCapabilities>,
1648    /// **UNSTABLE**
1649    ///
1650    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1651    ///
1652    /// The position encodings supported by the client, in order of preference.
1653    #[cfg(feature = "unstable_nes")]
1654    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1655    #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1656    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1657    pub position_encodings: Vec<PositionEncodingKind>,
1658
1659    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1660    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1661    /// these keys.
1662    ///
1663    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1664    #[serde(rename = "_meta")]
1665    pub meta: Option<Meta>,
1666}
1667
1668impl ClientCapabilities {
1669    /// Builds an empty [`ClientCapabilities`]; use builder methods to advertise supported sub-capabilities.
1670    #[must_use]
1671    pub fn new() -> Self {
1672        Self::default()
1673    }
1674
1675    /// File system capabilities supported by the client.
1676    /// Determines which file operations the agent can request.
1677    #[must_use]
1678    pub fn fs(mut self, fs: FileSystemCapabilities) -> Self {
1679        self.fs = fs;
1680        self
1681    }
1682
1683    /// Whether the Client support all `terminal/*` methods.
1684    #[must_use]
1685    pub fn terminal(mut self, terminal: bool) -> Self {
1686        self.terminal = terminal;
1687        self
1688    }
1689
1690    /// **UNSTABLE**
1691    ///
1692    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1693    ///
1694    /// Session-related capabilities supported by the client.
1695    #[cfg(feature = "unstable_boolean_config")]
1696    #[must_use]
1697    pub fn session(mut self, session: impl IntoOption<ClientSessionCapabilities>) -> Self {
1698        self.session = session.into_option();
1699        self
1700    }
1701
1702    /// **UNSTABLE**
1703    ///
1704    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1705    ///
1706    /// Whether the client supports `plan_update` and `plan_removed` session updates.
1707    ///
1708    /// Omitted means the client does not advertise support.
1709    /// Supplying `{}` means the client can receive both update types.
1710    #[cfg(feature = "unstable_plan_operations")]
1711    #[must_use]
1712    pub fn plan(mut self, plan: impl IntoOption<PlanCapabilities>) -> Self {
1713        self.plan = plan.into_option();
1714        self
1715    }
1716
1717    /// **UNSTABLE**
1718    ///
1719    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1720    ///
1721    /// Authentication capabilities supported by the client.
1722    /// Determines which authentication method types the agent may include
1723    /// in its `InitializeResponse`.
1724    #[cfg(feature = "unstable_auth_methods")]
1725    #[must_use]
1726    pub fn auth(mut self, auth: AuthCapabilities) -> Self {
1727        self.auth = auth;
1728        self
1729    }
1730
1731    /// **UNSTABLE**
1732    ///
1733    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1734    ///
1735    /// Elicitation capabilities supported by the client.
1736    /// Determines which elicitation modes the agent may use.
1737    #[cfg(feature = "unstable_elicitation")]
1738    #[must_use]
1739    pub fn elicitation(mut self, elicitation: impl IntoOption<ElicitationCapabilities>) -> Self {
1740        self.elicitation = elicitation.into_option();
1741        self
1742    }
1743
1744    /// **UNSTABLE**
1745    ///
1746    /// NES (Next Edit Suggestions) capabilities supported by the client.
1747    #[cfg(feature = "unstable_nes")]
1748    #[must_use]
1749    pub fn nes(mut self, nes: impl IntoOption<ClientNesCapabilities>) -> Self {
1750        self.nes = nes.into_option();
1751        self
1752    }
1753
1754    /// **UNSTABLE**
1755    ///
1756    /// The position encodings supported by the client, in order of preference.
1757    #[cfg(feature = "unstable_nes")]
1758    #[must_use]
1759    pub fn position_encodings(mut self, position_encodings: Vec<PositionEncodingKind>) -> Self {
1760        self.position_encodings = position_encodings;
1761        self
1762    }
1763
1764    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1765    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1766    /// these keys.
1767    ///
1768    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1769    #[must_use]
1770    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1771        self.meta = meta.into_option();
1772        self
1773    }
1774}
1775
1776/// **UNSTABLE**
1777///
1778/// This capability is not part of the spec yet, and may be removed or changed at any point.
1779///
1780/// Session-related capabilities supported by the client.
1781#[cfg(feature = "unstable_boolean_config")]
1782#[serde_as]
1783#[skip_serializing_none]
1784#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1785#[serde(rename_all = "camelCase")]
1786#[non_exhaustive]
1787pub struct ClientSessionCapabilities {
1788    /// Config option capabilities supported by the client.
1789    ///
1790    /// Omitted or `null` means the client does not advertise support for any
1791    /// config option extensions.
1792    #[serde_as(deserialize_as = "DefaultOnError")]
1793    #[schemars(extend("x-deserialize-default-on-error" = true))]
1794    #[serde(default)]
1795    pub config_options: Option<SessionConfigOptionsCapabilities>,
1796    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1797    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1798    /// these keys.
1799    ///
1800    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1801    #[serde(rename = "_meta")]
1802    pub meta: Option<Meta>,
1803}
1804
1805#[cfg(feature = "unstable_boolean_config")]
1806impl ClientSessionCapabilities {
1807    /// Builds an empty [`ClientSessionCapabilities`]; use builder methods to advertise supported sub-capabilities.
1808    #[must_use]
1809    pub fn new() -> Self {
1810        Self::default()
1811    }
1812
1813    /// Config option capabilities supported by the client.
1814    ///
1815    /// Omitted or `null` means the client does not advertise support for any
1816    /// config option extensions.
1817    #[must_use]
1818    pub fn config_options(
1819        mut self,
1820        config_options: impl IntoOption<SessionConfigOptionsCapabilities>,
1821    ) -> Self {
1822        self.config_options = config_options.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/// **UNSTABLE**
1839///
1840/// This capability is not part of the spec yet, and may be removed or changed at any point.
1841///
1842/// Session configuration option capabilities supported by the client.
1843#[cfg(feature = "unstable_boolean_config")]
1844#[serde_as]
1845#[skip_serializing_none]
1846#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1847#[serde(rename_all = "camelCase")]
1848#[non_exhaustive]
1849pub struct SessionConfigOptionsCapabilities {
1850    /// Whether the client supports boolean session configuration options.
1851    ///
1852    /// Omitted or `null` means the client does not advertise support.
1853    /// Supplying `{}` means agents may include `type: "boolean"` entries in
1854    /// `configOptions`, and the client may send `session/set_config_option`
1855    /// requests with `type: "boolean"` and a boolean `value`.
1856    #[serde_as(deserialize_as = "DefaultOnError")]
1857    #[schemars(extend("x-deserialize-default-on-error" = true))]
1858    #[serde(default)]
1859    pub boolean: Option<BooleanConfigOptionCapabilities>,
1860    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1861    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1862    /// these keys.
1863    ///
1864    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1865    #[serde(rename = "_meta")]
1866    pub meta: Option<Meta>,
1867}
1868
1869#[cfg(feature = "unstable_boolean_config")]
1870impl SessionConfigOptionsCapabilities {
1871    /// Builds an empty [`SessionConfigOptionsCapabilities`]; use builder methods to advertise supported sub-capabilities.
1872    #[must_use]
1873    pub fn new() -> Self {
1874        Self::default()
1875    }
1876
1877    /// Whether the client supports boolean session configuration options.
1878    ///
1879    /// Omitted or `null` means the client does not advertise support.
1880    /// Supplying `{}` means agents may include `type: "boolean"` entries in
1881    /// `configOptions`, and the client may send `session/set_config_option`
1882    /// requests with `type: "boolean"` and a boolean `value`.
1883    #[must_use]
1884    pub fn boolean(mut self, boolean: impl IntoOption<BooleanConfigOptionCapabilities>) -> Self {
1885        self.boolean = boolean.into_option();
1886        self
1887    }
1888
1889    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1890    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1891    /// these keys.
1892    ///
1893    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1894    #[must_use]
1895    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1896        self.meta = meta.into_option();
1897        self
1898    }
1899}
1900
1901/// **UNSTABLE**
1902///
1903/// This capability is not part of the spec yet, and may be removed or changed at any point.
1904///
1905/// Capabilities for boolean session configuration options.
1906///
1907/// Supplying `{}` means the client supports boolean session configuration options.
1908#[cfg(feature = "unstable_boolean_config")]
1909#[skip_serializing_none]
1910#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1911#[non_exhaustive]
1912pub struct BooleanConfigOptionCapabilities {
1913    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1914    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1915    /// these keys.
1916    ///
1917    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1918    #[serde(rename = "_meta")]
1919    pub meta: Option<Meta>,
1920}
1921
1922#[cfg(feature = "unstable_boolean_config")]
1923impl BooleanConfigOptionCapabilities {
1924    /// Builds an empty [`BooleanConfigOptionCapabilities`]; use builder methods to advertise supported sub-capabilities.
1925    #[must_use]
1926    pub fn new() -> Self {
1927        Self::default()
1928    }
1929
1930    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1931    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1932    /// these keys.
1933    ///
1934    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1935    #[must_use]
1936    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1937        self.meta = meta.into_option();
1938        self
1939    }
1940}
1941
1942/// **UNSTABLE**
1943///
1944/// This capability is not part of the spec yet, and may be removed or changed at any point.
1945///
1946/// Authentication capabilities supported by the client.
1947///
1948/// Advertised during initialization to inform the agent which authentication
1949/// method types the client can handle. This governs opt-in types that require
1950/// additional client-side support.
1951#[cfg(feature = "unstable_auth_methods")]
1952#[skip_serializing_none]
1953#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1954#[serde(rename_all = "camelCase")]
1955#[non_exhaustive]
1956pub struct AuthCapabilities {
1957    /// Whether the client supports `terminal` authentication methods.
1958    ///
1959    /// When `true`, the agent may include `terminal` entries in its authentication methods.
1960    #[serde(default)]
1961    pub terminal: bool,
1962    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1963    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1964    /// these keys.
1965    ///
1966    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1967    #[serde(rename = "_meta")]
1968    pub meta: Option<Meta>,
1969}
1970
1971#[cfg(feature = "unstable_auth_methods")]
1972impl AuthCapabilities {
1973    /// Builds an empty [`AuthCapabilities`]; use builder methods to advertise supported sub-capabilities.
1974    #[must_use]
1975    pub fn new() -> Self {
1976        Self::default()
1977    }
1978
1979    /// Whether the client supports `terminal` authentication methods.
1980    ///
1981    /// When `true`, the agent may include `AuthMethod::Terminal`
1982    /// entries in its authentication methods.
1983    #[must_use]
1984    pub fn terminal(mut self, terminal: bool) -> Self {
1985        self.terminal = terminal;
1986        self
1987    }
1988
1989    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1990    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1991    /// these keys.
1992    ///
1993    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1994    #[must_use]
1995    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1996        self.meta = meta.into_option();
1997        self
1998    }
1999}
2000
2001/// File system capabilities that a client may support.
2002///
2003/// See protocol docs: [FileSystem](https://agentclientprotocol.com/protocol/initialization#filesystem)
2004#[skip_serializing_none]
2005#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2006#[serde(rename_all = "camelCase")]
2007#[non_exhaustive]
2008pub struct FileSystemCapabilities {
2009    /// Whether the Client supports `fs/read_text_file` requests.
2010    #[serde(default)]
2011    pub read_text_file: bool,
2012    /// Whether the Client supports `fs/write_text_file` requests.
2013    #[serde(default)]
2014    pub write_text_file: bool,
2015    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2016    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2017    /// these keys.
2018    ///
2019    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2020    #[serde(rename = "_meta")]
2021    pub meta: Option<Meta>,
2022}
2023
2024impl FileSystemCapabilities {
2025    /// Builds an empty [`FileSystemCapabilities`]; use builder methods to advertise supported sub-capabilities.
2026    #[must_use]
2027    pub fn new() -> Self {
2028        Self::default()
2029    }
2030
2031    /// Whether the Client supports `fs/read_text_file` requests.
2032    #[must_use]
2033    pub fn read_text_file(mut self, read_text_file: bool) -> Self {
2034        self.read_text_file = read_text_file;
2035        self
2036    }
2037
2038    /// Whether the Client supports `fs/write_text_file` requests.
2039    #[must_use]
2040    pub fn write_text_file(mut self, write_text_file: bool) -> Self {
2041        self.write_text_file = write_text_file;
2042        self
2043    }
2044
2045    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2046    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2047    /// these keys.
2048    ///
2049    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2050    #[must_use]
2051    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2052        self.meta = meta.into_option();
2053        self
2054    }
2055}
2056
2057// Method schema
2058
2059/// Names of all methods that clients handle.
2060///
2061/// Provides a centralized definition of method names used in the protocol.
2062#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2063#[non_exhaustive]
2064pub struct ClientMethodNames {
2065    /// Method for requesting permission from the user.
2066    pub session_request_permission: &'static str,
2067    /// Notification for session updates.
2068    pub session_update: &'static str,
2069    /// Method for writing text files.
2070    pub fs_write_text_file: &'static str,
2071    /// Method for reading text files.
2072    pub fs_read_text_file: &'static str,
2073    /// Method for creating new terminals.
2074    pub terminal_create: &'static str,
2075    /// Method for getting terminals output.
2076    pub terminal_output: &'static str,
2077    /// Method for releasing a terminal.
2078    pub terminal_release: &'static str,
2079    /// Method for waiting for a terminal to finish.
2080    pub terminal_wait_for_exit: &'static str,
2081    /// Method for killing a terminal.
2082    pub terminal_kill: &'static str,
2083    /// Method for opening an MCP-over-ACP connection.
2084    #[cfg(feature = "unstable_mcp_over_acp")]
2085    pub mcp_connect: &'static str,
2086    /// Method for exchanging MCP-over-ACP messages.
2087    #[cfg(feature = "unstable_mcp_over_acp")]
2088    pub mcp_message: &'static str,
2089    /// Method for closing an MCP-over-ACP connection.
2090    #[cfg(feature = "unstable_mcp_over_acp")]
2091    pub mcp_disconnect: &'static str,
2092    /// Method for elicitation.
2093    #[cfg(feature = "unstable_elicitation")]
2094    pub elicitation_create: &'static str,
2095    /// Notification for elicitation completion.
2096    #[cfg(feature = "unstable_elicitation")]
2097    pub elicitation_complete: &'static str,
2098}
2099
2100/// Constant containing all client method names.
2101pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
2102    session_update: SESSION_UPDATE_NOTIFICATION,
2103    session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
2104    fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
2105    fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
2106    terminal_create: TERMINAL_CREATE_METHOD_NAME,
2107    terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
2108    terminal_release: TERMINAL_RELEASE_METHOD_NAME,
2109    terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
2110    terminal_kill: TERMINAL_KILL_METHOD_NAME,
2111    #[cfg(feature = "unstable_mcp_over_acp")]
2112    mcp_connect: MCP_CONNECT_METHOD_NAME,
2113    #[cfg(feature = "unstable_mcp_over_acp")]
2114    mcp_message: MCP_MESSAGE_METHOD_NAME,
2115    #[cfg(feature = "unstable_mcp_over_acp")]
2116    mcp_disconnect: MCP_DISCONNECT_METHOD_NAME,
2117    #[cfg(feature = "unstable_elicitation")]
2118    elicitation_create: ELICITATION_CREATE_METHOD_NAME,
2119    #[cfg(feature = "unstable_elicitation")]
2120    elicitation_complete: ELICITATION_COMPLETE_NOTIFICATION,
2121};
2122
2123/// Notification name for session updates.
2124pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
2125/// Method name for requesting user permission.
2126pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
2127/// Method name for writing text files.
2128pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
2129/// Method name for reading text files.
2130pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
2131/// Method name for creating a new terminal.
2132pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
2133/// Method for getting terminals output.
2134pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
2135/// Method for releasing a terminal.
2136pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
2137/// Method for waiting for a terminal to finish.
2138pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
2139/// Method for killing a terminal.
2140pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
2141/// Method name for elicitation.
2142#[cfg(feature = "unstable_elicitation")]
2143pub(crate) const ELICITATION_CREATE_METHOD_NAME: &str = "elicitation/create";
2144/// Notification name for elicitation completion.
2145#[cfg(feature = "unstable_elicitation")]
2146pub(crate) const ELICITATION_COMPLETE_NOTIFICATION: &str = "elicitation/complete";
2147
2148/// All possible requests that an agent can send to a client.
2149///
2150/// This enum is used internally for routing RPC requests. You typically won't need
2151/// to use this directly.
2152///
2153/// This enum encompasses all method calls from agent to client.
2154#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2155#[serde(untagged)]
2156#[schemars(inline)]
2157#[non_exhaustive]
2158#[allow(clippy::large_enum_variant)]
2159pub enum AgentRequest {
2160    /// Writes content to a text file in the client's file system.
2161    ///
2162    /// Only available if the client advertises the `fs.writeTextFile` capability.
2163    /// Allows the agent to create or modify files within the client's environment.
2164    ///
2165    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
2166    WriteTextFileRequest(WriteTextFileRequest),
2167    /// Reads content from a text file in the client's file system.
2168    ///
2169    /// Only available if the client advertises the `fs.readTextFile` capability.
2170    /// Allows the agent to access file contents within the client's environment.
2171    ///
2172    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
2173    ReadTextFileRequest(ReadTextFileRequest),
2174    /// Requests permission from the user for a tool call operation.
2175    ///
2176    /// Called by the agent when it needs user authorization before executing
2177    /// a potentially sensitive operation. The client should present the options
2178    /// to the user and return their decision.
2179    ///
2180    /// If the client cancels the prompt turn via `session/cancel`, it MUST
2181    /// respond to this request with `RequestPermissionOutcome::Cancelled`.
2182    ///
2183    /// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
2184    RequestPermissionRequest(RequestPermissionRequest),
2185    /// Executes a command in a new terminal
2186    ///
2187    /// Only available if the `terminal` Client capability is set to `true`.
2188    ///
2189    /// Returns a `TerminalId` that can be used with other terminal methods
2190    /// to get the current output, wait for exit, and kill the command.
2191    ///
2192    /// The `TerminalId` can also be used to embed the terminal in a tool call
2193    /// by using the `ToolCallContent::Terminal` variant.
2194    ///
2195    /// The Agent is responsible for releasing the terminal by using the `terminal/release`
2196    /// method.
2197    ///
2198    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2199    CreateTerminalRequest(CreateTerminalRequest),
2200    /// Gets the terminal output and exit status
2201    ///
2202    /// Returns the current content in the terminal without waiting for the command to exit.
2203    /// If the command has already exited, the exit status is included.
2204    ///
2205    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2206    TerminalOutputRequest(TerminalOutputRequest),
2207    /// Releases a terminal
2208    ///
2209    /// The command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`
2210    /// to wait for the command to exit before releasing the terminal.
2211    ///
2212    /// After release, the `TerminalId` can no longer be used with other `terminal/*` methods,
2213    /// but tool calls that already contain it, continue to display its output.
2214    ///
2215    /// The `terminal/kill` method can be used to terminate the command without releasing
2216    /// the terminal, allowing the Agent to call `terminal/output` and other methods.
2217    ///
2218    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2219    ReleaseTerminalRequest(ReleaseTerminalRequest),
2220    /// Waits for the terminal command to exit and return its exit status
2221    ///
2222    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2223    WaitForTerminalExitRequest(WaitForTerminalExitRequest),
2224    /// Kills the terminal command without releasing the terminal
2225    ///
2226    /// While `terminal/release` will also kill the command, this method will keep
2227    /// the `TerminalId` valid so it can be used with other methods.
2228    ///
2229    /// This method can be helpful when implementing command timeouts which terminate
2230    /// the command as soon as elapsed, and then get the final output so it can be sent
2231    /// to the model.
2232    ///
2233    /// Note: Call `terminal/release` when `TerminalId` is no longer needed.
2234    ///
2235    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
2236    KillTerminalRequest(KillTerminalRequest),
2237    /// **UNSTABLE**
2238    ///
2239    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2240    ///
2241    /// Requests structured user input via a form or URL.
2242    #[cfg(feature = "unstable_elicitation")]
2243    CreateElicitationRequest(CreateElicitationRequest),
2244    /// **UNSTABLE**
2245    ///
2246    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2247    ///
2248    /// Opens an MCP-over-ACP connection.
2249    #[cfg(feature = "unstable_mcp_over_acp")]
2250    ConnectMcpRequest(ConnectMcpRequest),
2251    /// **UNSTABLE**
2252    ///
2253    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2254    ///
2255    /// Exchanges an MCP-over-ACP message.
2256    #[cfg(feature = "unstable_mcp_over_acp")]
2257    MessageMcpRequest(MessageMcpRequest),
2258    /// **UNSTABLE**
2259    ///
2260    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2261    ///
2262    /// Closes an MCP-over-ACP connection.
2263    #[cfg(feature = "unstable_mcp_over_acp")]
2264    DisconnectMcpRequest(DisconnectMcpRequest),
2265    /// Handles extension method requests from the agent.
2266    ///
2267    /// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
2268    /// Extension methods provide a way to add custom functionality while maintaining
2269    /// protocol compatibility.
2270    ///
2271    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2272    ExtMethodRequest(ExtRequest),
2273}
2274
2275impl AgentRequest {
2276    /// Returns the corresponding method name of the request.
2277    #[must_use]
2278    pub fn method(&self) -> &str {
2279        match self {
2280            Self::WriteTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_write_text_file,
2281            Self::ReadTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_read_text_file,
2282            Self::RequestPermissionRequest(_) => CLIENT_METHOD_NAMES.session_request_permission,
2283            Self::CreateTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_create,
2284            Self::TerminalOutputRequest(_) => CLIENT_METHOD_NAMES.terminal_output,
2285            Self::ReleaseTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_release,
2286            Self::WaitForTerminalExitRequest(_) => CLIENT_METHOD_NAMES.terminal_wait_for_exit,
2287            Self::KillTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_kill,
2288            #[cfg(feature = "unstable_elicitation")]
2289            Self::CreateElicitationRequest(_) => CLIENT_METHOD_NAMES.elicitation_create,
2290            #[cfg(feature = "unstable_mcp_over_acp")]
2291            Self::ConnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_connect,
2292            #[cfg(feature = "unstable_mcp_over_acp")]
2293            Self::MessageMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_message,
2294            #[cfg(feature = "unstable_mcp_over_acp")]
2295            Self::DisconnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_disconnect,
2296            Self::ExtMethodRequest(ext_request) => &ext_request.method,
2297        }
2298    }
2299}
2300
2301/// All possible responses that a client can send to an agent.
2302///
2303/// This enum is used internally for routing RPC responses. You typically won't need
2304/// to use this directly - the responses are handled automatically by the connection.
2305///
2306/// These are responses to the corresponding `AgentRequest` variants.
2307#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2308#[serde(untagged)]
2309#[schemars(inline)]
2310#[non_exhaustive]
2311pub enum ClientResponse {
2312    /// Successful result returned for a `fs/write_text_file` request.
2313    WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
2314    /// Successful result returned for a `fs/read_text_file` request.
2315    ReadTextFileResponse(ReadTextFileResponse),
2316    /// Successful result returned for a `session/request_permission` request.
2317    RequestPermissionResponse(RequestPermissionResponse),
2318    /// Successful result returned for a `terminal/create` request.
2319    CreateTerminalResponse(CreateTerminalResponse),
2320    /// Successful result returned for a `terminal/output` request.
2321    TerminalOutputResponse(TerminalOutputResponse),
2322    /// Successful result returned for a `terminal/release` request.
2323    ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
2324    /// Successful result returned for a `terminal/wait_for_exit` request.
2325    WaitForTerminalExitResponse(WaitForTerminalExitResponse),
2326    /// Successful result returned for a `terminal/kill` request.
2327    KillTerminalResponse(#[serde(default)] KillTerminalResponse),
2328    /// Successful result returned for a `elicitation/create` request.
2329    #[cfg(feature = "unstable_elicitation")]
2330    CreateElicitationResponse(CreateElicitationResponse),
2331    /// Successful result returned for a `mcp/connect` request.
2332    #[cfg(feature = "unstable_mcp_over_acp")]
2333    ConnectMcpResponse(ConnectMcpResponse),
2334    /// Successful result returned for a `mcp/disconnect` request.
2335    #[cfg(feature = "unstable_mcp_over_acp")]
2336    DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse),
2337    /// Successful result returned by an extension method outside the core ACP method set.
2338    ExtMethodResponse(ExtResponse),
2339    /// Successful result returned by an MCP-over-ACP `mcp/message` request.
2340    #[cfg(feature = "unstable_mcp_over_acp")]
2341    MessageMcpResponse(MessageMcpResponse),
2342}
2343
2344/// All possible notifications that an agent can send to a client.
2345///
2346/// This enum is used internally for routing RPC notifications. You typically won't need
2347/// to use this directly.
2348///
2349/// Notifications do not expect a response.
2350#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2351#[serde(untagged)]
2352#[expect(clippy::large_enum_variant)]
2353#[schemars(inline)]
2354#[non_exhaustive]
2355pub enum AgentNotification {
2356    /// Handles session update notifications from the agent.
2357    ///
2358    /// This is a notification endpoint (no response expected) that receives
2359    /// real-time updates about session progress, including message chunks,
2360    /// tool calls, and execution plans.
2361    ///
2362    /// Note: Clients SHOULD continue accepting tool call updates even after
2363    /// sending a `session/cancel` notification, as the agent may send final
2364    /// updates before responding with the cancelled stop reason.
2365    ///
2366    /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
2367    SessionNotification(SessionNotification),
2368    /// **UNSTABLE**
2369    ///
2370    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2371    ///
2372    /// Notification that a URL-based elicitation has completed.
2373    #[cfg(feature = "unstable_elicitation")]
2374    CompleteElicitationNotification(CompleteElicitationNotification),
2375    /// **UNSTABLE**
2376    ///
2377    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2378    ///
2379    /// Receives an MCP-over-ACP notification.
2380    #[cfg(feature = "unstable_mcp_over_acp")]
2381    MessageMcpNotification(MessageMcpNotification),
2382    /// Handles extension notifications from the agent.
2383    ///
2384    /// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
2385    /// Extension notifications provide a way to send one-way messages for custom functionality
2386    /// while maintaining protocol compatibility.
2387    ///
2388    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2389    ExtNotification(ExtNotification),
2390}
2391
2392impl AgentNotification {
2393    /// Returns the corresponding method name of the notification.
2394    #[must_use]
2395    pub fn method(&self) -> &str {
2396        match self {
2397            Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update,
2398            #[cfg(feature = "unstable_elicitation")]
2399            Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete,
2400            #[cfg(feature = "unstable_mcp_over_acp")]
2401            Self::MessageMcpNotification(_) => CLIENT_METHOD_NAMES.mcp_message,
2402            Self::ExtNotification(ext_notification) => &ext_notification.method,
2403        }
2404    }
2405}
2406
2407#[cfg(test)]
2408mod tests {
2409    use super::*;
2410
2411    #[test]
2412    fn test_serialization_behavior() {
2413        use serde_json::json;
2414
2415        assert_eq!(
2416            serde_json::from_value::<SessionInfoUpdate>(json!({})).unwrap(),
2417            SessionInfoUpdate {
2418                title: MaybeUndefined::Undefined,
2419                updated_at: MaybeUndefined::Undefined,
2420                meta: None
2421            }
2422        );
2423        assert_eq!(
2424            serde_json::from_value::<SessionInfoUpdate>(json!({"title": null, "updatedAt": null}))
2425                .unwrap(),
2426            SessionInfoUpdate {
2427                title: MaybeUndefined::Null,
2428                updated_at: MaybeUndefined::Null,
2429                meta: None
2430            }
2431        );
2432        assert_eq!(
2433            serde_json::from_value::<SessionInfoUpdate>(
2434                json!({"title": "title", "updatedAt": "timestamp"})
2435            )
2436            .unwrap(),
2437            SessionInfoUpdate {
2438                title: MaybeUndefined::Value("title".to_string()),
2439                updated_at: MaybeUndefined::Value("timestamp".to_string()),
2440                meta: None
2441            }
2442        );
2443
2444        assert_eq!(
2445            serde_json::to_value(SessionInfoUpdate::new()).unwrap(),
2446            json!({})
2447        );
2448        assert_eq!(
2449            serde_json::to_value(SessionInfoUpdate::new().title("title")).unwrap(),
2450            json!({"title": "title"})
2451        );
2452        assert_eq!(
2453            serde_json::to_value(SessionInfoUpdate::new().title(None)).unwrap(),
2454            json!({"title": null})
2455        );
2456        assert_eq!(
2457            serde_json::to_value(
2458                SessionInfoUpdate::new()
2459                    .title("title")
2460                    .title(MaybeUndefined::Undefined)
2461            )
2462            .unwrap(),
2463            json!({})
2464        );
2465    }
2466
2467    #[test]
2468    fn test_content_chunk_message_id_serialization() {
2469        use serde_json::json;
2470
2471        assert_eq!(
2472            serde_json::to_value(SessionUpdate::AgentMessageChunk(ContentChunk::new(
2473                ContentBlock::Text(crate::v1::TextContent::new("Hello"))
2474            )))
2475            .unwrap(),
2476            json!({
2477                "sessionUpdate": "agent_message_chunk",
2478                "content": {
2479                    "type": "text",
2480                    "text": "Hello"
2481                }
2482            })
2483        );
2484
2485        assert_eq!(
2486            serde_json::to_value(SessionUpdate::AgentMessageChunk(
2487                ContentChunk::new(ContentBlock::Text(crate::v1::TextContent::new("Hello")))
2488                    .message_id("msg_agent_c42b9")
2489            ))
2490            .unwrap(),
2491            json!({
2492                "sessionUpdate": "agent_message_chunk",
2493                "messageId": "msg_agent_c42b9",
2494                "content": {
2495                    "type": "text",
2496                    "text": "Hello"
2497                }
2498            })
2499        );
2500
2501        let SessionUpdate::AgentMessageChunk(chunk) = serde_json::from_value(json!({
2502            "sessionUpdate": "agent_message_chunk",
2503            "messageId": null,
2504            "content": {
2505                "type": "text",
2506                "text": "Hello"
2507            }
2508        }))
2509        .unwrap() else {
2510            panic!("expected agent message chunk");
2511        };
2512
2513        assert_eq!(chunk.message_id, None);
2514    }
2515
2516    #[test]
2517    fn test_usage_update_serialization() {
2518        use serde_json::json;
2519
2520        assert_eq!(
2521            serde_json::to_value(SessionUpdate::UsageUpdate(UsageUpdate::new(
2522                53_000, 200_000
2523            )))
2524            .unwrap(),
2525            json!({
2526                "sessionUpdate": "usage_update",
2527                "used": 53000,
2528                "size": 200_000
2529            })
2530        );
2531
2532        assert_eq!(
2533            serde_json::to_value(SessionUpdate::UsageUpdate(
2534                UsageUpdate::new(53_000, 200_000).cost(Cost::new(0.045, "USD"))
2535            ))
2536            .unwrap(),
2537            json!({
2538                "sessionUpdate": "usage_update",
2539                "used": 53000,
2540                "size": 200_000,
2541                "cost": {
2542                    "amount": 0.045,
2543                    "currency": "USD"
2544                }
2545            })
2546        );
2547
2548        let SessionUpdate::UsageUpdate(update) = serde_json::from_value(json!({
2549            "sessionUpdate": "usage_update",
2550            "used": 53000,
2551            "size": 200_000,
2552            "cost": null
2553        }))
2554        .unwrap() else {
2555            panic!("expected usage update");
2556        };
2557
2558        assert_eq!(update.cost, None);
2559    }
2560
2561    #[cfg(feature = "unstable_nes")]
2562    #[test]
2563    fn test_client_capabilities_position_encodings_serialization() {
2564        use serde_json::json;
2565
2566        let capabilities = ClientCapabilities::new().position_encodings(vec![
2567            PositionEncodingKind::Utf32,
2568            PositionEncodingKind::Utf16,
2569        ]);
2570        let json = serde_json::to_value(&capabilities).unwrap();
2571
2572        assert_eq!(json["positionEncodings"], json!(["utf-32", "utf-16"]));
2573    }
2574
2575    #[cfg(feature = "unstable_boolean_config")]
2576    #[test]
2577    fn test_client_capabilities_boolean_config_options_serialization() {
2578        use serde_json::json;
2579
2580        let capabilities = ClientCapabilities::new().session(
2581            ClientSessionCapabilities::new().config_options(
2582                SessionConfigOptionsCapabilities::new()
2583                    .boolean(BooleanConfigOptionCapabilities::new()),
2584            ),
2585        );
2586        let json = serde_json::to_value(&capabilities).unwrap();
2587
2588        assert_eq!(json["session"]["configOptions"]["boolean"], json!({}));
2589
2590        let omitted: ClientCapabilities = serde_json::from_value(json!({})).unwrap();
2591        assert!(omitted.session.is_none());
2592
2593        let null_session: ClientCapabilities = serde_json::from_value(json!({
2594            "session": null
2595        }))
2596        .unwrap();
2597        assert!(null_session.session.is_none());
2598
2599        let null_config_options: ClientCapabilities = serde_json::from_value(json!({
2600            "session": {
2601                "configOptions": null
2602            }
2603        }))
2604        .unwrap();
2605        assert!(
2606            null_config_options
2607                .session
2608                .and_then(|session| session.config_options)
2609                .is_none()
2610        );
2611
2612        let null_boolean: ClientCapabilities = serde_json::from_value(json!({
2613            "session": {
2614                "configOptions": {
2615                    "boolean": null
2616                }
2617            }
2618        }))
2619        .unwrap();
2620        assert!(
2621            null_boolean
2622                .session
2623                .and_then(|session| session.config_options)
2624                .and_then(|config_options| config_options.boolean)
2625                .is_none()
2626        );
2627    }
2628
2629    #[cfg(feature = "unstable_plan_operations")]
2630    #[test]
2631    fn test_plan_operations_serialization() {
2632        use serde_json::json;
2633
2634        use crate::v1::{PlanEntry, PlanEntryPriority, PlanEntryStatus, PlanUpdateContent};
2635
2636        let plan_update = SessionUpdate::PlanUpdate(PlanUpdate::new(PlanUpdateContent::items(
2637            "plan-1",
2638            vec![PlanEntry::new(
2639                "Step 1",
2640                PlanEntryPriority::High,
2641                PlanEntryStatus::Pending,
2642            )],
2643        )));
2644
2645        assert_eq!(
2646            serde_json::to_value(plan_update).unwrap(),
2647            json!({
2648                "sessionUpdate": "plan_update",
2649                "plan": {
2650                    "type": "items",
2651                    "id": "plan-1",
2652                    "entries": [
2653                        {
2654                            "content": "Step 1",
2655                            "priority": "high",
2656                            "status": "pending"
2657                        }
2658                    ]
2659                }
2660            })
2661        );
2662
2663        assert_eq!(
2664            serde_json::to_value(SessionUpdate::PlanRemoved(PlanRemoved::new("plan-1"))).unwrap(),
2665            json!({
2666                "sessionUpdate": "plan_removed",
2667                "id": "plan-1"
2668            })
2669        );
2670
2671        let capabilities = ClientCapabilities::new().plan(PlanCapabilities::new());
2672        let json = serde_json::to_value(&capabilities).unwrap();
2673        assert_eq!(json["plan"], json!({}));
2674
2675        assert_eq!(
2676            serde_json::from_value::<ClientCapabilities>(json!({ "plan": null }))
2677                .unwrap()
2678                .plan,
2679            None
2680        );
2681    }
2682
2683    #[cfg(feature = "unstable_mcp_over_acp")]
2684    #[test]
2685    fn test_agent_mcp_request_method_names() {
2686        use serde_json::json;
2687
2688        let params: serde_json::Map<String, serde_json::Value> =
2689            [("cursor".to_string(), json!("abc"))].into_iter().collect();
2690
2691        assert_eq!(CLIENT_METHOD_NAMES.mcp_connect, "mcp/connect");
2692        assert_eq!(CLIENT_METHOD_NAMES.mcp_message, "mcp/message");
2693        assert_eq!(CLIENT_METHOD_NAMES.mcp_disconnect, "mcp/disconnect");
2694
2695        assert_eq!(
2696            AgentRequest::ConnectMcpRequest(ConnectMcpRequest::new("server-1")).method(),
2697            "mcp/connect"
2698        );
2699        assert_eq!(
2700            AgentRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
2701                .method(),
2702            "mcp/message"
2703        );
2704        assert_eq!(
2705            AgentRequest::DisconnectMcpRequest(DisconnectMcpRequest::new("conn-1")).method(),
2706            "mcp/disconnect"
2707        );
2708        assert_eq!(
2709            AgentNotification::MessageMcpNotification(MessageMcpNotification::new(
2710                "conn-1",
2711                "notifications/progress"
2712            ))
2713            .method(),
2714            "mcp/message"
2715        );
2716
2717        assert_eq!(
2718            serde_json::to_value(ConnectMcpRequest::new("server-1")).unwrap(),
2719            json!({ "acpId": "server-1" })
2720        );
2721        assert_eq!(
2722            serde_json::to_value(ConnectMcpResponse::new("conn-1")).unwrap(),
2723            json!({ "connectionId": "conn-1" })
2724        );
2725        assert_eq!(
2726            serde_json::to_value(MessageMcpRequest::new("conn-1", "tools/list").params(params))
2727                .unwrap(),
2728            json!({
2729                "connectionId": "conn-1",
2730                "method": "tools/list",
2731                "params": { "cursor": "abc" }
2732            })
2733        );
2734        assert_eq!(
2735            serde_json::to_value(DisconnectMcpRequest::new("conn-1")).unwrap(),
2736            json!({ "connectionId": "conn-1" })
2737        );
2738        assert_eq!(
2739            serde_json::to_value(MessageMcpNotification::new(
2740                "conn-1",
2741                "notifications/progress"
2742            ))
2743            .unwrap(),
2744            json!({
2745                "connectionId": "conn-1",
2746                "method": "notifications/progress"
2747            })
2748        );
2749
2750        let request_with_null_params: MessageMcpRequest = serde_json::from_value(json!({
2751            "connectionId": "conn-1",
2752            "method": "tools/list",
2753            "params": null
2754        }))
2755        .unwrap();
2756        assert_eq!(request_with_null_params.params, None);
2757    }
2758}