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