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