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