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