agent_client_protocol_schema/v1/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_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
12
13#[cfg(feature = "unstable_elicitation")]
14use crate::{
15 CompleteElicitationNotification, CreateElicitationRequest, CreateElicitationResponse,
16 ElicitationCapabilities,
17};
18use crate::{
19 ContentBlock, EnvVariable, ExtNotification, ExtRequest, ExtResponse, IntoMaybeUndefined,
20 IntoOption, MaybeUndefined, Meta, Plan, SessionConfigOption, SessionId, SessionModeId,
21 SkipListener, ToolCall, ToolCallUpdate,
22};
23
24#[cfg(feature = "unstable_mcp_over_acp")]
25use super::mcp::{
26 ConnectMcpRequest, ConnectMcpResponse, DisconnectMcpRequest, DisconnectMcpResponse,
27 MCP_CONNECT_METHOD_NAME, MCP_DISCONNECT_METHOD_NAME, MCP_MESSAGE_METHOD_NAME,
28 MessageMcpNotification, MessageMcpRequest, MessageMcpResponse,
29};
30
31#[cfg(feature = "unstable_nes")]
32use crate::{ClientNesCapabilities, PositionEncodingKind};
33
34// Session updates
35
36/// Notification containing a session update from the agent.
37///
38/// Used to stream real-time progress and results during prompt processing.
39///
40/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
41#[skip_serializing_none]
42#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
43#[schemars(extend("x-side" = "client", "x-method" = SESSION_UPDATE_NOTIFICATION))]
44#[serde(rename_all = "camelCase")]
45#[non_exhaustive]
46pub struct SessionNotification {
47 /// The ID of the session this update pertains to.
48 pub session_id: SessionId,
49 /// The actual update content.
50 pub update: SessionUpdate,
51 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
52 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
53 /// these keys.
54 ///
55 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
56 #[serde(rename = "_meta")]
57 pub meta: Option<Meta>,
58}
59
60impl SessionNotification {
61 #[must_use]
62 pub fn new(session_id: impl Into<SessionId>, update: SessionUpdate) -> Self {
63 Self {
64 session_id: session_id.into(),
65 update,
66 meta: None,
67 }
68 }
69
70 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
71 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
72 /// these keys.
73 ///
74 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
75 #[must_use]
76 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
77 self.meta = meta.into_option();
78 self
79 }
80}
81
82/// Different types of updates that can be sent during session processing.
83///
84/// These updates provide real-time feedback about the agent's progress.
85///
86/// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
87#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
88#[serde(tag = "sessionUpdate", rename_all = "snake_case")]
89#[schemars(extend("discriminator" = {"propertyName": "sessionUpdate"}))]
90#[non_exhaustive]
91pub enum SessionUpdate {
92 /// A chunk of the user's message being streamed.
93 UserMessageChunk(ContentChunk),
94 /// A chunk of the agent's response being streamed.
95 AgentMessageChunk(ContentChunk),
96 /// A chunk of the agent's internal reasoning being streamed.
97 AgentThoughtChunk(ContentChunk),
98 /// Notification that a new tool call has been initiated.
99 ToolCall(ToolCall),
100 /// Update on the status or results of a tool call.
101 ToolCallUpdate(ToolCallUpdate),
102 /// The agent's execution plan for complex tasks.
103 /// See protocol docs: [Agent Plan](https://agentclientprotocol.com/protocol/agent-plan)
104 Plan(Plan),
105 /// Available commands are ready or have changed
106 AvailableCommandsUpdate(AvailableCommandsUpdate),
107 /// The current mode of the session has changed
108 ///
109 /// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
110 CurrentModeUpdate(CurrentModeUpdate),
111 /// Session configuration options have been updated.
112 ConfigOptionUpdate(ConfigOptionUpdate),
113 /// Session metadata has been updated (title, timestamps, custom metadata)
114 SessionInfoUpdate(SessionInfoUpdate),
115 /// **UNSTABLE**
116 ///
117 /// This capability is not part of the spec yet, and may be removed or changed at any point.
118 ///
119 /// Context window and cost update for the session.
120 #[cfg(feature = "unstable_session_usage")]
121 UsageUpdate(UsageUpdate),
122}
123
124/// The current mode of the session has changed
125///
126/// See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes)
127#[skip_serializing_none]
128#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
129#[serde(rename_all = "camelCase")]
130#[non_exhaustive]
131pub struct CurrentModeUpdate {
132 /// The ID of the current mode
133 pub current_mode_id: SessionModeId,
134 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
135 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
136 /// these keys.
137 ///
138 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
139 #[serde(rename = "_meta")]
140 pub meta: Option<Meta>,
141}
142
143impl CurrentModeUpdate {
144 #[must_use]
145 pub fn new(current_mode_id: impl Into<SessionModeId>) -> Self {
146 Self {
147 current_mode_id: current_mode_id.into(),
148 meta: None,
149 }
150 }
151
152 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
153 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
154 /// these keys.
155 ///
156 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
157 #[must_use]
158 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
159 self.meta = meta.into_option();
160 self
161 }
162}
163
164/// Session configuration options have been updated.
165#[serde_as]
166#[skip_serializing_none]
167#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
168#[serde(rename_all = "camelCase")]
169#[non_exhaustive]
170pub struct ConfigOptionUpdate {
171 /// The full set of configuration options and their current values.
172 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
173 pub config_options: Vec<SessionConfigOption>,
174 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
175 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
176 /// these keys.
177 ///
178 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
179 #[serde(rename = "_meta")]
180 pub meta: Option<Meta>,
181}
182
183impl ConfigOptionUpdate {
184 #[must_use]
185 pub fn new(config_options: Vec<SessionConfigOption>) -> Self {
186 Self {
187 config_options,
188 meta: None,
189 }
190 }
191
192 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
193 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
194 /// these keys.
195 ///
196 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
197 #[must_use]
198 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
199 self.meta = meta.into_option();
200 self
201 }
202}
203
204/// Update to session metadata. All fields are optional to support partial updates.
205///
206/// Agents send this notification to update session information like title or custom metadata.
207/// This allows clients to display dynamic session names and track session state changes.
208#[skip_serializing_none]
209#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
210#[serde(rename_all = "camelCase")]
211#[non_exhaustive]
212pub struct SessionInfoUpdate {
213 /// Human-readable title for the session. Set to null to clear.
214 #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
215 pub title: MaybeUndefined<String>,
216 /// ISO 8601 timestamp of last activity. Set to null to clear.
217 #[serde(default, skip_serializing_if = "MaybeUndefined::is_undefined")]
218 pub updated_at: MaybeUndefined<String>,
219 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
220 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
221 /// these keys.
222 ///
223 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
224 #[serde(rename = "_meta")]
225 pub meta: Option<Meta>,
226}
227
228impl SessionInfoUpdate {
229 #[must_use]
230 pub fn new() -> Self {
231 Self::default()
232 }
233
234 /// Human-readable title for the session. Set to null to clear.
235 #[must_use]
236 pub fn title(mut self, title: impl IntoMaybeUndefined<String>) -> Self {
237 self.title = title.into_maybe_undefined();
238 self
239 }
240
241 /// ISO 8601 timestamp of last activity. Set to null to clear.
242 #[must_use]
243 pub fn updated_at(mut self, updated_at: impl IntoMaybeUndefined<String>) -> Self {
244 self.updated_at = updated_at.into_maybe_undefined();
245 self
246 }
247
248 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
249 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
250 /// these keys.
251 ///
252 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
253 #[must_use]
254 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
255 self.meta = meta.into_option();
256 self
257 }
258}
259
260/// **UNSTABLE**
261///
262/// This capability is not part of the spec yet, and may be removed or changed at any point.
263///
264/// Context window and cost update for a session.
265#[cfg(feature = "unstable_session_usage")]
266#[serde_as]
267#[skip_serializing_none]
268#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
269#[serde(rename_all = "camelCase")]
270#[non_exhaustive]
271pub struct UsageUpdate {
272 /// Tokens currently in context.
273 pub used: u64,
274 /// Total context window size in tokens.
275 pub size: u64,
276 /// Cumulative session cost (optional).
277 #[serde_as(deserialize_as = "DefaultOnError")]
278 #[serde(default)]
279 pub cost: Option<Cost>,
280 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
281 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
282 /// these keys.
283 ///
284 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
285 #[serde(rename = "_meta")]
286 pub meta: Option<Meta>,
287}
288
289#[cfg(feature = "unstable_session_usage")]
290impl UsageUpdate {
291 #[must_use]
292 pub fn new(used: u64, size: u64) -> Self {
293 Self {
294 used,
295 size,
296 cost: None,
297 meta: None,
298 }
299 }
300
301 /// Cumulative session cost (optional).
302 #[must_use]
303 pub fn cost(mut self, cost: impl IntoOption<Cost>) -> Self {
304 self.cost = cost.into_option();
305 self
306 }
307
308 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
309 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
310 /// these keys.
311 ///
312 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
313 #[must_use]
314 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
315 self.meta = meta.into_option();
316 self
317 }
318}
319
320/// **UNSTABLE**
321///
322/// This capability is not part of the spec yet, and may be removed or changed at any point.
323///
324/// Cost information for a session.
325#[cfg(feature = "unstable_session_usage")]
326#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
327#[serde(rename_all = "camelCase")]
328#[non_exhaustive]
329pub struct Cost {
330 /// Total cumulative cost for session.
331 pub amount: f64,
332 /// ISO 4217 currency code (e.g., "USD", "EUR").
333 pub currency: String,
334}
335
336#[cfg(feature = "unstable_session_usage")]
337impl Cost {
338 #[must_use]
339 pub fn new(amount: f64, currency: impl Into<String>) -> Self {
340 Self {
341 amount,
342 currency: currency.into(),
343 }
344 }
345}
346
347/// A streamed item of content
348#[skip_serializing_none]
349#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
350#[serde(rename_all = "camelCase")]
351#[non_exhaustive]
352pub struct ContentChunk {
353 /// A single item of content
354 pub content: ContentBlock,
355 /// **UNSTABLE**
356 ///
357 /// This capability is not part of the spec yet, and may be removed or changed at any point.
358 ///
359 /// A unique identifier for the message this chunk belongs to.
360 ///
361 /// All chunks belonging to the same message share the same `messageId`.
362 /// A change in `messageId` indicates a new message has started.
363 /// Both clients and agents MUST use UUID format for message IDs.
364 #[cfg(feature = "unstable_message_id")]
365 pub message_id: Option<String>,
366 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
367 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
368 /// these keys.
369 ///
370 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
371 #[serde(rename = "_meta")]
372 pub meta: Option<Meta>,
373}
374
375impl ContentChunk {
376 #[must_use]
377 pub fn new(content: ContentBlock) -> Self {
378 Self {
379 content,
380 #[cfg(feature = "unstable_message_id")]
381 message_id: None,
382 meta: None,
383 }
384 }
385
386 /// **UNSTABLE**
387 ///
388 /// This capability is not part of the spec yet, and may be removed or changed at any point.
389 ///
390 /// A unique identifier for the message this chunk belongs to.
391 ///
392 /// All chunks belonging to the same message share the same `messageId`.
393 /// A change in `messageId` indicates a new message has started.
394 /// Both clients and agents MUST use UUID format for message IDs.
395 #[cfg(feature = "unstable_message_id")]
396 #[must_use]
397 pub fn message_id(mut self, message_id: impl IntoOption<String>) -> Self {
398 self.message_id = message_id.into_option();
399 self
400 }
401
402 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
403 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
404 /// these keys.
405 ///
406 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
407 #[must_use]
408 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
409 self.meta = meta.into_option();
410 self
411 }
412}
413
414/// Available commands are ready or have changed
415#[serde_as]
416#[skip_serializing_none]
417#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
418#[serde(rename_all = "camelCase")]
419#[non_exhaustive]
420pub struct AvailableCommandsUpdate {
421 /// Commands the agent can execute
422 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
423 pub available_commands: Vec<AvailableCommand>,
424 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
425 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
426 /// these keys.
427 ///
428 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
429 #[serde(rename = "_meta")]
430 pub meta: Option<Meta>,
431}
432
433impl AvailableCommandsUpdate {
434 #[must_use]
435 pub fn new(available_commands: Vec<AvailableCommand>) -> Self {
436 Self {
437 available_commands,
438 meta: None,
439 }
440 }
441
442 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
443 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
444 /// these keys.
445 ///
446 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
447 #[must_use]
448 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
449 self.meta = meta.into_option();
450 self
451 }
452}
453
454/// Information about a command.
455#[serde_as]
456#[skip_serializing_none]
457#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
458#[serde(rename_all = "camelCase")]
459#[non_exhaustive]
460pub struct AvailableCommand {
461 /// Command name (e.g., `create_plan`, `research_codebase`).
462 pub name: String,
463 /// Human-readable description of what the command does.
464 pub description: String,
465 /// Input for the command if required
466 #[serde_as(deserialize_as = "DefaultOnError")]
467 #[serde(default)]
468 pub input: Option<AvailableCommandInput>,
469 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
470 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
471 /// these keys.
472 ///
473 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
474 #[serde(rename = "_meta")]
475 pub meta: Option<Meta>,
476}
477
478impl AvailableCommand {
479 #[must_use]
480 pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
481 Self {
482 name: name.into(),
483 description: description.into(),
484 input: None,
485 meta: None,
486 }
487 }
488
489 /// Input for the command if required
490 #[must_use]
491 pub fn input(mut self, input: impl IntoOption<AvailableCommandInput>) -> Self {
492 self.input = input.into_option();
493 self
494 }
495
496 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
497 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
498 /// these keys.
499 ///
500 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
501 #[must_use]
502 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
503 self.meta = meta.into_option();
504 self
505 }
506}
507
508/// The input specification for a command.
509#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
510#[serde(untagged, rename_all = "camelCase")]
511#[non_exhaustive]
512pub enum AvailableCommandInput {
513 /// All text that was typed after the command name is provided as input.
514 Unstructured(UnstructuredCommandInput),
515}
516
517/// All text that was typed after the command name is provided as input.
518#[skip_serializing_none]
519#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
520#[serde(rename_all = "camelCase")]
521#[non_exhaustive]
522pub struct UnstructuredCommandInput {
523 /// A hint to display when the input hasn't been provided yet
524 pub hint: String,
525 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
526 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
527 /// these keys.
528 ///
529 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
530 #[serde(rename = "_meta")]
531 pub meta: Option<Meta>,
532}
533
534impl UnstructuredCommandInput {
535 #[must_use]
536 pub fn new(hint: impl Into<String>) -> Self {
537 Self {
538 hint: hint.into(),
539 meta: None,
540 }
541 }
542
543 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
544 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
545 /// these keys.
546 ///
547 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
548 #[must_use]
549 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
550 self.meta = meta.into_option();
551 self
552 }
553}
554
555// Permission
556
557/// Request for user permission to execute a tool call.
558///
559/// Sent when the agent needs authorization before performing a sensitive operation.
560///
561/// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
562#[skip_serializing_none]
563#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
564#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
565#[serde(rename_all = "camelCase")]
566#[non_exhaustive]
567pub struct RequestPermissionRequest {
568 /// The session ID for this request.
569 pub session_id: SessionId,
570 /// Details about the tool call requiring permission.
571 pub tool_call: ToolCallUpdate,
572 /// Available permission options for the user to choose from.
573 pub options: Vec<PermissionOption>,
574 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
575 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
576 /// these keys.
577 ///
578 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
579 #[serde(rename = "_meta")]
580 pub meta: Option<Meta>,
581}
582
583impl RequestPermissionRequest {
584 #[must_use]
585 pub fn new(
586 session_id: impl Into<SessionId>,
587 tool_call: ToolCallUpdate,
588 options: Vec<PermissionOption>,
589 ) -> Self {
590 Self {
591 session_id: session_id.into(),
592 tool_call,
593 options,
594 meta: None,
595 }
596 }
597
598 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
599 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
600 /// these keys.
601 ///
602 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
603 #[must_use]
604 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
605 self.meta = meta.into_option();
606 self
607 }
608}
609
610/// An option presented to the user when requesting permission.
611#[skip_serializing_none]
612#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
613#[serde(rename_all = "camelCase")]
614#[non_exhaustive]
615pub struct PermissionOption {
616 /// Unique identifier for this permission option.
617 pub option_id: PermissionOptionId,
618 /// Human-readable label to display to the user.
619 pub name: String,
620 /// Hint about the nature of this permission option.
621 pub kind: PermissionOptionKind,
622 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
623 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
624 /// these keys.
625 ///
626 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
627 #[serde(rename = "_meta")]
628 pub meta: Option<Meta>,
629}
630
631impl PermissionOption {
632 #[must_use]
633 pub fn new(
634 option_id: impl Into<PermissionOptionId>,
635 name: impl Into<String>,
636 kind: PermissionOptionKind,
637 ) -> Self {
638 Self {
639 option_id: option_id.into(),
640 name: name.into(),
641 kind,
642 meta: None,
643 }
644 }
645
646 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
647 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
648 /// these keys.
649 ///
650 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
651 #[must_use]
652 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
653 self.meta = meta.into_option();
654 self
655 }
656}
657
658/// Unique identifier for a permission option.
659#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
660#[serde(transparent)]
661#[from(Arc<str>, String, &'static str)]
662#[non_exhaustive]
663pub struct PermissionOptionId(pub Arc<str>);
664
665impl PermissionOptionId {
666 #[must_use]
667 pub fn new(id: impl Into<Arc<str>>) -> Self {
668 Self(id.into())
669 }
670}
671
672/// The type of permission option being presented to the user.
673///
674/// Helps clients choose appropriate icons and UI treatment.
675#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
676#[serde(rename_all = "snake_case")]
677#[non_exhaustive]
678pub enum PermissionOptionKind {
679 /// Allow this operation only this time.
680 AllowOnce,
681 /// Allow this operation and remember the choice.
682 AllowAlways,
683 /// Reject this operation only this time.
684 RejectOnce,
685 /// Reject this operation and remember the choice.
686 RejectAlways,
687}
688
689/// Response to a permission request.
690#[skip_serializing_none]
691#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
692#[schemars(extend("x-side" = "client", "x-method" = SESSION_REQUEST_PERMISSION_METHOD_NAME))]
693#[serde(rename_all = "camelCase")]
694#[non_exhaustive]
695pub struct RequestPermissionResponse {
696 /// The user's decision on the permission request.
697 // This extra-level is unfortunately needed because the output must be an object
698 pub outcome: RequestPermissionOutcome,
699 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
700 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
701 /// these keys.
702 ///
703 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
704 #[serde(rename = "_meta")]
705 pub meta: Option<Meta>,
706}
707
708impl RequestPermissionResponse {
709 #[must_use]
710 pub fn new(outcome: RequestPermissionOutcome) -> Self {
711 Self {
712 outcome,
713 meta: None,
714 }
715 }
716
717 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
718 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
719 /// these keys.
720 ///
721 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
722 #[must_use]
723 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
724 self.meta = meta.into_option();
725 self
726 }
727}
728
729/// The outcome of a permission request.
730#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
731#[serde(tag = "outcome", rename_all = "snake_case")]
732#[schemars(extend("discriminator" = {"propertyName": "outcome"}))]
733#[non_exhaustive]
734pub enum RequestPermissionOutcome {
735 /// The prompt turn was cancelled before the user responded.
736 ///
737 /// When a client sends a `session/cancel` notification to cancel an ongoing
738 /// prompt turn, it MUST respond to all pending `session/request_permission`
739 /// requests with this `Cancelled` outcome.
740 ///
741 /// See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)
742 Cancelled,
743 /// The user selected one of the provided options.
744 #[serde(rename_all = "camelCase")]
745 Selected(SelectedPermissionOutcome),
746}
747
748/// The user selected one of the provided options.
749#[skip_serializing_none]
750#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
751#[serde(rename_all = "camelCase")]
752#[non_exhaustive]
753pub struct SelectedPermissionOutcome {
754 /// The ID of the option the user selected.
755 pub option_id: PermissionOptionId,
756 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
757 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
758 /// these keys.
759 ///
760 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
761 #[serde(rename = "_meta")]
762 pub meta: Option<Meta>,
763}
764
765impl SelectedPermissionOutcome {
766 #[must_use]
767 pub fn new(option_id: impl Into<PermissionOptionId>) -> Self {
768 Self {
769 option_id: option_id.into(),
770 meta: None,
771 }
772 }
773
774 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
775 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
776 /// these keys.
777 ///
778 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
779 #[must_use]
780 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
781 self.meta = meta.into_option();
782 self
783 }
784}
785
786// Write text file
787
788/// Request to write content to a text file.
789///
790/// Only available if the client supports the `fs.writeTextFile` capability.
791#[skip_serializing_none]
792#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
793#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
794#[serde(rename_all = "camelCase")]
795#[non_exhaustive]
796pub struct WriteTextFileRequest {
797 /// The session ID for this request.
798 pub session_id: SessionId,
799 /// Absolute path to the file to write.
800 pub path: PathBuf,
801 /// The text content to write to the file.
802 pub content: String,
803 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
804 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
805 /// these keys.
806 ///
807 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
808 #[serde(rename = "_meta")]
809 pub meta: Option<Meta>,
810}
811
812impl WriteTextFileRequest {
813 #[must_use]
814 pub fn new(
815 session_id: impl Into<SessionId>,
816 path: impl Into<PathBuf>,
817 content: impl Into<String>,
818 ) -> Self {
819 Self {
820 session_id: session_id.into(),
821 path: path.into(),
822 content: content.into(),
823 meta: None,
824 }
825 }
826
827 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
828 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
829 /// these keys.
830 ///
831 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
832 #[must_use]
833 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
834 self.meta = meta.into_option();
835 self
836 }
837}
838
839/// Response to `fs/write_text_file`
840#[skip_serializing_none]
841#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
842#[serde(rename_all = "camelCase")]
843#[schemars(extend("x-side" = "client", "x-method" = FS_WRITE_TEXT_FILE_METHOD_NAME))]
844#[non_exhaustive]
845pub struct WriteTextFileResponse {
846 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
847 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
848 /// these keys.
849 ///
850 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
851 #[serde(rename = "_meta")]
852 pub meta: Option<Meta>,
853}
854
855impl WriteTextFileResponse {
856 #[must_use]
857 pub fn new() -> Self {
858 Self::default()
859 }
860
861 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
862 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
863 /// these keys.
864 ///
865 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
866 #[must_use]
867 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
868 self.meta = meta.into_option();
869 self
870 }
871}
872
873// Read text file
874
875/// Request to read content from a text file.
876///
877/// Only available if the client supports the `fs.readTextFile` capability.
878#[skip_serializing_none]
879#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
880#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
881#[serde(rename_all = "camelCase")]
882#[non_exhaustive]
883pub struct ReadTextFileRequest {
884 /// The session ID for this request.
885 pub session_id: SessionId,
886 /// Absolute path to the file to read.
887 pub path: PathBuf,
888 /// Line number to start reading from (1-based).
889 pub line: Option<u32>,
890 /// Maximum number of lines to read.
891 pub limit: Option<u32>,
892 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
893 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
894 /// these keys.
895 ///
896 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
897 #[serde(rename = "_meta")]
898 pub meta: Option<Meta>,
899}
900
901impl ReadTextFileRequest {
902 #[must_use]
903 pub fn new(session_id: impl Into<SessionId>, path: impl Into<PathBuf>) -> Self {
904 Self {
905 session_id: session_id.into(),
906 path: path.into(),
907 line: None,
908 limit: None,
909 meta: None,
910 }
911 }
912
913 /// Line number to start reading from (1-based).
914 #[must_use]
915 pub fn line(mut self, line: impl IntoOption<u32>) -> Self {
916 self.line = line.into_option();
917 self
918 }
919
920 /// Maximum number of lines to read.
921 #[must_use]
922 pub fn limit(mut self, limit: impl IntoOption<u32>) -> Self {
923 self.limit = limit.into_option();
924 self
925 }
926
927 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
928 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
929 /// these keys.
930 ///
931 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
932 #[must_use]
933 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
934 self.meta = meta.into_option();
935 self
936 }
937}
938
939/// Response containing the contents of a text file.
940#[skip_serializing_none]
941#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
942#[schemars(extend("x-side" = "client", "x-method" = FS_READ_TEXT_FILE_METHOD_NAME))]
943#[serde(rename_all = "camelCase")]
944#[non_exhaustive]
945pub struct ReadTextFileResponse {
946 pub content: String,
947 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
948 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
949 /// these keys.
950 ///
951 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
952 #[serde(rename = "_meta")]
953 pub meta: Option<Meta>,
954}
955
956impl ReadTextFileResponse {
957 #[must_use]
958 pub fn new(content: impl Into<String>) -> Self {
959 Self {
960 content: content.into(),
961 meta: None,
962 }
963 }
964
965 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
966 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
967 /// these keys.
968 ///
969 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
970 #[must_use]
971 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
972 self.meta = meta.into_option();
973 self
974 }
975}
976
977// Terminals
978
979#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
980#[serde(transparent)]
981#[from(Arc<str>, String, &'static str)]
982#[non_exhaustive]
983pub struct TerminalId(pub Arc<str>);
984
985impl TerminalId {
986 #[must_use]
987 pub fn new(id: impl Into<Arc<str>>) -> Self {
988 Self(id.into())
989 }
990}
991
992/// Request to create a new terminal and execute a command.
993#[skip_serializing_none]
994#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
995#[serde(rename_all = "camelCase")]
996#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
997#[non_exhaustive]
998pub struct CreateTerminalRequest {
999 /// The session ID for this request.
1000 pub session_id: SessionId,
1001 /// The command to execute.
1002 pub command: String,
1003 /// Array of command arguments.
1004 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1005 pub args: Vec<String>,
1006 /// Environment variables for the command.
1007 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1008 pub env: Vec<EnvVariable>,
1009 /// Working directory for the command (absolute path).
1010 pub cwd: Option<PathBuf>,
1011 /// Maximum number of output bytes to retain.
1012 ///
1013 /// When the limit is exceeded, the Client truncates from the beginning of the output
1014 /// to stay within the limit.
1015 ///
1016 /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1017 /// string output, even if this means the retained output is slightly less than the
1018 /// specified limit.
1019 pub output_byte_limit: Option<u64>,
1020 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1021 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1022 /// these keys.
1023 ///
1024 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1025 #[serde(rename = "_meta")]
1026 pub meta: Option<Meta>,
1027}
1028
1029impl CreateTerminalRequest {
1030 #[must_use]
1031 pub fn new(session_id: impl Into<SessionId>, command: impl Into<String>) -> Self {
1032 Self {
1033 session_id: session_id.into(),
1034 command: command.into(),
1035 args: Vec::new(),
1036 env: Vec::new(),
1037 cwd: None,
1038 output_byte_limit: None,
1039 meta: None,
1040 }
1041 }
1042
1043 /// Array of command arguments.
1044 #[must_use]
1045 pub fn args(mut self, args: Vec<String>) -> Self {
1046 self.args = args;
1047 self
1048 }
1049
1050 /// Environment variables for the command.
1051 #[must_use]
1052 pub fn env(mut self, env: Vec<EnvVariable>) -> Self {
1053 self.env = env;
1054 self
1055 }
1056
1057 /// Working directory for the command (absolute path).
1058 #[must_use]
1059 pub fn cwd(mut self, cwd: impl IntoOption<PathBuf>) -> Self {
1060 self.cwd = cwd.into_option();
1061 self
1062 }
1063
1064 /// Maximum number of output bytes to retain.
1065 ///
1066 /// When the limit is exceeded, the Client truncates from the beginning of the output
1067 /// to stay within the limit.
1068 ///
1069 /// The Client MUST ensure truncation happens at a character boundary to maintain valid
1070 /// string output, even if this means the retained output is slightly less than the
1071 /// specified limit.
1072 #[must_use]
1073 pub fn output_byte_limit(mut self, output_byte_limit: impl IntoOption<u64>) -> Self {
1074 self.output_byte_limit = output_byte_limit.into_option();
1075 self
1076 }
1077
1078 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1079 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1080 /// these keys.
1081 ///
1082 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1083 #[must_use]
1084 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1085 self.meta = meta.into_option();
1086 self
1087 }
1088}
1089
1090/// Response containing the ID of the created terminal.
1091#[skip_serializing_none]
1092#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1093#[serde(rename_all = "camelCase")]
1094#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_CREATE_METHOD_NAME))]
1095#[non_exhaustive]
1096pub struct CreateTerminalResponse {
1097 /// The unique identifier for the created terminal.
1098 pub terminal_id: TerminalId,
1099 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1100 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1101 /// these keys.
1102 ///
1103 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1104 #[serde(rename = "_meta")]
1105 pub meta: Option<Meta>,
1106}
1107
1108impl CreateTerminalResponse {
1109 #[must_use]
1110 pub fn new(terminal_id: impl Into<TerminalId>) -> Self {
1111 Self {
1112 terminal_id: terminal_id.into(),
1113 meta: None,
1114 }
1115 }
1116
1117 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1118 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1119 /// these keys.
1120 ///
1121 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1122 #[must_use]
1123 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1124 self.meta = meta.into_option();
1125 self
1126 }
1127}
1128
1129/// Request to get the current output and status of a terminal.
1130#[skip_serializing_none]
1131#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1132#[serde(rename_all = "camelCase")]
1133#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1134#[non_exhaustive]
1135pub struct TerminalOutputRequest {
1136 /// The session ID for this request.
1137 pub session_id: SessionId,
1138 /// The ID of the terminal to get output from.
1139 pub terminal_id: TerminalId,
1140 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1141 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1142 /// these keys.
1143 ///
1144 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1145 #[serde(rename = "_meta")]
1146 pub meta: Option<Meta>,
1147}
1148
1149impl TerminalOutputRequest {
1150 #[must_use]
1151 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1152 Self {
1153 session_id: session_id.into(),
1154 terminal_id: terminal_id.into(),
1155 meta: None,
1156 }
1157 }
1158
1159 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1160 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1161 /// these keys.
1162 ///
1163 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1164 #[must_use]
1165 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1166 self.meta = meta.into_option();
1167 self
1168 }
1169}
1170
1171/// Response containing the terminal output and exit status.
1172#[skip_serializing_none]
1173#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1174#[serde(rename_all = "camelCase")]
1175#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_OUTPUT_METHOD_NAME))]
1176#[non_exhaustive]
1177pub struct TerminalOutputResponse {
1178 /// The terminal output captured so far.
1179 pub output: String,
1180 /// Whether the output was truncated due to byte limits.
1181 pub truncated: bool,
1182 /// Exit status if the command has completed.
1183 pub exit_status: Option<TerminalExitStatus>,
1184 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1185 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1186 /// these keys.
1187 ///
1188 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1189 #[serde(rename = "_meta")]
1190 pub meta: Option<Meta>,
1191}
1192
1193impl TerminalOutputResponse {
1194 #[must_use]
1195 pub fn new(output: impl Into<String>, truncated: bool) -> Self {
1196 Self {
1197 output: output.into(),
1198 truncated,
1199 exit_status: None,
1200 meta: None,
1201 }
1202 }
1203
1204 /// Exit status if the command has completed.
1205 #[must_use]
1206 pub fn exit_status(mut self, exit_status: impl IntoOption<TerminalExitStatus>) -> Self {
1207 self.exit_status = exit_status.into_option();
1208 self
1209 }
1210
1211 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1212 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1213 /// these keys.
1214 ///
1215 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1216 #[must_use]
1217 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1218 self.meta = meta.into_option();
1219 self
1220 }
1221}
1222
1223/// Request to release a terminal and free its resources.
1224#[skip_serializing_none]
1225#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1226#[serde(rename_all = "camelCase")]
1227#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1228#[non_exhaustive]
1229pub struct ReleaseTerminalRequest {
1230 /// The session ID for this request.
1231 pub session_id: SessionId,
1232 /// The ID of the terminal to release.
1233 pub terminal_id: TerminalId,
1234 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1235 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1236 /// these keys.
1237 ///
1238 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1239 #[serde(rename = "_meta")]
1240 pub meta: Option<Meta>,
1241}
1242
1243impl ReleaseTerminalRequest {
1244 #[must_use]
1245 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1246 Self {
1247 session_id: session_id.into(),
1248 terminal_id: terminal_id.into(),
1249 meta: None,
1250 }
1251 }
1252
1253 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1254 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1255 /// these keys.
1256 ///
1257 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1258 #[must_use]
1259 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1260 self.meta = meta.into_option();
1261 self
1262 }
1263}
1264
1265/// Response to terminal/release method
1266#[skip_serializing_none]
1267#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1268#[serde(rename_all = "camelCase")]
1269#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_RELEASE_METHOD_NAME))]
1270#[non_exhaustive]
1271pub struct ReleaseTerminalResponse {
1272 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1273 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1274 /// these keys.
1275 ///
1276 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1277 #[serde(rename = "_meta")]
1278 pub meta: Option<Meta>,
1279}
1280
1281impl ReleaseTerminalResponse {
1282 #[must_use]
1283 pub fn new() -> Self {
1284 Self::default()
1285 }
1286
1287 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1288 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1289 /// these keys.
1290 ///
1291 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1292 #[must_use]
1293 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1294 self.meta = meta.into_option();
1295 self
1296 }
1297}
1298
1299/// Request to kill a terminal without releasing it.
1300#[skip_serializing_none]
1301#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1302#[serde(rename_all = "camelCase")]
1303#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1304#[non_exhaustive]
1305pub struct KillTerminalRequest {
1306 /// The session ID for this request.
1307 pub session_id: SessionId,
1308 /// The ID of the terminal to kill.
1309 pub terminal_id: TerminalId,
1310 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1311 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1312 /// these keys.
1313 ///
1314 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1315 #[serde(rename = "_meta")]
1316 pub meta: Option<Meta>,
1317}
1318
1319impl KillTerminalRequest {
1320 #[must_use]
1321 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1322 Self {
1323 session_id: session_id.into(),
1324 terminal_id: terminal_id.into(),
1325 meta: None,
1326 }
1327 }
1328
1329 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1330 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1331 /// these keys.
1332 ///
1333 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1334 #[must_use]
1335 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1336 self.meta = meta.into_option();
1337 self
1338 }
1339}
1340
1341/// Response to `terminal/kill` method
1342#[skip_serializing_none]
1343#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1344#[serde(rename_all = "camelCase")]
1345#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_KILL_METHOD_NAME))]
1346#[non_exhaustive]
1347pub struct KillTerminalResponse {
1348 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1349 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1350 /// these keys.
1351 ///
1352 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1353 #[serde(rename = "_meta")]
1354 pub meta: Option<Meta>,
1355}
1356
1357impl KillTerminalResponse {
1358 #[must_use]
1359 pub fn new() -> Self {
1360 Self::default()
1361 }
1362
1363 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1364 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1365 /// these keys.
1366 ///
1367 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1368 #[must_use]
1369 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1370 self.meta = meta.into_option();
1371 self
1372 }
1373}
1374
1375/// Request to wait for a terminal command to exit.
1376#[skip_serializing_none]
1377#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1378#[serde(rename_all = "camelCase")]
1379#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1380#[non_exhaustive]
1381pub struct WaitForTerminalExitRequest {
1382 /// The session ID for this request.
1383 pub session_id: SessionId,
1384 /// The ID of the terminal to wait for.
1385 pub terminal_id: TerminalId,
1386 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1387 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1388 /// these keys.
1389 ///
1390 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1391 #[serde(rename = "_meta")]
1392 pub meta: Option<Meta>,
1393}
1394
1395impl WaitForTerminalExitRequest {
1396 #[must_use]
1397 pub fn new(session_id: impl Into<SessionId>, terminal_id: impl Into<TerminalId>) -> Self {
1398 Self {
1399 session_id: session_id.into(),
1400 terminal_id: terminal_id.into(),
1401 meta: None,
1402 }
1403 }
1404
1405 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1406 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1407 /// these keys.
1408 ///
1409 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1410 #[must_use]
1411 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1412 self.meta = meta.into_option();
1413 self
1414 }
1415}
1416
1417/// Response containing the exit status of a terminal command.
1418#[skip_serializing_none]
1419#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1420#[serde(rename_all = "camelCase")]
1421#[schemars(extend("x-side" = "client", "x-method" = TERMINAL_WAIT_FOR_EXIT_METHOD_NAME))]
1422#[non_exhaustive]
1423pub struct WaitForTerminalExitResponse {
1424 /// The exit status of the terminal command.
1425 #[serde(flatten)]
1426 pub exit_status: TerminalExitStatus,
1427 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1428 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1429 /// these keys.
1430 ///
1431 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1432 #[serde(rename = "_meta")]
1433 pub meta: Option<Meta>,
1434}
1435
1436impl WaitForTerminalExitResponse {
1437 #[must_use]
1438 pub fn new(exit_status: TerminalExitStatus) -> Self {
1439 Self {
1440 exit_status,
1441 meta: None,
1442 }
1443 }
1444
1445 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1446 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1447 /// these keys.
1448 ///
1449 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1450 #[must_use]
1451 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1452 self.meta = meta.into_option();
1453 self
1454 }
1455}
1456
1457/// Exit status of a terminal command.
1458#[skip_serializing_none]
1459#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1460#[serde(rename_all = "camelCase")]
1461#[non_exhaustive]
1462pub struct TerminalExitStatus {
1463 /// The process exit code (may be null if terminated by signal).
1464 pub exit_code: Option<u32>,
1465 /// The signal that terminated the process (may be null if exited normally).
1466 pub signal: Option<String>,
1467 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1468 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1469 /// these keys.
1470 ///
1471 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1472 #[serde(rename = "_meta")]
1473 pub meta: Option<Meta>,
1474}
1475
1476impl TerminalExitStatus {
1477 #[must_use]
1478 pub fn new() -> Self {
1479 Self::default()
1480 }
1481
1482 /// The process exit code (may be null if terminated by signal).
1483 #[must_use]
1484 pub fn exit_code(mut self, exit_code: impl IntoOption<u32>) -> Self {
1485 self.exit_code = exit_code.into_option();
1486 self
1487 }
1488
1489 /// The signal that terminated the process (may be null if exited normally).
1490 #[must_use]
1491 pub fn signal(mut self, signal: impl IntoOption<String>) -> Self {
1492 self.signal = signal.into_option();
1493 self
1494 }
1495
1496 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1497 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1498 /// these keys.
1499 ///
1500 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1501 #[must_use]
1502 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1503 self.meta = meta.into_option();
1504 self
1505 }
1506}
1507
1508// Capabilities
1509
1510/// Capabilities supported by the client.
1511///
1512/// Advertised during initialization to inform the agent about
1513/// available features and methods.
1514///
1515/// See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities)
1516#[serde_as]
1517#[skip_serializing_none]
1518#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1519#[serde(rename_all = "camelCase")]
1520#[non_exhaustive]
1521pub struct ClientCapabilities {
1522 /// File system capabilities supported by the client.
1523 /// Determines which file operations the agent can request.
1524 #[serde(default)]
1525 pub fs: FileSystemCapabilities,
1526 /// Whether the Client support all `terminal/*` methods.
1527 #[serde(default)]
1528 pub terminal: bool,
1529 /// **UNSTABLE**
1530 ///
1531 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1532 ///
1533 /// Authentication capabilities supported by the client.
1534 /// Determines which authentication method types the agent may include
1535 /// in its `InitializeResponse`.
1536 #[cfg(feature = "unstable_auth_methods")]
1537 #[serde(default)]
1538 pub auth: AuthCapabilities,
1539 /// **UNSTABLE**
1540 ///
1541 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1542 ///
1543 /// Elicitation capabilities supported by the client.
1544 /// Determines which elicitation modes the agent may use.
1545 #[cfg(feature = "unstable_elicitation")]
1546 #[serde_as(deserialize_as = "DefaultOnError")]
1547 #[serde(default)]
1548 pub elicitation: Option<ElicitationCapabilities>,
1549 /// **UNSTABLE**
1550 ///
1551 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1552 ///
1553 /// NES (Next Edit Suggestions) capabilities supported by the client.
1554 #[cfg(feature = "unstable_nes")]
1555 #[serde_as(deserialize_as = "DefaultOnError")]
1556 #[serde(default)]
1557 pub nes: Option<ClientNesCapabilities>,
1558 /// **UNSTABLE**
1559 ///
1560 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1561 ///
1562 /// The position encodings supported by the client, in order of preference.
1563 #[cfg(feature = "unstable_nes")]
1564 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1565 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1566 pub position_encodings: Vec<PositionEncodingKind>,
1567
1568 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1569 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1570 /// these keys.
1571 ///
1572 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1573 #[serde(rename = "_meta")]
1574 pub meta: Option<Meta>,
1575}
1576
1577impl ClientCapabilities {
1578 #[must_use]
1579 pub fn new() -> Self {
1580 Self::default()
1581 }
1582
1583 /// File system capabilities supported by the client.
1584 /// Determines which file operations the agent can request.
1585 #[must_use]
1586 pub fn fs(mut self, fs: FileSystemCapabilities) -> Self {
1587 self.fs = fs;
1588 self
1589 }
1590
1591 /// Whether the Client support all `terminal/*` methods.
1592 #[must_use]
1593 pub fn terminal(mut self, terminal: bool) -> Self {
1594 self.terminal = terminal;
1595 self
1596 }
1597
1598 /// **UNSTABLE**
1599 ///
1600 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1601 ///
1602 /// Authentication capabilities supported by the client.
1603 /// Determines which authentication method types the agent may include
1604 /// in its `InitializeResponse`.
1605 #[cfg(feature = "unstable_auth_methods")]
1606 #[must_use]
1607 pub fn auth(mut self, auth: AuthCapabilities) -> Self {
1608 self.auth = auth;
1609 self
1610 }
1611
1612 /// **UNSTABLE**
1613 ///
1614 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1615 ///
1616 /// Elicitation capabilities supported by the client.
1617 /// Determines which elicitation modes the agent may use.
1618 #[cfg(feature = "unstable_elicitation")]
1619 #[must_use]
1620 pub fn elicitation(mut self, elicitation: impl IntoOption<ElicitationCapabilities>) -> Self {
1621 self.elicitation = elicitation.into_option();
1622 self
1623 }
1624
1625 /// **UNSTABLE**
1626 ///
1627 /// NES (Next Edit Suggestions) capabilities supported by the client.
1628 #[cfg(feature = "unstable_nes")]
1629 #[must_use]
1630 pub fn nes(mut self, nes: impl IntoOption<ClientNesCapabilities>) -> Self {
1631 self.nes = nes.into_option();
1632 self
1633 }
1634
1635 /// **UNSTABLE**
1636 ///
1637 /// The position encodings supported by the client, in order of preference.
1638 #[cfg(feature = "unstable_nes")]
1639 #[must_use]
1640 pub fn position_encodings(mut self, position_encodings: Vec<PositionEncodingKind>) -> Self {
1641 self.position_encodings = position_encodings;
1642 self
1643 }
1644
1645 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1646 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1647 /// these keys.
1648 ///
1649 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1650 #[must_use]
1651 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1652 self.meta = meta.into_option();
1653 self
1654 }
1655}
1656
1657/// **UNSTABLE**
1658///
1659/// This capability is not part of the spec yet, and may be removed or changed at any point.
1660///
1661/// Authentication capabilities supported by the client.
1662///
1663/// Advertised during initialization to inform the agent which authentication
1664/// method types the client can handle. This governs opt-in types that require
1665/// additional client-side support.
1666#[cfg(feature = "unstable_auth_methods")]
1667#[skip_serializing_none]
1668#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1669#[serde(rename_all = "camelCase")]
1670#[non_exhaustive]
1671pub struct AuthCapabilities {
1672 /// Whether the client supports `terminal` authentication methods.
1673 ///
1674 /// When `true`, the agent may include `terminal` entries in its authentication methods.
1675 #[serde(default)]
1676 pub terminal: bool,
1677 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1678 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1679 /// these keys.
1680 ///
1681 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1682 #[serde(rename = "_meta")]
1683 pub meta: Option<Meta>,
1684}
1685
1686#[cfg(feature = "unstable_auth_methods")]
1687impl AuthCapabilities {
1688 #[must_use]
1689 pub fn new() -> Self {
1690 Self::default()
1691 }
1692
1693 /// Whether the client supports `terminal` authentication methods.
1694 ///
1695 /// When `true`, the agent may include `AuthMethod::Terminal`
1696 /// entries in its authentication methods.
1697 #[must_use]
1698 pub fn terminal(mut self, terminal: bool) -> Self {
1699 self.terminal = terminal;
1700 self
1701 }
1702
1703 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1704 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1705 /// these keys.
1706 ///
1707 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1708 #[must_use]
1709 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1710 self.meta = meta.into_option();
1711 self
1712 }
1713}
1714
1715/// File system capabilities that a client may support.
1716///
1717/// See protocol docs: [FileSystem](https://agentclientprotocol.com/protocol/initialization#filesystem)
1718#[skip_serializing_none]
1719#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1720#[serde(rename_all = "camelCase")]
1721#[non_exhaustive]
1722pub struct FileSystemCapabilities {
1723 /// Whether the Client supports `fs/read_text_file` requests.
1724 #[serde(default)]
1725 pub read_text_file: bool,
1726 /// Whether the Client supports `fs/write_text_file` requests.
1727 #[serde(default)]
1728 pub write_text_file: bool,
1729 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1730 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1731 /// these keys.
1732 ///
1733 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1734 #[serde(rename = "_meta")]
1735 pub meta: Option<Meta>,
1736}
1737
1738impl FileSystemCapabilities {
1739 #[must_use]
1740 pub fn new() -> Self {
1741 Self::default()
1742 }
1743
1744 /// Whether the Client supports `fs/read_text_file` requests.
1745 #[must_use]
1746 pub fn read_text_file(mut self, read_text_file: bool) -> Self {
1747 self.read_text_file = read_text_file;
1748 self
1749 }
1750
1751 /// Whether the Client supports `fs/write_text_file` requests.
1752 #[must_use]
1753 pub fn write_text_file(mut self, write_text_file: bool) -> Self {
1754 self.write_text_file = write_text_file;
1755 self
1756 }
1757
1758 /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1759 /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1760 /// these keys.
1761 ///
1762 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1763 #[must_use]
1764 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1765 self.meta = meta.into_option();
1766 self
1767 }
1768}
1769
1770// Method schema
1771
1772/// Names of all methods that clients handle.
1773///
1774/// Provides a centralized definition of method names used in the protocol.
1775#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1776#[non_exhaustive]
1777pub struct ClientMethodNames {
1778 /// Method for requesting permission from the user.
1779 pub session_request_permission: &'static str,
1780 /// Notification for session updates.
1781 pub session_update: &'static str,
1782 /// Method for writing text files.
1783 pub fs_write_text_file: &'static str,
1784 /// Method for reading text files.
1785 pub fs_read_text_file: &'static str,
1786 /// Method for creating new terminals.
1787 pub terminal_create: &'static str,
1788 /// Method for getting terminals output.
1789 pub terminal_output: &'static str,
1790 /// Method for releasing a terminal.
1791 pub terminal_release: &'static str,
1792 /// Method for waiting for a terminal to finish.
1793 pub terminal_wait_for_exit: &'static str,
1794 /// Method for killing a terminal.
1795 pub terminal_kill: &'static str,
1796 /// Method for opening an MCP-over-ACP connection.
1797 #[cfg(feature = "unstable_mcp_over_acp")]
1798 pub mcp_connect: &'static str,
1799 /// Method for exchanging MCP-over-ACP messages.
1800 #[cfg(feature = "unstable_mcp_over_acp")]
1801 pub mcp_message: &'static str,
1802 /// Method for closing an MCP-over-ACP connection.
1803 #[cfg(feature = "unstable_mcp_over_acp")]
1804 pub mcp_disconnect: &'static str,
1805 /// Method for elicitation.
1806 #[cfg(feature = "unstable_elicitation")]
1807 pub elicitation_create: &'static str,
1808 /// Notification for elicitation completion.
1809 #[cfg(feature = "unstable_elicitation")]
1810 pub elicitation_complete: &'static str,
1811}
1812
1813/// Constant containing all client method names.
1814pub const CLIENT_METHOD_NAMES: ClientMethodNames = ClientMethodNames {
1815 session_update: SESSION_UPDATE_NOTIFICATION,
1816 session_request_permission: SESSION_REQUEST_PERMISSION_METHOD_NAME,
1817 fs_write_text_file: FS_WRITE_TEXT_FILE_METHOD_NAME,
1818 fs_read_text_file: FS_READ_TEXT_FILE_METHOD_NAME,
1819 terminal_create: TERMINAL_CREATE_METHOD_NAME,
1820 terminal_output: TERMINAL_OUTPUT_METHOD_NAME,
1821 terminal_release: TERMINAL_RELEASE_METHOD_NAME,
1822 terminal_wait_for_exit: TERMINAL_WAIT_FOR_EXIT_METHOD_NAME,
1823 terminal_kill: TERMINAL_KILL_METHOD_NAME,
1824 #[cfg(feature = "unstable_mcp_over_acp")]
1825 mcp_connect: MCP_CONNECT_METHOD_NAME,
1826 #[cfg(feature = "unstable_mcp_over_acp")]
1827 mcp_message: MCP_MESSAGE_METHOD_NAME,
1828 #[cfg(feature = "unstable_mcp_over_acp")]
1829 mcp_disconnect: MCP_DISCONNECT_METHOD_NAME,
1830 #[cfg(feature = "unstable_elicitation")]
1831 elicitation_create: ELICITATION_CREATE_METHOD_NAME,
1832 #[cfg(feature = "unstable_elicitation")]
1833 elicitation_complete: ELICITATION_COMPLETE_NOTIFICATION,
1834};
1835
1836/// Notification name for session updates.
1837pub(crate) const SESSION_UPDATE_NOTIFICATION: &str = "session/update";
1838/// Method name for requesting user permission.
1839pub(crate) const SESSION_REQUEST_PERMISSION_METHOD_NAME: &str = "session/request_permission";
1840/// Method name for writing text files.
1841pub(crate) const FS_WRITE_TEXT_FILE_METHOD_NAME: &str = "fs/write_text_file";
1842/// Method name for reading text files.
1843pub(crate) const FS_READ_TEXT_FILE_METHOD_NAME: &str = "fs/read_text_file";
1844/// Method name for creating a new terminal.
1845pub(crate) const TERMINAL_CREATE_METHOD_NAME: &str = "terminal/create";
1846/// Method for getting terminals output.
1847pub(crate) const TERMINAL_OUTPUT_METHOD_NAME: &str = "terminal/output";
1848/// Method for releasing a terminal.
1849pub(crate) const TERMINAL_RELEASE_METHOD_NAME: &str = "terminal/release";
1850/// Method for waiting for a terminal to finish.
1851pub(crate) const TERMINAL_WAIT_FOR_EXIT_METHOD_NAME: &str = "terminal/wait_for_exit";
1852/// Method for killing a terminal.
1853pub(crate) const TERMINAL_KILL_METHOD_NAME: &str = "terminal/kill";
1854/// Method name for elicitation.
1855#[cfg(feature = "unstable_elicitation")]
1856pub(crate) const ELICITATION_CREATE_METHOD_NAME: &str = "elicitation/create";
1857/// Notification name for elicitation completion.
1858#[cfg(feature = "unstable_elicitation")]
1859pub(crate) const ELICITATION_COMPLETE_NOTIFICATION: &str = "elicitation/complete";
1860
1861/// All possible requests that an agent can send to a client.
1862///
1863/// This enum is used internally for routing RPC requests. You typically won't need
1864/// to use this directly.
1865///
1866/// This enum encompasses all method calls from agent to client.
1867#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
1868#[serde(untagged)]
1869#[schemars(inline)]
1870#[non_exhaustive]
1871pub enum AgentRequest {
1872 /// Writes content to a text file in the client's file system.
1873 ///
1874 /// Only available if the client advertises the `fs.writeTextFile` capability.
1875 /// Allows the agent to create or modify files within the client's environment.
1876 ///
1877 /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
1878 WriteTextFileRequest(WriteTextFileRequest),
1879 /// Reads content from a text file in the client's file system.
1880 ///
1881 /// Only available if the client advertises the `fs.readTextFile` capability.
1882 /// Allows the agent to access file contents within the client's environment.
1883 ///
1884 /// See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client)
1885 ReadTextFileRequest(ReadTextFileRequest),
1886 /// Requests permission from the user for a tool call operation.
1887 ///
1888 /// Called by the agent when it needs user authorization before executing
1889 /// a potentially sensitive operation. The client should present the options
1890 /// to the user and return their decision.
1891 ///
1892 /// If the client cancels the prompt turn via `session/cancel`, it MUST
1893 /// respond to this request with `RequestPermissionOutcome::Cancelled`.
1894 ///
1895 /// See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission)
1896 RequestPermissionRequest(RequestPermissionRequest),
1897 /// Executes a command in a new terminal
1898 ///
1899 /// Only available if the `terminal` Client capability is set to `true`.
1900 ///
1901 /// Returns a `TerminalId` that can be used with other terminal methods
1902 /// to get the current output, wait for exit, and kill the command.
1903 ///
1904 /// The `TerminalId` can also be used to embed the terminal in a tool call
1905 /// by using the `ToolCallContent::Terminal` variant.
1906 ///
1907 /// The Agent is responsible for releasing the terminal by using the `terminal/release`
1908 /// method.
1909 ///
1910 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1911 CreateTerminalRequest(CreateTerminalRequest),
1912 /// Gets the terminal output and exit status
1913 ///
1914 /// Returns the current content in the terminal without waiting for the command to exit.
1915 /// If the command has already exited, the exit status is included.
1916 ///
1917 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1918 TerminalOutputRequest(TerminalOutputRequest),
1919 /// Releases a terminal
1920 ///
1921 /// The command is killed if it hasn't exited yet. Use `terminal/wait_for_exit`
1922 /// to wait for the command to exit before releasing the terminal.
1923 ///
1924 /// After release, the `TerminalId` can no longer be used with other `terminal/*` methods,
1925 /// but tool calls that already contain it, continue to display its output.
1926 ///
1927 /// The `terminal/kill` method can be used to terminate the command without releasing
1928 /// the terminal, allowing the Agent to call `terminal/output` and other methods.
1929 ///
1930 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1931 ReleaseTerminalRequest(ReleaseTerminalRequest),
1932 /// Waits for the terminal command to exit and return its exit status
1933 ///
1934 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1935 WaitForTerminalExitRequest(WaitForTerminalExitRequest),
1936 /// Kills the terminal command without releasing the terminal
1937 ///
1938 /// While `terminal/release` will also kill the command, this method will keep
1939 /// the `TerminalId` valid so it can be used with other methods.
1940 ///
1941 /// This method can be helpful when implementing command timeouts which terminate
1942 /// the command as soon as elapsed, and then get the final output so it can be sent
1943 /// to the model.
1944 ///
1945 /// Note: Call `terminal/release` when `TerminalId` is no longer needed.
1946 ///
1947 /// See protocol docs: [Terminals](https://agentclientprotocol.com/protocol/terminals)
1948 KillTerminalRequest(KillTerminalRequest),
1949 /// **UNSTABLE**
1950 ///
1951 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1952 ///
1953 /// Requests structured user input via a form or URL.
1954 #[cfg(feature = "unstable_elicitation")]
1955 CreateElicitationRequest(CreateElicitationRequest),
1956 /// **UNSTABLE**
1957 ///
1958 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1959 ///
1960 /// Opens an MCP-over-ACP connection.
1961 #[cfg(feature = "unstable_mcp_over_acp")]
1962 ConnectMcpRequest(ConnectMcpRequest),
1963 /// **UNSTABLE**
1964 ///
1965 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1966 ///
1967 /// Exchanges an MCP-over-ACP message.
1968 #[cfg(feature = "unstable_mcp_over_acp")]
1969 MessageMcpRequest(MessageMcpRequest),
1970 /// **UNSTABLE**
1971 ///
1972 /// This capability is not part of the spec yet, and may be removed or changed at any point.
1973 ///
1974 /// Closes an MCP-over-ACP connection.
1975 #[cfg(feature = "unstable_mcp_over_acp")]
1976 DisconnectMcpRequest(DisconnectMcpRequest),
1977 /// Handles extension method requests from the agent.
1978 ///
1979 /// Allows the Agent to send an arbitrary request that is not part of the ACP spec.
1980 /// Extension methods provide a way to add custom functionality while maintaining
1981 /// protocol compatibility.
1982 ///
1983 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1984 ExtMethodRequest(ExtRequest),
1985}
1986
1987impl AgentRequest {
1988 /// Returns the corresponding method name of the request.
1989 #[must_use]
1990 pub fn method(&self) -> &str {
1991 match self {
1992 Self::WriteTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_write_text_file,
1993 Self::ReadTextFileRequest(_) => CLIENT_METHOD_NAMES.fs_read_text_file,
1994 Self::RequestPermissionRequest(_) => CLIENT_METHOD_NAMES.session_request_permission,
1995 Self::CreateTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_create,
1996 Self::TerminalOutputRequest(_) => CLIENT_METHOD_NAMES.terminal_output,
1997 Self::ReleaseTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_release,
1998 Self::WaitForTerminalExitRequest(_) => CLIENT_METHOD_NAMES.terminal_wait_for_exit,
1999 Self::KillTerminalRequest(_) => CLIENT_METHOD_NAMES.terminal_kill,
2000 #[cfg(feature = "unstable_elicitation")]
2001 Self::CreateElicitationRequest(_) => CLIENT_METHOD_NAMES.elicitation_create,
2002 #[cfg(feature = "unstable_mcp_over_acp")]
2003 Self::ConnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_connect,
2004 #[cfg(feature = "unstable_mcp_over_acp")]
2005 Self::MessageMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_message,
2006 #[cfg(feature = "unstable_mcp_over_acp")]
2007 Self::DisconnectMcpRequest(_) => CLIENT_METHOD_NAMES.mcp_disconnect,
2008 Self::ExtMethodRequest(ext_request) => &ext_request.method,
2009 }
2010 }
2011}
2012
2013/// All possible responses that a client can send to an agent.
2014///
2015/// This enum is used internally for routing RPC responses. You typically won't need
2016/// to use this directly - the responses are handled automatically by the connection.
2017///
2018/// These are responses to the corresponding `AgentRequest` variants.
2019#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2020#[serde(untagged)]
2021#[schemars(inline)]
2022#[non_exhaustive]
2023pub enum ClientResponse {
2024 WriteTextFileResponse(#[serde(default)] WriteTextFileResponse),
2025 ReadTextFileResponse(ReadTextFileResponse),
2026 RequestPermissionResponse(RequestPermissionResponse),
2027 CreateTerminalResponse(CreateTerminalResponse),
2028 TerminalOutputResponse(TerminalOutputResponse),
2029 ReleaseTerminalResponse(#[serde(default)] ReleaseTerminalResponse),
2030 WaitForTerminalExitResponse(WaitForTerminalExitResponse),
2031 KillTerminalResponse(#[serde(default)] KillTerminalResponse),
2032 #[cfg(feature = "unstable_elicitation")]
2033 CreateElicitationResponse(CreateElicitationResponse),
2034 #[cfg(feature = "unstable_mcp_over_acp")]
2035 ConnectMcpResponse(ConnectMcpResponse),
2036 #[cfg(feature = "unstable_mcp_over_acp")]
2037 DisconnectMcpResponse(#[serde(default)] DisconnectMcpResponse),
2038 ExtMethodResponse(ExtResponse),
2039 #[cfg(feature = "unstable_mcp_over_acp")]
2040 MessageMcpResponse(MessageMcpResponse),
2041}
2042
2043/// All possible notifications that an agent can send to a client.
2044///
2045/// This enum is used internally for routing RPC notifications. You typically won't need
2046/// to use this directly.
2047///
2048/// Notifications do not expect a response.
2049#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
2050#[serde(untagged)]
2051#[expect(clippy::large_enum_variant)]
2052#[schemars(inline)]
2053#[non_exhaustive]
2054pub enum AgentNotification {
2055 /// Handles session update notifications from the agent.
2056 ///
2057 /// This is a notification endpoint (no response expected) that receives
2058 /// real-time updates about session progress, including message chunks,
2059 /// tool calls, and execution plans.
2060 ///
2061 /// Note: Clients SHOULD continue accepting tool call updates even after
2062 /// sending a `session/cancel` notification, as the agent may send final
2063 /// updates before responding with the cancelled stop reason.
2064 ///
2065 /// See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output)
2066 SessionNotification(SessionNotification),
2067 /// **UNSTABLE**
2068 ///
2069 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2070 ///
2071 /// Notification that a URL-based elicitation has completed.
2072 #[cfg(feature = "unstable_elicitation")]
2073 CompleteElicitationNotification(CompleteElicitationNotification),
2074 /// **UNSTABLE**
2075 ///
2076 /// This capability is not part of the spec yet, and may be removed or changed at any point.
2077 ///
2078 /// Receives an MCP-over-ACP notification.
2079 #[cfg(feature = "unstable_mcp_over_acp")]
2080 MessageMcpNotification(MessageMcpNotification),
2081 /// Handles extension notifications from the agent.
2082 ///
2083 /// Allows the Agent to send an arbitrary notification that is not part of the ACP spec.
2084 /// Extension notifications provide a way to send one-way messages for custom functionality
2085 /// while maintaining protocol compatibility.
2086 ///
2087 /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2088 ExtNotification(ExtNotification),
2089}
2090
2091impl AgentNotification {
2092 /// Returns the corresponding method name of the notification.
2093 #[must_use]
2094 pub fn method(&self) -> &str {
2095 match self {
2096 Self::SessionNotification(_) => CLIENT_METHOD_NAMES.session_update,
2097 #[cfg(feature = "unstable_elicitation")]
2098 Self::CompleteElicitationNotification(_) => CLIENT_METHOD_NAMES.elicitation_complete,
2099 #[cfg(feature = "unstable_mcp_over_acp")]
2100 Self::MessageMcpNotification(_) => CLIENT_METHOD_NAMES.mcp_message,
2101 Self::ExtNotification(ext_notification) => &ext_notification.method,
2102 }
2103 }
2104}
2105
2106#[cfg(test)]
2107mod tests {
2108 use super::*;
2109
2110 #[test]
2111 fn test_serialization_behavior() {
2112 use serde_json::json;
2113
2114 assert_eq!(
2115 serde_json::from_value::<SessionInfoUpdate>(json!({})).unwrap(),
2116 SessionInfoUpdate {
2117 title: MaybeUndefined::Undefined,
2118 updated_at: MaybeUndefined::Undefined,
2119 meta: None
2120 }
2121 );
2122 assert_eq!(
2123 serde_json::from_value::<SessionInfoUpdate>(json!({"title": null, "updatedAt": null}))
2124 .unwrap(),
2125 SessionInfoUpdate {
2126 title: MaybeUndefined::Null,
2127 updated_at: MaybeUndefined::Null,
2128 meta: None
2129 }
2130 );
2131 assert_eq!(
2132 serde_json::from_value::<SessionInfoUpdate>(
2133 json!({"title": "title", "updatedAt": "timestamp"})
2134 )
2135 .unwrap(),
2136 SessionInfoUpdate {
2137 title: MaybeUndefined::Value("title".to_string()),
2138 updated_at: MaybeUndefined::Value("timestamp".to_string()),
2139 meta: None
2140 }
2141 );
2142
2143 assert_eq!(
2144 serde_json::to_value(SessionInfoUpdate::new()).unwrap(),
2145 json!({})
2146 );
2147 assert_eq!(
2148 serde_json::to_value(SessionInfoUpdate::new().title("title")).unwrap(),
2149 json!({"title": "title"})
2150 );
2151 assert_eq!(
2152 serde_json::to_value(SessionInfoUpdate::new().title(None)).unwrap(),
2153 json!({"title": null})
2154 );
2155 assert_eq!(
2156 serde_json::to_value(
2157 SessionInfoUpdate::new()
2158 .title("title")
2159 .title(MaybeUndefined::Undefined)
2160 )
2161 .unwrap(),
2162 json!({})
2163 );
2164 }
2165
2166 #[cfg(feature = "unstable_nes")]
2167 #[test]
2168 fn test_client_capabilities_position_encodings_serialization() {
2169 use serde_json::json;
2170
2171 let capabilities = ClientCapabilities::new().position_encodings(vec![
2172 PositionEncodingKind::Utf32,
2173 PositionEncodingKind::Utf16,
2174 ]);
2175 let json = serde_json::to_value(&capabilities).unwrap();
2176
2177 assert_eq!(json["positionEncodings"], json!(["utf-32", "utf-16"]));
2178 }
2179
2180 #[cfg(feature = "unstable_mcp_over_acp")]
2181 #[test]
2182 fn test_agent_mcp_request_method_names() {
2183 use serde_json::json;
2184
2185 let params: serde_json::Map<String, serde_json::Value> =
2186 [("cursor".to_string(), json!("abc"))].into_iter().collect();
2187
2188 assert_eq!(CLIENT_METHOD_NAMES.mcp_connect, "mcp/connect");
2189 assert_eq!(CLIENT_METHOD_NAMES.mcp_message, "mcp/message");
2190 assert_eq!(CLIENT_METHOD_NAMES.mcp_disconnect, "mcp/disconnect");
2191
2192 assert_eq!(
2193 AgentRequest::ConnectMcpRequest(ConnectMcpRequest::new("server-1")).method(),
2194 "mcp/connect"
2195 );
2196 assert_eq!(
2197 AgentRequest::MessageMcpRequest(MessageMcpRequest::new("conn-1", "tools/list"))
2198 .method(),
2199 "mcp/message"
2200 );
2201 assert_eq!(
2202 AgentRequest::DisconnectMcpRequest(DisconnectMcpRequest::new("conn-1")).method(),
2203 "mcp/disconnect"
2204 );
2205 assert_eq!(
2206 AgentNotification::MessageMcpNotification(MessageMcpNotification::new(
2207 "conn-1",
2208 "notifications/progress"
2209 ))
2210 .method(),
2211 "mcp/message"
2212 );
2213
2214 assert_eq!(
2215 serde_json::to_value(ConnectMcpRequest::new("server-1")).unwrap(),
2216 json!({ "acpId": "server-1" })
2217 );
2218 assert_eq!(
2219 serde_json::to_value(ConnectMcpResponse::new("conn-1")).unwrap(),
2220 json!({ "connectionId": "conn-1" })
2221 );
2222 assert_eq!(
2223 serde_json::to_value(MessageMcpRequest::new("conn-1", "tools/list").params(params))
2224 .unwrap(),
2225 json!({
2226 "connectionId": "conn-1",
2227 "method": "tools/list",
2228 "params": { "cursor": "abc" }
2229 })
2230 );
2231 assert_eq!(
2232 serde_json::to_value(DisconnectMcpRequest::new("conn-1")).unwrap(),
2233 json!({ "connectionId": "conn-1" })
2234 );
2235 assert_eq!(
2236 serde_json::to_value(MessageMcpNotification::new(
2237 "conn-1",
2238 "notifications/progress"
2239 ))
2240 .unwrap(),
2241 json!({
2242 "connectionId": "conn-1",
2243 "method": "notifications/progress"
2244 })
2245 );
2246
2247 let request_with_null_params: MessageMcpRequest = serde_json::from_value(json!({
2248 "connectionId": "conn-1",
2249 "method": "tools/list",
2250 "params": null
2251 }))
2252 .unwrap();
2253 assert_eq!(request_with_null_params.params, None);
2254 }
2255}