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