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