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