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