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