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