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}