Skip to main content

agent_client_protocol_schema/
client.rs

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