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