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