agent_client_protocol_schema/lib.rs
1//! [](https://agentclientprotocol.com/)
2//!
3//! # Agent Client Protocol (ACP)
4//!
5//! The Agent Client Protocol standardizes communication between code editors
6//! (IDEs, text-editors, etc.) and coding agents (programs that use generative AI
7//! to autonomously modify code).
8//!
9//! ## Protocol & Transport
10//!
11//! ACP is a JSON-RPC based protocol. While clients typically start agents as
12//! subprocesses and communicate over stdio (stdin/stdout), this crate is
13//! transport-agnostic.
14//!
15//! You can use any bidirectional stream that implements `AsyncRead` and `AsyncWrite`.
16//!
17//! ## Core Components
18//!
19//! - **Agent**: Programs that use generative AI to autonomously modify code
20//! - See: [Agent](https://agentclientprotocol.com/protocol/overview#agent)
21//! - **Client**: Code editors that provide the interface between users and agents
22//! - See: [Client](https://agentclientprotocol.com/protocol/overview#client)
23//!
24//! ## Getting Started
25//!
26//! To understand the protocol, start by exploring the [`Agent`] and [`Client`] traits,
27//! which define the core methods and capabilities of each side of the connection.
28//!
29//! To see working examples of these traits in action, check out the
30//! [agent](https://github.com/agentclientprotocol/rust-sdk/blob/main/examples/agent.rs)
31//! and
32//! [client](https://github.com/agentclientprotocol/rust-sdk/blob/main/examples/client.rs)
33//! example binaries included with this crate.
34//!
35//! ### Implementation Pattern
36//!
37//! ACP uses a symmetric design where each participant implements one trait and
38//! creates a connection that provides the complementary trait:
39//!
40//! - **Agent builders** implement the [`Agent`] trait to handle client requests
41//! (like initialization, authentication, and prompts). They pass this implementation
42//! to [`AgentSideConnection::new`], which returns a connection providing [`Client`]
43//! methods for requesting permissions and accessing the file system.
44//!
45//! - **Client builders** implement the [`Client`] trait to handle agent requests
46//! (like file system operations and permission checks). They pass this implementation
47//! to [`ClientSideConnection::new`], which returns a connection providing [`Agent`]
48//! methods for managing sessions and sending prompts.
49//!
50//! For the complete protocol specification and documentation, visit:
51//! [https://agentclientprotocol.com](https://agentclientprotocol.com)
52
53mod agent;
54mod client;
55mod content;
56mod error;
57mod ext;
58mod maybe_undefined;
59mod plan;
60#[cfg(feature = "unstable_cancel_request")]
61mod protocol_level;
62mod rpc;
63mod tool_call;
64mod version;
65
66pub use agent::*;
67pub use client::*;
68pub use content::*;
69use derive_more::{Display, From};
70pub use error::*;
71pub use ext::*;
72pub use maybe_undefined::*;
73pub use plan::*;
74#[cfg(feature = "unstable_cancel_request")]
75pub use protocol_level::*;
76pub use rpc::*;
77pub use serde_json::value::RawValue;
78pub use tool_call::*;
79pub use version::*;
80
81use schemars::JsonSchema;
82use serde::{Deserialize, Serialize};
83use std::{
84 borrow::Cow,
85 ffi::OsStr,
86 path::{Path, PathBuf},
87 sync::Arc,
88};
89
90/// A unique identifier for a conversation session between a client and agent.
91///
92/// Sessions maintain their own context, conversation history, and state,
93/// allowing multiple independent interactions with the same agent.
94///
95/// See protocol docs: [Session ID](https://agentclientprotocol.com/protocol/session-setup#session-id)
96#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, Display, From)]
97#[serde(transparent)]
98#[from(Arc<str>, String, &'static str)]
99#[non_exhaustive]
100pub struct SessionId(pub Arc<str>);
101
102impl SessionId {
103 #[must_use]
104 pub fn new(id: impl Into<Arc<str>>) -> Self {
105 Self(id.into())
106 }
107}
108
109/// Utility trait for builder methods for optional values.
110/// This allows the caller to either pass in the value itself without wrapping it in `Some`,
111/// or to just pass in an Option if that is what they have.
112pub trait IntoOption<T> {
113 fn into_option(self) -> Option<T>;
114}
115
116impl<T> IntoOption<T> for Option<T> {
117 fn into_option(self) -> Option<T> {
118 self
119 }
120}
121
122impl<T> IntoOption<T> for T {
123 fn into_option(self) -> Option<T> {
124 Some(self)
125 }
126}
127
128impl IntoOption<String> for &str {
129 fn into_option(self) -> Option<String> {
130 Some(self.into())
131 }
132}
133
134impl IntoOption<String> for &mut str {
135 fn into_option(self) -> Option<String> {
136 Some(self.into())
137 }
138}
139
140impl IntoOption<String> for &String {
141 fn into_option(self) -> Option<String> {
142 Some(self.into())
143 }
144}
145
146impl IntoOption<String> for Box<str> {
147 fn into_option(self) -> Option<String> {
148 Some(self.into())
149 }
150}
151
152impl IntoOption<String> for Cow<'_, str> {
153 fn into_option(self) -> Option<String> {
154 Some(self.into())
155 }
156}
157
158impl IntoOption<String> for Arc<str> {
159 fn into_option(self) -> Option<String> {
160 Some(self.to_string())
161 }
162}
163
164impl<T: ?Sized + AsRef<OsStr>> IntoOption<PathBuf> for &T {
165 fn into_option(self) -> Option<PathBuf> {
166 Some(self.into())
167 }
168}
169
170impl IntoOption<PathBuf> for Box<Path> {
171 fn into_option(self) -> Option<PathBuf> {
172 Some(self.into())
173 }
174}
175
176impl IntoOption<PathBuf> for Cow<'_, Path> {
177 fn into_option(self) -> Option<PathBuf> {
178 Some(self.into())
179 }
180}
181
182impl IntoOption<serde_json::Value> for &str {
183 fn into_option(self) -> Option<serde_json::Value> {
184 Some(self.into())
185 }
186}
187
188impl IntoOption<serde_json::Value> for String {
189 fn into_option(self) -> Option<serde_json::Value> {
190 Some(self.into())
191 }
192}
193
194impl IntoOption<serde_json::Value> for Cow<'_, str> {
195 fn into_option(self) -> Option<serde_json::Value> {
196 Some(self.into())
197 }
198}