Skip to main content

agent_client_protocol_schema/
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 crate::elicitation::{
15    CompleteElicitationNotification, CreateElicitationRequest, CreateElicitationResponse,
16    ElicitationCapabilities,
17};
18use crate::{
19    ContentBlock, ExtNotification, ExtRequest, ExtResponse, IntoOption, Meta, Plan,
20    SessionConfigOption, SessionId, SessionModeId, SkipListener, ToolCall, ToolCallUpdate,
21};
22use crate::{IntoMaybeUndefined, MaybeUndefined};
23
24#[cfg(feature = "unstable_nes")]
25use crate::{ClientNesCapabilities, PositionEncodingKind};
26
27// Session updates
28
29/// Notification containing a session update from the agent.
30///
31/// Used to stream real-time progress and results during prompt processing.
32///
33/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
34#[skip_serializing_none]
35#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
36#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
37#[serde(rename_all = "camelCase")]
38#[non_exhaustive]
39pub struct SessionNotification {
40    /// The ID of the session this update pertains to.
41    pub session_id: SessionId,
42    /// The actual update content.
43    pub update: SessionUpdate,
44    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
45    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
46    /// these keys.
47    ///
48    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
49    #[serde(rename = "_meta")]
50    pub meta: Option<Meta>,
51}
52
53impl SessionNotification {
54    #[must_use]
55    pub fn new(session_id: impl Into<SessionId>, update: SessionUpdate) -> Self {
56        Self {
57            session_id: session_id.into(),
58            update,
59            meta: None,
60        }
61    }
62
63    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
64    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
65    /// these keys.
66    ///
67    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
68    #[must_use]
69    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
70        self.meta = meta.into_option();
71        self
72    }
73}
74
75/// Different types of updates that can be sent during session processing.
76///
77/// These updates provide real-time feedback about the agent's progress.
78///
79/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
80#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
81#[serde(tag = "sessionUpdate", rename_all = "snake_case")]
82#[schemars(extend("discriminator" = {"propertyName": "sessionUpdate"}))]
83#[non_exhaustive]
84pub enum SessionUpdate {
85    /// A chunk of the user's message being streamed.
86    UserMessageChunk(ContentChunk),
87    /// A chunk of the agent's response being streamed.
88    AgentMessageChunk(ContentChunk),
89    /// A chunk of the agent's internal reasoning being streamed.
90    AgentThoughtChunk(ContentChunk),
91    /// Notification that a new tool call has been initiated.
92    ToolCall(ToolCall),
93    /// Update on the status or results of a tool call.
94    ToolCallUpdate(ToolCallUpdate),
95    /// The agent's execution plan for complex tasks.
96    /// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
97    Plan(Plan),
98    /// Available commands are ready or have changed
99    AvailableCommandsUpdate(AvailableCommandsUpdate),
100    /// The current mode of the session has changed
101    ///
102    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
103    CurrentModeUpdate(CurrentModeUpdate),
104    /// Session configuration options have been updated.
105    ConfigOptionUpdate(ConfigOptionUpdate),
106    /// Session metadata has been updated (title, timestamps, custom metadata)
107    SessionInfoUpdate(SessionInfoUpdate),
108    /// **UNSTABLE**
109    ///
110    /// This capability is not part of the spec yet, and may be removed or changed at any point.
111    ///
112    /// Context window and cost update for the session.
113    #[cfg(feature = "unstable_session_usage")]
114    UsageUpdate(UsageUpdate),
115}
116
117/// The current mode of the session has changed
118///
119/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
120#[skip_serializing_none]
121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
122#[serde(rename_all = "camelCase")]
123#[non_exhaustive]
124pub struct CurrentModeUpdate {
125    /// The ID of the current mode
126    pub current_mode_id: SessionModeId,
127    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
128    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
129    /// these keys.
130    ///
131    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
132    #[serde(rename = "_meta")]
133    pub meta: Option<Meta>,
134}
135
136impl CurrentModeUpdate {
137    #[must_use]
138    pub fn new(current_mode_id: impl Into<SessionModeId>) -> Self {
139        Self {
140            current_mode_id: current_mode_id.into(),
141            meta: None,
142        }
143    }
144
145    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
146    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
147    /// these keys.
148    ///
149    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
150    #[must_use]
151    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
152        self.meta = meta.into_option();
153        self
154    }
155}
156
157/// Session configuration options have been updated.
158#[serde_as]
159#[skip_serializing_none]
160#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
161#[serde(rename_all = "camelCase")]
162#[non_exhaustive]
163pub struct ConfigOptionUpdate {
164    /// The full set of configuration options and their current values.
165    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
166    pub config_options: Vec<SessionConfigOption>,
167    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
168    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
169    /// these keys.
170    ///
171    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
172    #[serde(rename = "_meta")]
173    pub meta: Option<Meta>,
174}
175
176impl ConfigOptionUpdate {
177    #[must_use]
178    pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
179        Self {
180            config_options,
181            meta: None,
182        }
183    }
184
185    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
186    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
187    /// these keys.
188    ///
189    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
190    #[must_use]
191    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
192        self.meta = meta.into_option();
193        self
194    }
195}
196
197/// Update to session metadata. All fields are optional to support partial updates.
198///
199/// Agents send this notification to update session information like title or custom metadata.
200/// This allows clients to display dynamic session names and track session state changes.
201#[skip_serializing_none]
202#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
203#[serde(rename_all = "camelCase")]
204#[non_exhaustive]
205pub struct SessionInfoUpdate {
206    /// Human-readable title for the session. Set to null to clear.
207    #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
208    pub title: MaybeUndefined<String>,
209    /// ISO 8601 timestamp of last activity. Set to null to clear.
210    #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
211    pub updated_at: MaybeUndefined<String>,
212    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
213    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
214    /// these keys.
215    ///
216    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
217    #[serde(rename = "_meta")]
218    pub meta: Option<Meta>,
219}
220
221impl SessionInfoUpdate {
222    #[must_use]
223    pub fn new() -> Self {
224        Self::default()
225    }
226
227    /// Human-readable title for the session. Set to null to clear.
228    #[must_use]
229    pub fn title(mut self, title: impl IntoMaybeUndefined<String>) -> Self {
230        self.title = title.into_maybe_undefined();
231        self
232    }
233
234    /// ISO 8601 timestamp of last activity. Set to null to clear.
235    #[must_use]
236    pub fn updated_at(mut self, updated_at: impl IntoMaybeUndefined<String>) -> Self {
237        self.updated_at = updated_at.into_maybe_undefined();
238        self
239    }
240
241    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
242    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
243    /// these keys.
244    ///
245    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
246    #[must_use]
247    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
248        self.meta = meta.into_option();
249        self
250    }
251}
252
253/// **UNSTABLE**
254///
255/// This capability is not part of the spec yet, and may be removed or changed at any point.
256///
257/// Context window and cost update for a session.
258#[cfg(feature = "unstable_session_usage")]
259#[serde_as]
260#[skip_serializing_none]
261#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
262#[serde(rename_all = "camelCase")]
263#[non_exhaustive]
264pub struct UsageUpdate {
265    /// Tokens currently in context.
266    pub used: u64,
267    /// Total context window size in tokens.
268    pub size: u64,
269    /// Cumulative session cost (optional).
270    #[serde_as(deserialize_as = "DefaultOnError")]
271    #[serde(default)]
272    pub cost: Option<Cost>,
273    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
274    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
275    /// these keys.
276    ///
277    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
278    #[serde(rename = "_meta")]
279    pub meta: Option<Meta>,
280}
281
282#[cfg(feature = "unstable_session_usage")]
283impl UsageUpdate {
284    #[must_use]
285    pub fn new(used: u64, size: u64) -> Self {
286        Self {
287            used,
288            size,
289            cost: None,
290            meta: None,
291        }
292    }
293
294    /// Cumulative session cost (optional).
295    #[must_use]
296    pub fn cost(mut self, cost: impl IntoOption<Cost>) -> Self {
297        self.cost = cost.into_option();
298        self
299    }
300
301    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
302    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
303    /// these keys.
304    ///
305    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
306    #[must_use]
307    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
308        self.meta = meta.into_option();
309        self
310    }
311}
312
313/// **UNSTABLE**
314///
315/// This capability is not part of the spec yet, and may be removed or changed at any point.
316///
317/// Cost information for a session.
318#[cfg(feature = "unstable_session_usage")]
319#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
320#[serde(rename_all = "camelCase")]
321#[non_exhaustive]
322pub struct Cost {
323    /// Total cumulative cost for session.
324    pub amount: f64,
325    /// ISO 4217 currency code (e.g., "USD", "EUR").
326    pub currency: String,
327}
328
329#[cfg(feature = "unstable_session_usage")]
330impl Cost {
331    #[must_use]
332    pub fn new(amount: f64, currency: impl Into<String>) -> Self {
333        Self {
334            amount,
335            currency: currency.into(),
336        }
337    }
338}
339
340/// A streamed item of content
341#[skip_serializing_none]
342#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
343#[serde(rename_all = "camelCase")]
344#[non_exhaustive]
345pub struct ContentChunk {
346    /// A single item of content
347    pub content: ContentBlock,
348    /// **UNSTABLE**
349    ///
350    /// This capability is not part of the spec yet, and may be removed or changed at any point.
351    ///
352    /// A unique identifier for the message this chunk belongs to.
353    ///
354    /// All chunks belonging to the same message share the same `messageId`.
355    /// A change in `messageId` indicates a new message has started.
356    /// Both clients and agents MUST use UUID format for message IDs.
357    #[cfg(feature = "unstable_message_id")]
358    pub message_id: Option<String>,
359    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
360    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
361    /// these keys.
362    ///
363    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
364    #[serde(rename = "_meta")]
365    pub meta: Option<Meta>,
366}
367
368impl ContentChunk {
369    #[must_use]
370    pub fn new(content: ContentBlock) -> Self {
371        Self {
372            content,
373            #[cfg(feature = "unstable_message_id")]
374            message_id: None,
375            meta: None,
376        }
377    }
378
379    /// **UNSTABLE**
380    ///
381    /// This capability is not part of the spec yet, and may be removed or changed at any point.
382    ///
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    /// Both clients and agents MUST use UUID format for message IDs.
388    #[cfg(feature = "unstable_message_id")]
389    #[must_use]
390    pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
391        self.message_id = message_id.into_option();
392        self
393    }
394
395    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
396    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
397    /// these keys.
398    ///
399    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
400    #[must_use]
401    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
402        self.meta = meta.into_option();
403        self
404    }
405}
406
407/// Available commands are ready or have changed
408#[serde_as]
409#[skip_serializing_none]
410#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
411#[serde(rename_all = "camelCase")]
412#[non_exhaustive]
413pub struct AvailableCommandsUpdate {
414    /// Commands the agent can execute
415    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
416    pub available_commands: Vec<AvailableCommand>,
417    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
418    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
419    /// these keys.
420    ///
421    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
422    #[serde(rename = "_meta")]
423    pub meta: Option<Meta>,
424}
425
426impl AvailableCommandsUpdate {
427    #[must_use]
428    pub fn new(available_commands: Vec<AvailableCommand>) -> Self {
429        Self {
430            available_commands,
431            meta: None,
432        }
433    }
434
435    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
436    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
437    /// these keys.
438    ///
439    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
440    #[must_use]
441    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
442        self.meta = meta.into_option();
443        self
444    }
445}
446
447/// Information about a command.
448#[serde_as]
449#[skip_serializing_none]
450#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
451#[serde(rename_all = "camelCase")]
452#[non_exhaustive]
453pub struct AvailableCommand {
454    /// Command name (e.g., `create_plan`, `research_codebase`).
455    pub name: String,
456    /// Human-readable description of what the command does.
457    pub description: String,
458    /// Input for the command if required
459    #[serde_as(deserialize_as = "DefaultOnError")]
460    #[serde(default)]
461    pub input: Option<AvailableCommandInput>,
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 AvailableCommand {
472    #[must_use]
473    pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
474        Self {
475            name: name.into(),
476            description: description.into(),
477            input: None,
478            meta: None,
479        }
480    }
481
482    /// Input for the command if required
483    #[must_use]
484    pub fn input(mut self, input: impl IntoOption<AvailableCommandInput>) -> Self {
485        self.input = input.into_option();
486        self
487    }
488
489    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
490    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
491    /// these keys.
492    ///
493    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
494    #[must_use]
495    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
496        self.meta = meta.into_option();
497        self
498    }
499}
500
501/// The input specification for a command.
502#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
503#[serde(untagged, rename_all = "camelCase")]
504#[non_exhaustive]
505pub enum AvailableCommandInput {
506    /// All text that was typed after the command name is provided as input.
507    Unstructured(UnstructuredCommandInput),
508}
509
510/// All text that was typed after the command name is provided as input.
511#[skip_serializing_none]
512#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
513#[serde(rename_all = "camelCase")]
514#[non_exhaustive]
515pub struct UnstructuredCommandInput {
516    /// A hint to display when the input hasn't been provided yet
517    pub hint: String,
518    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
519    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
520    /// these keys.
521    ///
522    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
523    #[serde(rename = "_meta")]
524    pub meta: Option<Meta>,
525}
526
527impl UnstructuredCommandInput {
528    #[must_use]
529    pub fn new(hint: impl Into<String>) -> Self {
530        Self {
531            hint: hint.into(),
532            meta: None,
533        }
534    }
535
536    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
537    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
538    /// these keys.
539    ///
540    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
541    #[must_use]
542    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
543        self.meta = meta.into_option();
544        self
545    }
546}
547
548// Permission
549
550/// Request for user permission to execute a tool call.
551///
552/// Sent when the agent needs authorization before performing a sensitive operation.
553///
554/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
555#[skip_serializing_none]
556#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
557#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
558#[serde(rename_all = "camelCase")]
559#[non_exhaustive]
560pub struct RequestPermissionRequest {
561    /// The session ID for this request.
562    pub session_id: SessionId,
563    /// Details about the tool call requiring permission.
564    pub tool_call: ToolCallUpdate,
565    /// Available permission options for the user to choose from.
566    pub options: Vec<PermissionOption>,
567    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
568    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
569    /// these keys.
570    ///
571    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
572    #[serde(rename = "_meta")]
573    pub meta: Option<Meta>,
574}
575
576impl RequestPermissionRequest {
577    #[must_use]
578    pub fn new(
579        session_id: impl Into<SessionId>,
580        tool_call: ToolCallUpdate,
581        options: Vec<PermissionOption>,
582    ) -> Self {
583        Self {
584            session_id: session_id.into(),
585            tool_call,
586            options,
587            meta: None,
588        }
589    }
590
591    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
592    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
593    /// these keys.
594    ///
595    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
596    #[must_use]
597    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
598        self.meta = meta.into_option();
599        self
600    }
601}
602
603/// An option presented to the user when requesting permission.
604#[skip_serializing_none]
605#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
606#[serde(rename_all = "camelCase")]
607#[non_exhaustive]
608pub struct PermissionOption {
609    /// Unique identifier for this permission option.
610    pub option_id: PermissionOptionId,
611    /// Human-readable label to display to the user.
612    pub name: String,
613    /// Hint about the nature of this permission option.
614    pub kind: PermissionOptionKind,
615    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
616    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
617    /// these keys.
618    ///
619    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
620    #[serde(rename = "_meta")]
621    pub meta: Option<Meta>,
622}
623
624impl PermissionOption {
625    #[must_use]
626    pub fn new(
627        option_id: impl Into<PermissionOptionId>,
628        name: impl Into<String>,
629        kind: PermissionOptionKind,
630    ) -> Self {
631        Self {
632            option_id: option_id.into(),
633            name: name.into(),
634            kind,
635            meta: None,
636        }
637    }
638
639    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
640    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
641    /// these keys.
642    ///
643    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
644    #[must_use]
645    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
646        self.meta = meta.into_option();
647        self
648    }
649}
650
651/// Unique identifier for a permission option.
652#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
653#[serde(transparent)]
654#[from(Arc<str>, String, &'static str)]
655#[non_exhaustive]
656pub struct PermissionOptionId(pub Arc<str>);
657
658impl PermissionOptionId {
659    #[must_use]
660    pub fn new(id: impl Into<Arc<str>>) -> Self {
661        Self(id.into())
662    }
663}
664
665/// The type of permission option being presented to the user.
666///
667/// Helps clients choose appropriate icons and UI treatment.
668#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
669#[serde(rename_all = "snake_case")]
670#[non_exhaustive]
671pub enum PermissionOptionKind {
672    /// Allow this operation only this time.
673    AllowOnce,
674    /// Allow this operation and remember the choice.
675    AllowAlways,
676    /// Reject this operation only this time.
677    RejectOnce,
678    /// Reject this operation and remember the choice.
679    RejectAlways,
680}
681
682/// Response to a permission request.
683#[skip_serializing_none]
684#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
685#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
686#[serde(rename_all = "camelCase")]
687#[non_exhaustive]
688pub struct RequestPermissionResponse {
689    /// The user's decision on the permission request.
690    // This extra-level is unfortunately needed because the output must be an object
691    pub outcome: RequestPermissionOutcome,
692    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
693    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
694    /// these keys.
695    ///
696    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
697    #[serde(rename = "_meta")]
698    pub meta: Option<Meta>,
699}
700
701impl RequestPermissionResponse {
702    #[must_use]
703    pub fn new(outcome: RequestPermissionOutcome) -> Self {
704        Self {
705            outcome,
706            meta: None,
707        }
708    }
709
710    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
711    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
712    /// these keys.
713    ///
714    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
715    #[must_use]
716    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
717        self.meta = meta.into_option();
718        self
719    }
720}
721
722/// The outcome of a permission request.
723#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
724#[serde(tag = "outcome", rename_all = "snake_case")]
725#[schemars(extend("discriminator" = {"propertyName": "outcome"}))]
726#[non_exhaustive]
727pub enum RequestPermissionOutcome {
728    /// The prompt turn was cancelled before the user responded.
729    ///
730    /// When a client sends a `session/cancel` notification to cancel an ongoing
731    /// prompt turn, it MUST respond to all pending `session/request_permission`
732    /// requests with this `Cancelled` outcome.
733    ///
734    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
735    Cancelled,
736    /// The user selected one of the provided options.
737    #[serde(rename_all = "camelCase")]
738    Selected(SelectedPermissionOutcome),
739}
740
741/// The user selected one of the provided options.
742#[skip_serializing_none]
743#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
744#[serde(rename_all = "camelCase")]
745#[non_exhaustive]
746pub struct SelectedPermissionOutcome {
747    /// The ID of the option the user selected.
748    pub option_id: PermissionOptionId,
749    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
750    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
751    /// these keys.
752    ///
753    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
754    #[serde(rename = "_meta")]
755    pub meta: Option<Meta>,
756}
757
758impl SelectedPermissionOutcome {
759    #[must_use]
760    pub fn new(option_id: impl Into<PermissionOptionId>) -> Self {
761        Self {
762            option_id: option_id.into(),
763            meta: None,
764        }
765    }
766
767    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
768    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
769    /// these keys.
770    ///
771    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
772    #[must_use]
773    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
774        self.meta = meta.into_option();
775        self
776    }
777}
778
779// Write text file
780
781/// Request to write content to a text file.
782///
783/// Only available if the client supports the `fs.writeTextFile` capability.
784#[skip_serializing_none]
785#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
786#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
787#[serde(rename_all = "camelCase")]
788#[non_exhaustive]
789pub struct WriteTextFileRequest {
790    /// The session ID for this request.
791    pub session_id: SessionId,
792    /// Absolute path to the file to write.
793    pub path: PathBuf,
794    /// The text content to write to the file.
795    pub content: String,
796    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
797    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
798    /// these keys.
799    ///
800    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
801    #[serde(rename = "_meta")]
802    pub meta: Option<Meta>,
803}
804
805impl WriteTextFileRequest {
806    #[must_use]
807    pub fn new(
808        session_id: impl Into<SessionId>,
809        path: impl Into<PathBuf>,
810        content: impl Into<String>,
811    ) -> Self {
812        Self {
813            session_id: session_id.into(),
814            path: path.into(),
815            content: content.into(),
816            meta: None,
817        }
818    }
819
820    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
821    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
822    /// these keys.
823    ///
824    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
825    #[must_use]
826    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
827        self.meta = meta.into_option();
828        self
829    }
830}
831
832/// Response to `fs/write_text_file`
833#[skip_serializing_none]
834#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
835#[serde(rename_all = "camelCase")]
836#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
837#[non_exhaustive]
838pub struct WriteTextFileResponse {
839    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
840    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
841    /// these keys.
842    ///
843    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
844    #[serde(rename = "_meta")]
845    pub meta: Option<Meta>,
846}
847
848impl WriteTextFileResponse {
849    #[must_use]
850    pub fn new() -> Self {
851        Self::default()
852    }
853
854    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
855    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
856    /// these keys.
857    ///
858    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
859    #[must_use]
860    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
861        self.meta = meta.into_option();
862        self
863    }
864}
865
866// Read text file
867
868/// Request to read content from a text file.
869///
870/// Only available if the client supports the `fs.readTextFile` capability.
871#[skip_serializing_none]
872#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
873#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
874#[serde(rename_all = "camelCase")]
875#[non_exhaustive]
876pub struct ReadTextFileRequest {
877    /// The session ID for this request.
878    pub session_id: SessionId,
879    /// Absolute path to the file to read.
880    pub path: PathBuf,
881    /// Line number to start reading from (1-based).
882    pub line: Option<u32>,
883    /// Maximum number of lines to read.
884    pub limit: Option<u32>,
885    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
886    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
887    /// these keys.
888    ///
889    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
890    #[serde(rename = "_meta")]
891    pub meta: Option<Meta>,
892}
893
894impl ReadTextFileRequest {
895    #[must_use]
896    pub fn new(session_id: impl Into<SessionId>, path: impl Into<PathBuf>) -> Self {
897        Self {
898            session_id: session_id.into(),
899            path: path.into(),
900            line: None,
901            limit: None,
902            meta: None,
903        }
904    }
905
906    /// Line number to start reading from (1-based).
907    #[must_use]
908    pub fn line(mut self, line: impl IntoOption<u32>) -> Self {
909        self.line = line.into_option();
910        self
911    }
912
913    /// Maximum number of lines to read.
914    #[must_use]
915    pub fn limit(mut self, limit: impl IntoOption<u32>) -> Self {
916        self.limit = limit.into_option();
917        self
918    }
919
920    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
921    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
922    /// these keys.
923    ///
924    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
925    #[must_use]
926    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
927        self.meta = meta.into_option();
928        self
929    }
930}
931
932/// Response containing the contents of a text file.
933#[skip_serializing_none]
934#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
935#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
936#[serde(rename_all = "camelCase")]
937#[non_exhaustive]
938pub struct ReadTextFileResponse {
939    pub content: String,
940    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
941    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
942    /// these keys.
943    ///
944    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
945    #[serde(rename = "_meta")]
946    pub meta: Option<Meta>,
947}
948
949impl ReadTextFileResponse {
950    #[must_use]
951    pub fn new(content: impl Into<String>) -> Self {
952        Self {
953            content: content.into(),
954            meta: None,
955        }
956    }
957
958    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
959    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
960    /// these keys.
961    ///
962    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
963    #[must_use]
964    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
965        self.meta = meta.into_option();
966        self
967    }
968}
969
970// Terminals
971
972#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
973#[serde(transparent)]
974#[from(Arc<str>, String, &'static str)]
975#[non_exhaustive]
976pub struct TerminalId(pub Arc<str>);
977
978impl TerminalId {
979    #[must_use]
980    pub fn new(id: impl Into<Arc<str>>) -> Self {
981        Self(id.into())
982    }
983}
984
985/// Request to create a new terminal and execute a command.
986#[skip_serializing_none]
987#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
988#[serde(rename_all = "camelCase")]
989#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
990#[non_exhaustive]
991pub struct CreateTerminalRequest {
992    /// The session ID for this request.
993    pub session_id: SessionId,
994    /// The command to execute.
995    pub command: String,
996    /// Array of command arguments.
997    #[serde(default, skip_serializing_if = "Vec::is_empty")]
998    pub args: Vec<String>,
999    /// Environment variables for the command.
1000    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1001    pub env: Vec<crate::EnvVariable>,
1002    /// Working directory for the command (absolute path).
1003    pub cwd: Option<PathBuf>,
1004    /// Maximum number of output bytes to retain.
1005    ///
1006    /// When the limit is exceeded, the Client truncates from the beginning of the output
1007    /// to stay within the limit.
1008    ///
1009    /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1010    /// string output, even if this means the retained output is slightly less than the
1011    /// specified limit.
1012    pub output_byte_limit: Option<u64>,
1013    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1014    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1015    /// these keys.
1016    ///
1017    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1018    #[serde(rename = "_meta")]
1019    pub meta: Option<Meta>,
1020}
1021
1022impl CreateTerminalRequest {
1023    #[must_use]
1024    pub fn new(session_id: impl Into<SessionId>, command: impl Into<String>) -> Self {
1025        Self {
1026            session_id: session_id.into(),
1027            command: command.into(),
1028            args: Vec::new(),
1029            env: Vec::new(),
1030            cwd: None,
1031            output_byte_limit: None,
1032            meta: None,
1033        }
1034    }
1035
1036    /// Array of command arguments.
1037    #[must_use]
1038    pub fn args(mut self, args: Vec<String>) -> Self {
1039        self.args = args;
1040        self
1041    }
1042
1043    /// Environment variables for the command.
1044    #[must_use]
1045    pub fn env(mut self, env: Vec<crate::EnvVariable>) -> Self {
1046        self.env = env;
1047        self
1048    }
1049
1050    /// Working directory for the command (absolute path).
1051    #[must_use]
1052    pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1053        self.cwd = cwd.into_option();
1054        self
1055    }
1056
1057    /// Maximum number of output bytes to retain.
1058    ///
1059    /// When the limit is exceeded, the Client truncates from the beginning of the output
1060    /// to stay within the limit.
1061    ///
1062    /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1063    /// string output, even if this means the retained output is slightly less than the
1064    /// specified limit.
1065    #[must_use]
1066    pub fn output_byte_limit(mut self, output_byte_limit: impl IntoOption<u64>) -> Self {
1067        self.output_byte_limit = output_byte_limit.into_option();
1068        self
1069    }
1070
1071    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1072    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1073    /// these keys.
1074    ///
1075    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1076    #[must_use]
1077    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1078        self.meta = meta.into_option();
1079        self
1080    }
1081}
1082
1083/// Response containing the ID of the created terminal.
1084#[skip_serializing_none]
1085#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1086#[serde(rename_all = "camelCase")]
1087#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1088#[non_exhaustive]
1089pub struct CreateTerminalResponse {
1090    /// The unique identifier for the created terminal.
1091    pub terminal_id: TerminalId,
1092    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1093    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1094    /// these keys.
1095    ///
1096    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1097    #[serde(rename = "_meta")]
1098    pub meta: Option<Meta>,
1099}
1100
1101impl CreateTerminalResponse {
1102    #[must_use]
1103    pub fn new(terminal_id: impl Into<TerminalId>) -> Self {
1104        Self {
1105            terminal_id: terminal_id.into(),
1106            meta: None,
1107        }
1108    }
1109
1110    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1111    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1112    /// these keys.
1113    ///
1114    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1115    #[must_use]
1116    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1117        self.meta = meta.into_option();
1118        self
1119    }
1120}
1121
1122/// Request to get the current output and status of a terminal.
1123#[skip_serializing_none]
1124#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1125#[serde(rename_all = "camelCase")]
1126#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1127#[non_exhaustive]
1128pub struct TerminalOutputRequest {
1129    /// The session ID for this request.
1130    pub session_id: SessionId,
1131    /// The ID of the terminal to get output from.
1132    pub terminal_id: TerminalId,
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    #[serde(rename = "_meta")]
1139    pub meta: Option<Meta>,
1140}
1141
1142impl TerminalOutputRequest {
1143    #[must_use]
1144    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1145        Self {
1146            session_id: session_id.into(),
1147            terminal_id: terminal_id.into(),
1148            meta: None,
1149        }
1150    }
1151
1152    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1153    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1154    /// these keys.
1155    ///
1156    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1157    #[must_use]
1158    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1159        self.meta = meta.into_option();
1160        self
1161    }
1162}
1163
1164/// Response containing the terminal output and exit status.
1165#[skip_serializing_none]
1166#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1167#[serde(rename_all = "camelCase")]
1168#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1169#[non_exhaustive]
1170pub struct TerminalOutputResponse {
1171    /// The terminal output captured so far.
1172    pub output: String,
1173    /// Whether the output was truncated due to byte limits.
1174    pub truncated: bool,
1175    /// Exit status if the command has completed.
1176    pub exit_status: Option<TerminalExitStatus>,
1177    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1178    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1179    /// these keys.
1180    ///
1181    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1182    #[serde(rename = "_meta")]
1183    pub meta: Option<Meta>,
1184}
1185
1186impl TerminalOutputResponse {
1187    #[must_use]
1188    pub fn new(output: impl Into<String>, truncated: bool) -> Self {
1189        Self {
1190            output: output.into(),
1191            truncated,
1192            exit_status: None,
1193            meta: None,
1194        }
1195    }
1196
1197    /// Exit status if the command has completed.
1198    #[must_use]
1199    pub fn exit_status(mut self, exit_status: impl IntoOption<TerminalExitStatus>) -> Self {
1200        self.exit_status = exit_status.into_option();
1201        self
1202    }
1203
1204    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1205    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1206    /// these keys.
1207    ///
1208    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1209    #[must_use]
1210    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1211        self.meta = meta.into_option();
1212        self
1213    }
1214}
1215
1216/// Request to release a terminal and free its resources.
1217#[skip_serializing_none]
1218#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1219#[serde(rename_all = "camelCase")]
1220#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1221#[non_exhaustive]
1222pub struct ReleaseTerminalRequest {
1223    /// The session ID for this request.
1224    pub session_id: SessionId,
1225    /// The ID of the terminal to release.
1226    pub terminal_id: TerminalId,
1227    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1228    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1229    /// these keys.
1230    ///
1231    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1232    #[serde(rename = "_meta")]
1233    pub meta: Option<Meta>,
1234}
1235
1236impl ReleaseTerminalRequest {
1237    #[must_use]
1238    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1239        Self {
1240            session_id: session_id.into(),
1241            terminal_id: terminal_id.into(),
1242            meta: None,
1243        }
1244    }
1245
1246    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1247    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1248    /// these keys.
1249    ///
1250    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1251    #[must_use]
1252    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1253        self.meta = meta.into_option();
1254        self
1255    }
1256}
1257
1258/// Response to terminal/release method
1259#[skip_serializing_none]
1260#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1261#[serde(rename_all = "camelCase")]
1262#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1263#[non_exhaustive]
1264pub struct ReleaseTerminalResponse {
1265    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1266    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1267    /// these keys.
1268    ///
1269    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1270    #[serde(rename = "_meta")]
1271    pub meta: Option<Meta>,
1272}
1273
1274impl ReleaseTerminalResponse {
1275    #[must_use]
1276    pub fn new() -> Self {
1277        Self::default()
1278    }
1279
1280    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1281    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1282    /// these keys.
1283    ///
1284    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1285    #[must_use]
1286    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1287        self.meta = meta.into_option();
1288        self
1289    }
1290}
1291
1292/// Request to kill a terminal without releasing it.
1293#[skip_serializing_none]
1294#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1295#[serde(rename_all = "camelCase")]
1296#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1297#[non_exhaustive]
1298pub struct KillTerminalRequest {
1299    /// The session ID for this request.
1300    pub session_id: SessionId,
1301    /// The ID of the terminal to kill.
1302    pub terminal_id: TerminalId,
1303    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1304    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1305    /// these keys.
1306    ///
1307    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1308    #[serde(rename = "_meta")]
1309    pub meta: Option<Meta>,
1310}
1311
1312impl KillTerminalRequest {
1313    #[must_use]
1314    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1315        Self {
1316            session_id: session_id.into(),
1317            terminal_id: terminal_id.into(),
1318            meta: None,
1319        }
1320    }
1321
1322    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1323    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1324    /// these keys.
1325    ///
1326    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1327    #[must_use]
1328    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1329        self.meta = meta.into_option();
1330        self
1331    }
1332}
1333
1334/// Response to `terminal/kill` method
1335#[skip_serializing_none]
1336#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1337#[serde(rename_all = "camelCase")]
1338#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1339#[non_exhaustive]
1340pub struct KillTerminalResponse {
1341    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1342    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1343    /// these keys.
1344    ///
1345    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1346    #[serde(rename = "_meta")]
1347    pub meta: Option<Meta>,
1348}
1349
1350impl KillTerminalResponse {
1351    #[must_use]
1352    pub fn new() -> Self {
1353        Self::default()
1354    }
1355
1356    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1357    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1358    /// these keys.
1359    ///
1360    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1361    #[must_use]
1362    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1363        self.meta = meta.into_option();
1364        self
1365    }
1366}
1367
1368/// Request to wait for a terminal command to exit.
1369#[skip_serializing_none]
1370#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1371#[serde(rename_all = "camelCase")]
1372#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1373#[non_exhaustive]
1374pub struct WaitForTerminalExitRequest {
1375    /// The session ID for this request.
1376    pub session_id: SessionId,
1377    /// The ID of the terminal to wait for.
1378    pub terminal_id: TerminalId,
1379    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1380    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1381    /// these keys.
1382    ///
1383    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1384    #[serde(rename = "_meta")]
1385    pub meta: Option<Meta>,
1386}
1387
1388impl WaitForTerminalExitRequest {
1389    #[must_use]
1390    pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1391        Self {
1392            session_id: session_id.into(),
1393            terminal_id: terminal_id.into(),
1394            meta: None,
1395        }
1396    }
1397
1398    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1399    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1400    /// these keys.
1401    ///
1402    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1403    #[must_use]
1404    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1405        self.meta = meta.into_option();
1406        self
1407    }
1408}
1409
1410/// Response containing the exit status of a terminal command.
1411#[skip_serializing_none]
1412#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1413#[serde(rename_all = "camelCase")]
1414#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1415#[non_exhaustive]
1416pub struct WaitForTerminalExitResponse {
1417    /// The exit status of the terminal command.
1418    #[serde(flatten)]
1419    pub exit_status: TerminalExitStatus,
1420    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1421    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1422    /// these keys.
1423    ///
1424    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1425    #[serde(rename = "_meta")]
1426    pub meta: Option<Meta>,
1427}
1428
1429impl WaitForTerminalExitResponse {
1430    #[must_use]
1431    pub fn new(exit_status: TerminalExitStatus) -> Self {
1432        Self {
1433            exit_status,
1434            meta: None,
1435        }
1436    }
1437
1438    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1439    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1440    /// these keys.
1441    ///
1442    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1443    #[must_use]
1444    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1445        self.meta = meta.into_option();
1446        self
1447    }
1448}
1449
1450/// Exit status of a terminal command.
1451#[skip_serializing_none]
1452#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1453#[serde(rename_all = "camelCase")]
1454#[non_exhaustive]
1455pub struct TerminalExitStatus {
1456    /// The process exit code (may be null if terminated by signal).
1457    pub exit_code: Option<u32>,
1458    /// The signal that terminated the process (may be null if exited normally).
1459    pub signal: Option<String>,
1460    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1461    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1462    /// these keys.
1463    ///
1464    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1465    #[serde(rename = "_meta")]
1466    pub meta: Option<Meta>,
1467}
1468
1469impl TerminalExitStatus {
1470    #[must_use]
1471    pub fn new() -> Self {
1472        Self::default()
1473    }
1474
1475    /// The process exit code (may be null if terminated by signal).
1476    #[must_use]
1477    pub fn exit_code(mut self, exit_code: impl IntoOption<u32>) -> Self {
1478        self.exit_code = exit_code.into_option();
1479        self
1480    }
1481
1482    /// The signal that terminated the process (may be null if exited normally).
1483    #[must_use]
1484    pub fn signal(mut self, signal: impl IntoOption<String>) -> Self {
1485        self.signal = signal.into_option();
1486        self
1487    }
1488
1489    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1490    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1491    /// these keys.
1492    ///
1493    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1494    #[must_use]
1495    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1496        self.meta = meta.into_option();
1497        self
1498    }
1499}
1500
1501// Capabilities
1502
1503/// Capabilities supported by the client.
1504///
1505/// Advertised during initialization to inform the agent about
1506/// available features and methods.
1507///
1508/// See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities)
1509#[serde_as]
1510#[skip_serializing_none]
1511#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1512#[serde(rename_all = "camelCase")]
1513#[non_exhaustive]
1514pub struct ClientCapabilities {
1515    /// File system capabilities supported by the client.
1516    /// Determines which file operations the agent can request.
1517    #[serde(default)]
1518    pub fs: FileSystemCapabilities,
1519    /// Whether the Client support all `terminal/*` methods.
1520    #[serde(default)]
1521    pub terminal: bool,
1522    /// **UNSTABLE**
1523    ///
1524    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1525    ///
1526    /// Authentication capabilities supported by the client.
1527    /// Determines which authentication method types the agent may include
1528    /// in its `InitializeResponse`.
1529    #[cfg(feature = "unstable_auth_methods")]
1530    #[serde(default)]
1531    pub auth: AuthCapabilities,
1532    /// **UNSTABLE**
1533    ///
1534    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1535    ///
1536    /// Elicitation capabilities supported by the client.
1537    /// Determines which elicitation modes the agent may use.
1538    #[cfg(feature = "unstable_elicitation")]
1539    #[serde_as(deserialize_as = "DefaultOnError")]
1540    #[serde(default)]
1541    pub elicitation: Option<ElicitationCapabilities>,
1542    /// **UNSTABLE**
1543    ///
1544    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1545    ///
1546    /// NES (Next Edit Suggestions) capabilities supported by the client.
1547    #[cfg(feature = "unstable_nes")]
1548    #[serde_as(deserialize_as = "DefaultOnError")]
1549    #[serde(default)]
1550    pub nes: Option<ClientNesCapabilities>,
1551    /// **UNSTABLE**
1552    ///
1553    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1554    ///
1555    /// The position encodings supported by the client, in order of preference.
1556    #[cfg(feature = "unstable_nes")]
1557    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1558    #[serde(default, skip_serializing_if = "Vec::is_empty")]
1559    pub position_encodings: Vec<PositionEncodingKind>,
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    #[serde(rename = "_meta")]
1567    pub meta: Option<Meta>,
1568}
1569
1570impl ClientCapabilities {
1571    #[must_use]
1572    pub fn new() -> Self {
1573        Self::default()
1574    }
1575
1576    /// File system capabilities supported by the client.
1577    /// Determines which file operations the agent can request.
1578    #[must_use]
1579    pub fn fs(mut self, fs: FileSystemCapabilities) -> Self {
1580        self.fs = fs;
1581        self
1582    }
1583
1584    /// Whether the Client support all `terminal/*` methods.
1585    #[must_use]
1586    pub fn terminal(mut self, terminal: bool) -> Self {
1587        self.terminal = terminal;
1588        self
1589    }
1590
1591    /// **UNSTABLE**
1592    ///
1593    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1594    ///
1595    /// Authentication capabilities supported by the client.
1596    /// Determines which authentication method types the agent may include
1597    /// in its `InitializeResponse`.
1598    #[cfg(feature = "unstable_auth_methods")]
1599    #[must_use]
1600    pub fn auth(mut self, auth: AuthCapabilities) -> Self {
1601        self.auth = auth;
1602        self
1603    }
1604
1605    /// **UNSTABLE**
1606    ///
1607    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1608    ///
1609    /// Elicitation capabilities supported by the client.
1610    /// Determines which elicitation modes the agent may use.
1611    #[cfg(feature = "unstable_elicitation")]
1612    #[must_use]
1613    pub fn elicitation(mut self, elicitation: impl IntoOption<ElicitationCapabilities>) -> Self {
1614        self.elicitation = elicitation.into_option();
1615        self
1616    }
1617
1618    /// **UNSTABLE**
1619    ///
1620    /// NES (Next Edit Suggestions) capabilities supported by the client.
1621    #[cfg(feature = "unstable_nes")]
1622    #[must_use]
1623    pub fn nes(mut self, nes: impl IntoOption<ClientNesCapabilities>) -> Self {
1624        self.nes = nes.into_option();
1625        self
1626    }
1627
1628    /// **UNSTABLE**
1629    ///
1630    /// The position encodings supported by the client, in order of preference.
1631    #[cfg(feature = "unstable_nes")]
1632    #[must_use]
1633    pub fn position_encodings(mut self, position_encodings: Vec<PositionEncodingKind>) -> Self {
1634        self.position_encodings = position_encodings;
1635        self
1636    }
1637
1638    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1639    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1640    /// these keys.
1641    ///
1642    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1643    #[must_use]
1644    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1645        self.meta = meta.into_option();
1646        self
1647    }
1648}
1649
1650/// **UNSTABLE**
1651///
1652/// This capability is not part of the spec yet, and may be removed or changed at any point.
1653///
1654/// Authentication capabilities supported by the client.
1655///
1656/// Advertised during initialization to inform the agent which authentication
1657/// method types the client can handle. This governs opt-in types that require
1658/// additional client-side support.
1659#[cfg(feature = "unstable_auth_methods")]
1660#[skip_serializing_none]
1661#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1662#[serde(rename_all = "camelCase")]
1663#[non_exhaustive]
1664pub struct AuthCapabilities {
1665    /// Whether the client supports `terminal` authentication methods.
1666    ///
1667    /// When `true`, the agent may include `terminal` entries in its authentication methods.
1668    #[serde(default)]
1669    pub terminal: bool,
1670    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1671    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1672    /// these keys.
1673    ///
1674    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1675    #[serde(rename = "_meta")]
1676    pub meta: Option<Meta>,
1677}
1678
1679#[cfg(feature = "unstable_auth_methods")]
1680impl AuthCapabilities {
1681    #[must_use]
1682    pub fn new() -> Self {
1683        Self::default()
1684    }
1685
1686    /// Whether the client supports `terminal` authentication methods.
1687    ///
1688    /// When `true`, the agent may include `AuthMethod::Terminal`
1689    /// entries in its authentication methods.
1690    #[must_use]
1691    pub fn terminal(mut self, terminal: bool) -> Self {
1692        self.terminal = terminal;
1693        self
1694    }
1695
1696    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1697    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1698    /// these keys.
1699    ///
1700    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1701    #[must_use]
1702    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1703        self.meta = meta.into_option();
1704        self
1705    }
1706}
1707
1708/// File system capabilities that a client may support.
1709///
1710/// See protocol docs: [FileSystem](https://agentclientprotocol.com/protocol/initialization#filesystem)
1711#[skip_serializing_none]
1712#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1713#[serde(rename_all = "camelCase")]
1714#[non_exhaustive]
1715pub struct FileSystemCapabilities {
1716    /// Whether the Client supports `fs/read_text_file` requests.
1717    #[serde(default)]
1718    pub read_text_file: bool,
1719    /// Whether the Client supports `fs/write_text_file` requests.
1720    #[serde(default)]
1721    pub write_text_file: bool,
1722    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1723    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1724    /// these keys.
1725    ///
1726    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1727    #[serde(rename = "_meta")]
1728    pub meta: Option<Meta>,
1729}
1730
1731impl FileSystemCapabilities {
1732    #[must_use]
1733    pub fn new() -> Self {
1734        Self::default()
1735    }
1736
1737    /// Whether the Client supports `fs/read_text_file` requests.
1738    #[must_use]
1739    pub fn read_text_file(mut self, read_text_file: bool) -> Self {
1740        self.read_text_file = read_text_file;
1741        self
1742    }
1743
1744    /// Whether the Client supports `fs/write_text_file` requests.
1745    #[must_use]
1746    pub fn write_text_file(mut self, write_text_file: bool) -> Self {
1747        self.write_text_file = write_text_file;
1748        self
1749    }
1750
1751    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1752    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1753    /// these keys.
1754    ///
1755    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1756    #[must_use]
1757    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1758        self.meta = meta.into_option();
1759        self
1760    }
1761}
1762
1763// Method schema
1764
1765/// Names of all methods that clients handle.
1766///
1767/// Provides a centralized definition of method names used in the protocol.
1768#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1769#[non_exhaustive]
1770pub struct ClientMethodNames {
1771    /// Method for requesting permission from the user.
1772    pub session_request_permission: &'static str,
1773    /// Notification for session updates.
1774    pub session_update: &'static str,
1775    /// Method for writing text files.
1776    pub fs_write_text_file: &'static str,
1777    /// Method for reading text files.
1778    pub fs_read_text_file: &'static str,
1779    /// Method for creating new terminals.
1780    pub terminal_create: &'static str,
1781    /// Method for getting terminals output.
1782    pub terminal_output: &'static str,
1783    /// Method for releasing a terminal.
1784    pub terminal_release: &'static str,
1785    /// Method for waiting for a terminal to finish.
1786    pub terminal_wait_for_exit: &'static str,
1787    /// Method for killing a terminal.
1788    pub terminal_kill: &'static str,
1789    /// Method for elicitation.
1790    #[cfg(feature = "unstable_elicitation")]
1791    pub elicitation_create: &'static str,
1792    /// Notification for elicitation completion.
1793    #[cfg(feature = "unstable_elicitation")]
1794    pub elicitation_complete: &'static str,
1795}
1796
1797/// Constant containing all client method names.
1798pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
1799    session_update: SESSION_UPDATE_NOTIFICATION,
1800    session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
1801    fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
1802    fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
1803    terminal_create: TERMINAL_CREATE_METHOD_NAME,
1804    terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
1805    terminal_release: TERMINAL_RELEASE_METHOD_NAME,
1806    terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
1807    terminal_kill: TERMINAL_KILL_METHOD_NAME,
1808    #[cfg(feature = "unstable_elicitation")]
1809    elicitation_create: ELICITATION_CREATE_METHOD_NAME,
1810    #[cfg(feature = "unstable_elicitation")]
1811    elicitation_complete: ELICITATION_COMPLETE_NOTIFICATION,
1812};
1813
1814/// Notification name for session updates.
1815pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
1816/// Method name for requesting user permission.
1817pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
1818/// Method name for writing text files.
1819pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
1820/// Method name for reading text files.
1821pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
1822/// Method name for creating a new terminal.
1823pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
1824/// Method for getting terminals output.
1825pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
1826/// Method for releasing a terminal.
1827pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
1828/// Method for waiting for a terminal to finish.
1829pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
1830/// Method for killing a terminal.
1831pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
1832/// Method name for elicitation.
1833#[cfg(feature = "unstable_elicitation")]
1834pub(crate) const ELICITATION_CREATE_METHOD_NAME: &str = "elicitation/create";
1835/// Notification name for elicitation completion.
1836#[cfg(feature = "unstable_elicitation")]
1837pub(crate) const ELICITATION_COMPLETE_NOTIFICATION: &str = "elicitation/complete";
1838
1839/// All possible requests that an agent can send to a client.
1840///
1841/// This enum is used internally for routing RPC requests. You typically won't need
1842/// to use this directly - instead, use the methods on the [`Client`] trait.
1843///
1844/// This enum encompasses all method calls from agent to client.
1845#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1846#[serde(untagged)]
1847#[schemars(inline)]
1848#[non_exhaustive]
1849pub enum AgentRequest {
1850    /// Writes content to a text file in the client's file system.
1851    ///
1852    /// Only available if the client advertises the `fs.writeTextFile` capability.
1853    /// Allows the agent to create or modify files within the client's environment.
1854    ///
1855    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
1856    WriteTextFileRequest(WriteTextFileRequest),
1857    /// Reads content from a text file in the client's file system.
1858    ///
1859    /// Only available if the client advertises the `fs.readTextFile` capability.
1860    /// Allows the agent to access file contents within the client's environment.
1861    ///
1862    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
1863    ReadTextFileRequest(ReadTextFileRequest),
1864    /// Requests permission from the user for a tool call operation.
1865    ///
1866    /// Called by the agent when it needs user authorization before executing
1867    /// a potentially sensitive operation. The client should present the options
1868    /// to the user and return their decision.
1869    ///
1870    /// If the client cancels the prompt turn via `session/cancel`, it MUST
1871    /// respond to this request with `RequestPermissionOutcome::Cancelled`.
1872    ///
1873    /// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
1874    RequestPermissionRequest(RequestPermissionRequest),
1875    /// Executes a command in a new terminal
1876    ///
1877    /// Only available if the `terminal` Client capability is set to `true`.
1878    ///
1879    /// Returns a `TerminalId` that can be used with other terminal methods
1880    /// to get the current output, wait for exit, and kill the command.
1881    ///
1882    /// The `TerminalId` can also be used to embed the terminal in a tool call
1883    /// by using the `ToolCallContent::Terminal` variant.
1884    ///
1885    /// The Agent is responsible for releasing the terminal by using the `terminal/release`
1886    /// method.
1887    ///
1888    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1889    CreateTerminalRequest(CreateTerminalRequest),
1890    /// Gets the terminal output and exit status
1891    ///
1892    /// Returns the current content in the terminal without waiting for the command to exit.
1893    /// If the command has already exited, the exit status is included.
1894    ///
1895    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1896    TerminalOutputRequest(TerminalOutputRequest),
1897    /// Releases a terminal
1898    ///
1899    /// The command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`
1900    /// to wait for the command to exit before releasing the terminal.
1901    ///
1902    /// After release, the `TerminalId` can no longer be used with other `terminal/*` methods,
1903    /// but tool calls that already contain it, continue to display its output.
1904    ///
1905    /// The `terminal/kill` method can be used to terminate the command without releasing
1906    /// the terminal, allowing the Agent to call `terminal/output` and other methods.
1907    ///
1908    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1909    ReleaseTerminalRequest(ReleaseTerminalRequest),
1910    /// Waits for the terminal command to exit and return its exit status
1911    ///
1912    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1913    WaitForTerminalExitRequest(WaitForTerminalExitRequest),
1914    /// Kills the terminal command without releasing the terminal
1915    ///
1916    /// While `terminal/release` will also kill the command, this method will keep
1917    /// the `TerminalId` valid so it can be used with other methods.
1918    ///
1919    /// This method can be helpful when implementing command timeouts which terminate
1920    /// the command as soon as elapsed, and then get the final output so it can be sent
1921    /// to the model.
1922    ///
1923    /// Note: Call `terminal/release` when `TerminalId` is no longer needed.
1924    ///
1925    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1926    KillTerminalRequest(KillTerminalRequest),
1927    /// **UNSTABLE**
1928    ///
1929    /// This capability is not part of the spec yet, and may be removed or changed at any point.
1930    ///
1931    /// Requests structured user input via a form or URL.
1932    #[cfg(feature = "unstable_elicitation")]
1933    CreateElicitationRequest(CreateElicitationRequest),
1934    /// Handles extension method requests from the agent.
1935    ///
1936    /// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
1937    /// Extension methods provide a way to add custom functionality while maintaining
1938    /// protocol compatibility.
1939    ///
1940    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1941    ExtMethodRequest(ExtRequest),
1942}
1943
1944impl AgentRequest {
1945    /// Returns the corresponding method name of the request.
1946    #[must_use]
1947    pub fn method(&self) -> &str {
1948        match self {
1949            Self::WriteTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_write_text_file,
1950            Self::ReadTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_read_text_file,
1951            Self::RequestPermissionRequest(_) => CLIENT_METHOD_NAMES.session_request_permission,
1952            Self::CreateTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_create,
1953            Self::TerminalOutputRequest(_) => CLIENT_METHOD_NAMES.terminal_output,
1954            Self::ReleaseTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_release,
1955            Self::WaitForTerminalExitRequest(_) => CLIENT_METHOD_NAMES.terminal_wait_for_exit,
1956            Self::KillTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_kill,
1957            #[cfg(feature = "unstable_elicitation")]
1958            Self::CreateElicitationRequest(_) => CLIENT_METHOD_NAMES.elicitation_create,
1959            Self::ExtMethodRequest(ext_request) => &ext_request.method,
1960        }
1961    }
1962}
1963
1964/// All possible responses that a client can send to an agent.
1965///
1966/// This enum is used internally for routing RPC responses. You typically won't need
1967/// to use this directly - the responses are handled automatically by the connection.
1968///
1969/// These are responses to the corresponding `AgentRequest` variants.
1970#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1971#[serde(untagged)]
1972#[schemars(inline)]
1973#[non_exhaustive]
1974pub enum ClientResponse {
1975    WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
1976    ReadTextFileResponse(ReadTextFileResponse),
1977    RequestPermissionResponse(RequestPermissionResponse),
1978    CreateTerminalResponse(CreateTerminalResponse),
1979    TerminalOutputResponse(TerminalOutputResponse),
1980    ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
1981    WaitForTerminalExitResponse(WaitForTerminalExitResponse),
1982    KillTerminalResponse(#[serde(default)] KillTerminalResponse),
1983    #[cfg(feature = "unstable_elicitation")]
1984    CreateElicitationResponse(CreateElicitationResponse),
1985    ExtMethodResponse(ExtResponse),
1986}
1987
1988/// All possible notifications that an agent can send to a client.
1989///
1990/// This enum is used internally for routing RPC notifications. You typically won't need
1991/// to use this directly - use the notification methods on the [`Client`] trait instead.
1992///
1993/// Notifications do not expect a response.
1994#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1995#[serde(untagged)]
1996#[expect(clippy::large_enum_variant)]
1997#[schemars(inline)]
1998#[non_exhaustive]
1999pub enum AgentNotification {
2000    /// Handles session update notifications from the agent.
2001    ///
2002    /// This is a notification endpoint (no response expected) that receives
2003    /// real-time updates about session progress, including message chunks,
2004    /// tool calls, and execution plans.
2005    ///
2006    /// Note: Clients SHOULD continue accepting tool call updates even after
2007    /// sending a `session/cancel` notification, as the agent may send final
2008    /// updates before responding with the cancelled stop reason.
2009    ///
2010    /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
2011    SessionNotification(SessionNotification),
2012    /// **UNSTABLE**
2013    ///
2014    /// This capability is not part of the spec yet, and may be removed or changed at any point.
2015    ///
2016    /// Notification that a URL-based elicitation has completed.
2017    #[cfg(feature = "unstable_elicitation")]
2018    CompleteElicitationNotification(CompleteElicitationNotification),
2019    /// Handles extension notifications from the agent.
2020    ///
2021    /// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
2022    /// Extension notifications provide a way to send one-way messages for custom functionality
2023    /// while maintaining protocol compatibility.
2024    ///
2025    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2026    ExtNotification(ExtNotification),
2027}
2028
2029impl AgentNotification {
2030    /// Returns the corresponding method name of the notification.
2031    #[must_use]
2032    pub fn method(&self) -> &str {
2033        match self {
2034            Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update,
2035            #[cfg(feature = "unstable_elicitation")]
2036            Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete,
2037            Self::ExtNotification(ext_notification) => &ext_notification.method,
2038        }
2039    }
2040}
2041
2042#[cfg(test)]
2043mod tests {
2044    use super::*;
2045
2046    #[test]
2047    fn test_serialization_behavior() {
2048        use serde_json::json;
2049
2050        assert_eq!(
2051            serde_json::from_value::<SessionInfoUpdate>(json!({})).unwrap(),
2052            SessionInfoUpdate {
2053                title: MaybeUndefined::Undefined,
2054                updated_at: MaybeUndefined::Undefined,
2055                meta: None
2056            }
2057        );
2058        assert_eq!(
2059            serde_json::from_value::<SessionInfoUpdate>(json!({"title": null, "updatedAt": null}))
2060                .unwrap(),
2061            SessionInfoUpdate {
2062                title: MaybeUndefined::Null,
2063                updated_at: MaybeUndefined::Null,
2064                meta: None
2065            }
2066        );
2067        assert_eq!(
2068            serde_json::from_value::<SessionInfoUpdate>(
2069                json!({"title": "title", "updatedAt": "timestamp"})
2070            )
2071            .unwrap(),
2072            SessionInfoUpdate {
2073                title: MaybeUndefined::Value("title".to_string()),
2074                updated_at: MaybeUndefined::Value("timestamp".to_string()),
2075                meta: None
2076            }
2077        );
2078
2079        assert_eq!(
2080            serde_json::to_value(SessionInfoUpdate::new()).unwrap(),
2081            json!({})
2082        );
2083        assert_eq!(
2084            serde_json::to_value(SessionInfoUpdate::new().title("title")).unwrap(),
2085            json!({"title": "title"})
2086        );
2087        assert_eq!(
2088            serde_json::to_value(SessionInfoUpdate::new().title(None)).unwrap(),
2089            json!({"title": null})
2090        );
2091        assert_eq!(
2092            serde_json::to_value(
2093                SessionInfoUpdate::new()
2094                    .title("title")
2095                    .title(MaybeUndefined::Undefined)
2096            )
2097            .unwrap(),
2098            json!({})
2099        );
2100    }
2101
2102    #[cfg(feature = "unstable_nes")]
2103    #[test]
2104    fn test_client_capabilities_position_encodings_serialization() {
2105        use serde_json::json;
2106
2107        let capabilities = ClientCapabilities::new().position_encodings(vec![
2108            PositionEncodingKind::Utf32,
2109            PositionEncodingKind::Utf16,
2110        ]);
2111        let json = serde_json::to_value(&capabilities).unwrap();
2112
2113        assert_eq!(json["positionEncodings"], json!(["utf-32", "utf-16"]));
2114    }
2115}