agent_client_protocol_schema/
client.rs

1//! Methods and notifications the client handles/receives.
2//!
3//! This module defines the Client trait and all associated types for implementing
4//! a client that interacts with AI coding agents via the Agent Client Protocol (ACP).
5
6use std::{path::PathBuf, sync::Arc};
7
8use derive_more::{Display, From};
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use serde_json::value::RawValue;
12
13use crate::{
14    ContentBlock, ExtNotification, Plan, SessionId, SessionModeId, ToolCall, ToolCallUpdate,
15    ext::ExtRequest,
16};
17
18// Session updates
19
20/// Notification containing a session update from the agent.
21///
22/// Used to stream real-time progress and results during prompt processing.
23///
24/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
26#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
27#[serde(rename_all = "camelCase")]
28pub struct SessionNotification {
29    /// The ID of the session this update pertains to.
30    pub session_id: SessionId,
31    /// The actual update content.
32    pub update: SessionUpdate,
33    /// Extension point for implementations
34    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
35    pub meta: Option<serde_json::Value>,
36}
37
38/// Different types of updates that can be sent during session processing.
39///
40/// These updates provide real-time feedback about the agent's progress.
41///
42/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
43#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
44#[serde(rename_all = "snake_case", tag = "sessionUpdate")]
45pub enum SessionUpdate {
46    /// A chunk of the user's message being streamed.
47    UserMessageChunk { content: ContentBlock },
48    /// A chunk of the agent's response being streamed.
49    AgentMessageChunk { content: ContentBlock },
50    /// A chunk of the agent's internal reasoning being streamed.
51    AgentThoughtChunk { content: ContentBlock },
52    /// Notification that a new tool call has been initiated.
53    ToolCall(ToolCall),
54    /// Update on the status or results of a tool call.
55    ToolCallUpdate(ToolCallUpdate),
56    /// The agent's execution plan for complex tasks.
57    /// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
58    Plan(Plan),
59    /// Available commands are ready or have changed
60    #[serde(rename_all = "camelCase")]
61    AvailableCommandsUpdate {
62        available_commands: Vec<AvailableCommand>,
63    },
64    /// The current mode of the session has changed
65    ///
66    /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
67    #[serde(rename_all = "camelCase")]
68    CurrentModeUpdate { current_mode_id: SessionModeId },
69}
70
71/// Information about a command.
72#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
73#[serde(rename_all = "camelCase")]
74pub struct AvailableCommand {
75    /// Command name (e.g., `create_plan`, `research_codebase`).
76    pub name: String,
77    /// Human-readable description of what the command does.
78    pub description: String,
79    /// Input for the command if required
80    pub input: Option<AvailableCommandInput>,
81    /// Extension point for implementations
82    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
83    pub meta: Option<serde_json::Value>,
84}
85
86/// The input specification for a command.
87#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
88#[serde(untagged, rename_all = "camelCase")]
89pub enum AvailableCommandInput {
90    /// All text that was typed after the command name is provided as input.
91    #[schemars(rename = "UnstructuredCommandInput")]
92    Unstructured {
93        /// A hint to display when the input hasn't been provided yet
94        hint: String,
95    },
96}
97
98// Permission
99
100/// Request for user permission to execute a tool call.
101///
102/// Sent when the agent needs authorization before performing a sensitive operation.
103///
104/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
105#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
106#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
107#[serde(rename_all = "camelCase")]
108pub struct RequestPermissionRequest {
109    /// The session ID for this request.
110    pub session_id: SessionId,
111    /// Details about the tool call requiring permission.
112    pub tool_call: ToolCallUpdate,
113    /// Available permission options for the user to choose from.
114    pub options: Vec<PermissionOption>,
115    /// Extension point for implementations
116    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
117    pub meta: Option<serde_json::Value>,
118}
119
120/// An option presented to the user when requesting permission.
121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
122pub struct PermissionOption {
123    /// Unique identifier for this permission option.
124    #[serde(rename = "optionId")]
125    pub id: PermissionOptionId,
126    /// Human-readable label to display to the user.
127    pub name: String,
128    /// Hint about the nature of this permission option.
129    pub kind: PermissionOptionKind,
130    /// Extension point for implementations
131    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
132    pub meta: Option<serde_json::Value>,
133}
134
135/// Unique identifier for a permission option.
136#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
137#[serde(transparent)]
138#[from(Arc<str>, String, &'static str)]
139pub struct PermissionOptionId(pub Arc<str>);
140
141/// The type of permission option being presented to the user.
142///
143/// Helps clients choose appropriate icons and UI treatment.
144#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
145#[serde(rename_all = "snake_case")]
146pub enum PermissionOptionKind {
147    /// Allow this operation only this time.
148    AllowOnce,
149    /// Allow this operation and remember the choice.
150    AllowAlways,
151    /// Reject this operation only this time.
152    RejectOnce,
153    /// Reject this operation and remember the choice.
154    RejectAlways,
155}
156
157/// Response to a permission request.
158#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
159#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
160#[serde(rename_all = "camelCase")]
161pub struct RequestPermissionResponse {
162    /// The user's decision on the permission request.
163    // This extra-level is unfortunately needed because the output must be an object
164    pub outcome: RequestPermissionOutcome,
165    /// Extension point for implementations
166    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
167    pub meta: Option<serde_json::Value>,
168}
169
170/// The outcome of a permission request.
171#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
172#[serde(tag = "outcome", rename_all = "snake_case")]
173pub enum RequestPermissionOutcome {
174    /// The prompt turn was cancelled before the user responded.
175    ///
176    /// When a client sends a `session/cancel` notification to cancel an ongoing
177    /// prompt turn, it MUST respond to all pending `session/request_permission`
178    /// requests with this `Cancelled` outcome.
179    ///
180    /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
181    Cancelled,
182    /// The user selected one of the provided options.
183    #[serde(rename_all = "camelCase")]
184    Selected {
185        /// The ID of the option the user selected.
186        option_id: PermissionOptionId,
187    },
188}
189
190// Write text file
191
192/// Request to write content to a text file.
193///
194/// Only available if the client supports the `fs.writeTextFile` capability.
195#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
196#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
197#[serde(rename_all = "camelCase")]
198pub struct WriteTextFileRequest {
199    /// The session ID for this request.
200    pub session_id: SessionId,
201    /// Absolute path to the file to write.
202    pub path: PathBuf,
203    /// The text content to write to the file.
204    pub content: String,
205    /// Extension point for implementations
206    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
207    pub meta: Option<serde_json::Value>,
208}
209
210/// Response to `fs/write_text_file`
211#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
212#[serde(rename_all = "camelCase")]
213#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
214#[serde(default)]
215pub struct WriteTextFileResponse {
216    /// Extension point for implementations
217    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
218    pub meta: Option<serde_json::Value>,
219}
220
221// Read text file
222
223/// Request to read content from a text file.
224///
225/// Only available if the client supports the `fs.readTextFile` capability.
226#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
227#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
228#[serde(rename_all = "camelCase")]
229pub struct ReadTextFileRequest {
230    /// The session ID for this request.
231    pub session_id: SessionId,
232    /// Absolute path to the file to read.
233    pub path: PathBuf,
234    /// Line number to start reading from (1-based).
235    #[serde(default, skip_serializing_if = "Option::is_none")]
236    pub line: Option<u32>,
237    /// Maximum number of lines to read.
238    #[serde(default, skip_serializing_if = "Option::is_none")]
239    pub limit: Option<u32>,
240    /// Extension point for implementations
241    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
242    pub meta: Option<serde_json::Value>,
243}
244
245/// Response containing the contents of a text file.
246#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
247#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
248#[serde(rename_all = "camelCase")]
249pub struct ReadTextFileResponse {
250    pub content: String,
251    /// Extension point for implementations
252    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
253    pub meta: Option<serde_json::Value>,
254}
255
256// Terminals
257
258#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
259#[serde(transparent)]
260#[from(Arc<str>, String, &'static str)]
261pub struct TerminalId(pub Arc<str>);
262
263/// Request to create a new terminal and execute a command.
264#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
265#[serde(rename_all = "camelCase")]
266#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
267pub struct CreateTerminalRequest {
268    /// The session ID for this request.
269    pub session_id: SessionId,
270    /// The command to execute.
271    pub command: String,
272    /// Array of command arguments.
273    #[serde(default, skip_serializing_if = "Vec::is_empty")]
274    pub args: Vec<String>,
275    /// Environment variables for the command.
276    #[serde(default, skip_serializing_if = "Vec::is_empty")]
277    pub env: Vec<crate::EnvVariable>,
278    /// Working directory for the command (absolute path).
279    #[serde(default, skip_serializing_if = "Option::is_none")]
280    pub cwd: Option<PathBuf>,
281    /// Maximum number of output bytes to retain.
282    ///
283    /// When the limit is exceeded, the Client truncates from the beginning of the output
284    /// to stay within the limit.
285    ///
286    /// The Client MUST ensure truncation happens at a character boundary to maintain valid
287    /// string output, even if this means the retained output is slightly less than the
288    /// specified limit.
289    #[serde(default, skip_serializing_if = "Option::is_none")]
290    pub output_byte_limit: Option<u64>,
291    /// Extension point for implementations
292    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
293    pub meta: Option<serde_json::Value>,
294}
295
296/// Response containing the ID of the created terminal.
297#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
298#[serde(rename_all = "camelCase")]
299#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
300pub struct CreateTerminalResponse {
301    /// The unique identifier for the created terminal.
302    pub terminal_id: TerminalId,
303    /// Extension point for implementations
304    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
305    pub meta: Option<serde_json::Value>,
306}
307
308/// Request to get the current output and status of a terminal.
309#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
310#[serde(rename_all = "camelCase")]
311#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
312pub struct TerminalOutputRequest {
313    /// The session ID for this request.
314    pub session_id: SessionId,
315    /// The ID of the terminal to get output from.
316    pub terminal_id: TerminalId,
317    /// Extension point for implementations
318    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
319    pub meta: Option<serde_json::Value>,
320}
321
322/// Response containing the terminal output and exit status.
323#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
324#[serde(rename_all = "camelCase")]
325#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
326pub struct TerminalOutputResponse {
327    /// The terminal output captured so far.
328    pub output: String,
329    /// Whether the output was truncated due to byte limits.
330    pub truncated: bool,
331    /// Exit status if the command has completed.
332    pub exit_status: Option<TerminalExitStatus>,
333    /// Extension point for implementations
334    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
335    pub meta: Option<serde_json::Value>,
336}
337
338/// Request to release a terminal and free its resources.
339#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
340#[serde(rename_all = "camelCase")]
341#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
342pub struct ReleaseTerminalRequest {
343    /// The session ID for this request.
344    pub session_id: SessionId,
345    /// The ID of the terminal to release.
346    pub terminal_id: TerminalId,
347    /// Extension point for implementations
348    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
349    pub meta: Option<serde_json::Value>,
350}
351
352/// Response to terminal/release method
353#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
354#[serde(rename_all = "camelCase")]
355#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
356pub struct ReleaseTerminalResponse {
357    /// Extension point for implementations
358    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
359    pub meta: Option<serde_json::Value>,
360}
361
362/// Request to kill a terminal command without releasing the terminal.
363#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
364#[serde(rename_all = "camelCase")]
365#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
366pub struct KillTerminalCommandRequest {
367    /// The session ID for this request.
368    pub session_id: SessionId,
369    /// The ID of the terminal to kill.
370    pub terminal_id: TerminalId,
371    /// Extension point for implementations
372    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
373    pub meta: Option<serde_json::Value>,
374}
375
376/// Response to terminal/kill command method
377#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
378#[serde(rename_all = "camelCase")]
379#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
380pub struct KillTerminalCommandResponse {
381    /// Extension point for implementations
382    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
383    pub meta: Option<serde_json::Value>,
384}
385
386/// Request to wait for a terminal command to exit.
387#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
388#[serde(rename_all = "camelCase")]
389#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
390pub struct WaitForTerminalExitRequest {
391    /// The session ID for this request.
392    pub session_id: SessionId,
393    /// The ID of the terminal to wait for.
394    pub terminal_id: TerminalId,
395    /// Extension point for implementations
396    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
397    pub meta: Option<serde_json::Value>,
398}
399
400/// Response containing the exit status of a terminal command.
401#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
402#[serde(rename_all = "camelCase")]
403#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
404pub struct WaitForTerminalExitResponse {
405    /// The exit status of the terminal command.
406    #[serde(flatten)]
407    pub exit_status: TerminalExitStatus,
408    /// Extension point for implementations
409    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
410    pub meta: Option<serde_json::Value>,
411}
412
413/// Exit status of a terminal command.
414#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
415#[serde(rename_all = "camelCase")]
416pub struct TerminalExitStatus {
417    /// The process exit code (may be null if terminated by signal).
418    pub exit_code: Option<u32>,
419    /// The signal that terminated the process (may be null if exited normally).
420    pub signal: Option<String>,
421    /// Extension point for implementations
422    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
423    pub meta: Option<serde_json::Value>,
424}
425
426// Capabilities
427
428/// Capabilities supported by the client.
429///
430/// Advertised during initialization to inform the agent about
431/// available features and methods.
432///
433/// See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities)
434#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
435#[serde(rename_all = "camelCase")]
436pub struct ClientCapabilities {
437    /// File system capabilities supported by the client.
438    /// Determines which file operations the agent can request.
439    #[serde(default)]
440    pub fs: FileSystemCapability,
441    /// Whether the Client support all `terminal/*` methods.
442    #[serde(default)]
443    pub terminal: bool,
444    /// Extension point for implementations
445    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
446    pub meta: Option<serde_json::Value>,
447}
448
449/// File system capabilities that a client may support.
450///
451/// See protocol docs: [FileSystem](https://agentclientprotocol.com/protocol/initialization#filesystem)
452#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
453#[serde(rename_all = "camelCase")]
454pub struct FileSystemCapability {
455    /// Whether the Client supports `fs/read_text_file` requests.
456    #[serde(default)]
457    pub read_text_file: bool,
458    /// Whether the Client supports `fs/write_text_file` requests.
459    #[serde(default)]
460    pub write_text_file: bool,
461    /// Extension point for implementations
462    #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
463    pub meta: Option<serde_json::Value>,
464}
465
466// Method schema
467
468/// Names of all methods that clients handle.
469///
470/// Provides a centralized definition of method names used in the protocol.
471#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
472pub struct ClientMethodNames {
473    /// Method for requesting permission from the user.
474    pub session_request_permission: &'static str,
475    /// Notification for session updates.
476    pub session_update: &'static str,
477    /// Method for writing text files.
478    pub fs_write_text_file: &'static str,
479    /// Method for reading text files.
480    pub fs_read_text_file: &'static str,
481    /// Method for creating new terminals.
482    pub terminal_create: &'static str,
483    /// Method for getting terminals output.
484    pub terminal_output: &'static str,
485    /// Method for releasing a terminal.
486    pub terminal_release: &'static str,
487    /// Method for waiting for a terminal to finish.
488    pub terminal_wait_for_exit: &'static str,
489    /// Method for killing a terminal.
490    pub terminal_kill: &'static str,
491}
492
493/// Constant containing all client method names.
494pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
495    session_update: SESSION_UPDATE_NOTIFICATION,
496    session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
497    fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
498    fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
499    terminal_create: TERMINAL_CREATE_METHOD_NAME,
500    terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
501    terminal_release: TERMINAL_RELEASE_METHOD_NAME,
502    terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
503    terminal_kill: TERMINAL_KILL_METHOD_NAME,
504};
505
506/// Notification name for session updates.
507pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
508/// Method name for requesting user permission.
509pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
510/// Method name for writing text files.
511pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
512/// Method name for reading text files.
513pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
514/// Method name for creating a new terminal.
515pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
516/// Method for getting terminals output.
517pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
518/// Method for releasing a terminal.
519pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
520/// Method for waiting for a terminal to finish.
521pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
522/// Method for killing a terminal.
523pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
524
525/// All possible requests that an agent can send to a client.
526///
527/// This enum is used internally for routing RPC requests. You typically won't need
528/// to use this directly - instead, use the methods on the [`Client`] trait.
529///
530/// This enum encompasses all method calls from agent to client.
531#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
532#[serde(untagged)]
533#[schemars(extend("x-docs-ignore" = true))]
534pub enum AgentRequest {
535    /// Writes content to a text file in the client's file system.
536    ///
537    /// Only available if the client advertises the `fs.writeTextFile` capability.
538    /// Allows the agent to create or modify files within the client's environment.
539    ///
540    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
541    WriteTextFileRequest(WriteTextFileRequest),
542    /// Reads content from a text file in the client's file system.
543    ///
544    /// Only available if the client advertises the `fs.readTextFile` capability.
545    /// Allows the agent to access file contents within the client's environment.
546    ///
547    /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
548    ReadTextFileRequest(ReadTextFileRequest),
549    /// Requests permission from the user for a tool call operation.
550    ///
551    /// Called by the agent when it needs user authorization before executing
552    /// a potentially sensitive operation. The client should present the options
553    /// to the user and return their decision.
554    ///
555    /// If the client cancels the prompt turn via `session/cancel`, it MUST
556    /// respond to this request with `RequestPermissionOutcome::Cancelled`.
557    ///
558    /// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
559    RequestPermissionRequest(RequestPermissionRequest),
560    /// Executes a command in a new terminal
561    ///
562    /// Only available if the `terminal` Client capability is set to `true`.
563    ///
564    /// Returns a `TerminalId` that can be used with other terminal methods
565    /// to get the current output, wait for exit, and kill the command.
566    ///
567    /// The `TerminalId` can also be used to embed the terminal in a tool call
568    /// by using the `ToolCallContent::Terminal` variant.
569    ///
570    /// The Agent is responsible for releasing the terminal by using the `terminal/release`
571    /// method.
572    ///
573    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
574    CreateTerminalRequest(CreateTerminalRequest),
575    /// Gets the terminal output and exit status
576    ///
577    /// Returns the current content in the terminal without waiting for the command to exit.
578    /// If the command has already exited, the exit status is included.
579    ///
580    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
581    TerminalOutputRequest(TerminalOutputRequest),
582    /// Releases a terminal
583    ///
584    /// The command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`
585    /// to wait for the command to exit before releasing the terminal.
586    ///
587    /// After release, the `TerminalId` can no longer be used with other `terminal/*` methods,
588    /// but tool calls that already contain it, continue to display its output.
589    ///
590    /// The `terminal/kill` method can be used to terminate the command without releasing
591    /// the terminal, allowing the Agent to call `terminal/output` and other methods.
592    ///
593    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
594    ReleaseTerminalRequest(ReleaseTerminalRequest),
595    /// Waits for the terminal command to exit and return its exit status
596    ///
597    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
598    WaitForTerminalExitRequest(WaitForTerminalExitRequest),
599    /// Kills the terminal command without releasing the terminal
600    ///
601    /// While `terminal/release` will also kill the command, this method will keep
602    /// the `TerminalId` valid so it can be used with other methods.
603    ///
604    /// This method can be helpful when implementing command timeouts which terminate
605    /// the command as soon as elapsed, and then get the final output so it can be sent
606    /// to the model.
607    ///
608    /// Note: `terminal/release` when `TerminalId` is no longer needed.
609    ///
610    /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
611    KillTerminalCommandRequest(KillTerminalCommandRequest),
612    /// Handles extension method requests from the agent.
613    ///
614    /// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
615    /// Extension methods provide a way to add custom functionality while maintaining
616    /// protocol compatibility.
617    ///
618    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
619    ExtMethodRequest(ExtRequest),
620}
621
622/// All possible responses that a client can send to an agent.
623///
624/// This enum is used internally for routing RPC responses. You typically won't need
625/// to use this directly - the responses are handled automatically by the connection.
626///
627/// These are responses to the corresponding `AgentRequest` variants.
628#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
629#[serde(untagged)]
630#[schemars(extend("x-docs-ignore" = true))]
631pub enum ClientResponse {
632    WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
633    ReadTextFileResponse(ReadTextFileResponse),
634    RequestPermissionResponse(RequestPermissionResponse),
635    CreateTerminalResponse(CreateTerminalResponse),
636    TerminalOutputResponse(TerminalOutputResponse),
637    ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
638    WaitForTerminalExitResponse(WaitForTerminalExitResponse),
639    KillTerminalResponse(#[serde(default)] KillTerminalCommandResponse),
640    ExtMethodResponse(#[schemars(with = "serde_json::Value")] Arc<RawValue>),
641}
642
643/// All possible notifications that an agent can send to a client.
644///
645/// This enum is used internally for routing RPC notifications. You typically won't need
646/// to use this directly - use the notification methods on the [`Client`] trait instead.
647///
648/// Notifications do not expect a response.
649#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
650#[serde(untagged)]
651#[allow(clippy::large_enum_variant)]
652#[schemars(extend("x-docs-ignore" = true))]
653pub enum AgentNotification {
654    /// Handles session update notifications from the agent.
655    ///
656    /// This is a notification endpoint (no response expected) that receives
657    /// real-time updates about session progress, including message chunks,
658    /// tool calls, and execution plans.
659    ///
660    /// Note: Clients SHOULD continue accepting tool call updates even after
661    /// sending a `session/cancel` notification, as the agent may send final
662    /// updates before responding with the cancelled stop reason.
663    ///
664    /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
665    SessionNotification(SessionNotification),
666    /// Handles extension notifications from the agent.
667    ///
668    /// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
669    /// Extension notifications provide a way to send one-way messages for custom functionality
670    /// while maintaining protocol compatibility.
671    ///
672    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
673    ExtNotification(ExtNotification),
674}