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