1pub mod mcp_types;
2pub use mcp_types::*;
3
4use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc};
5
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9pub const NEW_SESSION_TOOL_NAME: &str = "acp__new_session";
12
13#[derive(Debug, Serialize, Deserialize, JsonSchema)]
14#[serde(rename_all = "camelCase")]
15pub struct NewSessionToolArguments {
16 pub mcp_servers: HashMap<String, McpServerConfig>,
17 pub client_tools: ClientTools,
18 pub cwd: PathBuf,
19}
20
21pub const LOAD_SESSION_TOOL_NAME: &str = "acp__load_session";
24
25#[derive(Debug, Serialize, Deserialize, JsonSchema)]
26#[serde(rename_all = "camelCase")]
27pub struct LoadSessionToolArguments {
28 pub mcp_servers: HashMap<String, McpServerConfig>,
29 pub client_tools: ClientTools,
30 pub cwd: PathBuf,
31 pub session_id: SessionId,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
35#[serde(transparent)]
36pub struct SessionId(pub Arc<str>);
37
38impl Display for SessionId {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{}", self.0)
41 }
42}
43
44#[derive(Debug, Serialize, Deserialize, JsonSchema)]
45#[serde(rename_all = "camelCase")]
46pub struct McpServerConfig {
47 pub command: String,
48 pub args: Vec<String>,
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub env: Option<HashMap<String, String>>,
51 #[serde(default)]
53 pub enabled_tools: Option<Vec<String>>,
54}
55
56#[derive(Debug, Serialize, Deserialize, JsonSchema)]
57#[serde(rename_all = "camelCase")]
58pub struct McpToolId {
59 pub mcp_server: String,
60 pub tool_name: String,
61}
62
63pub const PROMPT_TOOL_NAME: &str = "acp__prompt";
66
67#[derive(Debug, Serialize, Deserialize, JsonSchema)]
68#[serde(rename_all = "camelCase")]
69pub struct PromptToolArguments {
70 pub session_id: SessionId,
71 pub prompt: Vec<ContentBlock>,
72}
73
74#[derive(Debug, Serialize, Deserialize, JsonSchema)]
77#[serde(tag = "type", rename_all = "camelCase")]
78pub struct SessionNotification {
79 pub session_id: SessionId,
80 #[serde(flatten)]
81 pub update: SessionUpdate,
82}
83
84#[derive(Debug, Serialize, Deserialize, JsonSchema)]
85#[serde(tag = "type", rename_all = "camelCase")]
86pub enum SessionUpdate {
87 Started,
88 UserMessage(ContentBlock),
89 AgentMessage(ContentBlock),
90 AgentThought(ContentBlock),
91 ToolCall(ToolCall),
92 Plan(Plan),
93}
94
95#[derive(Debug, Serialize, Deserialize, JsonSchema)]
96#[serde(rename_all = "camelCase")]
97pub struct ToolCall {
98 pub id: ToolCallId,
99 pub label: String,
100 pub kind: ToolKind,
101 pub status: ToolCallStatus,
102 #[serde(skip_serializing_if = "Vec::is_empty")]
103 pub content: Vec<ToolCallContent>,
104 #[serde(default, skip_serializing_if = "Vec::is_empty")]
105 pub locations: Vec<ToolCallLocation>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
109#[serde(transparent)]
110pub struct ToolCallId(pub Arc<str>);
111
112#[derive(Debug, Serialize, Deserialize, JsonSchema)]
113#[serde(rename_all = "camelCase")]
114pub enum ToolKind {
115 Read,
116 Edit,
117 Search,
118 Execute,
119 Think,
120 Fetch,
121 Other,
122}
123
124#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema)]
125#[serde(rename_all = "camelCase")]
126pub enum ToolCallStatus {
127 InProgress,
129 Completed,
131 Failed,
133}
134
135#[derive(Debug, Serialize, Deserialize, JsonSchema)]
136#[serde(untagged, rename_all = "camelCase")]
137pub enum ToolCallContent {
139 ContentBlock { content: ContentBlock },
140 Diff { diff: Diff },
141}
142
143impl<T: Into<ContentBlock>> From<T> for ToolCallContent {
144 fn from(content: T) -> Self {
145 ToolCallContent::ContentBlock {
146 content: content.into(),
147 }
148 }
149}
150
151impl From<Diff> for ToolCallContent {
152 fn from(diff: Diff) -> Self {
153 ToolCallContent::Diff { diff }
154 }
155}
156
157#[derive(Debug, Serialize, Deserialize, JsonSchema)]
158#[serde(rename_all = "camelCase")]
159pub struct Diff {
160 pub path: PathBuf,
161 pub old_text: Option<String>,
162 pub new_text: String,
163}
164
165#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
166#[serde(tag = "type", rename_all = "camelCase")]
167pub struct ToolCallLocation {
168 pub path: PathBuf,
169 #[serde(skip_serializing_if = "Option::is_none")]
170 pub line: Option<u32>,
171}
172
173#[derive(Debug, Serialize, Deserialize, JsonSchema)]
174#[serde(rename_all = "camelCase")]
175pub struct Plan {
176 pub entries: Vec<PlanEntry>,
177}
178
179#[derive(Debug, Serialize, Deserialize, JsonSchema)]
184#[serde(rename_all = "camelCase")]
185pub struct PlanEntry {
186 pub content: String,
188 pub priority: PlanEntryPriority,
190 pub status: PlanEntryStatus,
192}
193
194#[derive(Deserialize, Serialize, JsonSchema, Debug)]
199#[serde(rename_all = "snake_case")]
200pub enum PlanEntryPriority {
201 High,
202 Medium,
203 Low,
204}
205
206#[derive(Deserialize, Serialize, JsonSchema, Debug)]
210#[serde(rename_all = "snake_case")]
211pub enum PlanEntryStatus {
212 Pending,
213 InProgress,
214 Completed,
215}
216
217#[derive(Debug, Serialize, Deserialize, JsonSchema)]
220#[serde(rename_all = "camelCase")]
221pub struct ClientTools {
222 pub confirm_permission: Option<McpToolId>,
223 pub write_text_file: Option<McpToolId>,
224 pub read_text_file: Option<McpToolId>,
225}
226
227#[derive(Debug, Serialize, Deserialize, JsonSchema)]
230#[serde(rename_all = "camelCase")]
231pub struct PermissionToolArguments {
232 pub session_id: SessionId,
233 pub tool_call: ToolCall,
234 pub options: Vec<PermissionOption>,
235}
236
237#[derive(Debug, Serialize, Deserialize, JsonSchema)]
238pub struct PermissionOption {
239 pub id: PermissionOptionId,
240 pub label: String,
241 pub kind: PermissionOptionKind,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash)]
245#[serde(transparent)]
246pub struct PermissionOptionId(pub Arc<str>);
247
248#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
249#[serde(rename_all = "camelCase")]
250pub enum PermissionOptionKind {
251 AllowOnce,
252 AllowAlways,
253 RejectOnce,
254 RejectAlways,
255}
256
257#[derive(Debug, Serialize, Deserialize, JsonSchema)]
258#[serde(tag = "outcome", rename_all = "camelCase")]
259pub enum PermissionOutcome {
260 Canceled,
261 #[serde(rename_all = "camelCase")]
262 Selected {
263 option_id: PermissionOptionId,
264 },
265}
266
267#[derive(Debug, Serialize, Deserialize, JsonSchema)]
270#[serde(rename_all = "camelCase")]
271pub struct WriteTextFileToolArguments {
272 pub session_id: SessionId,
273 pub path: PathBuf,
274 pub content: String,
275}
276
277#[derive(Debug, Serialize, Deserialize, JsonSchema)]
280#[serde(rename_all = "camelCase")]
281pub struct ReadTextFileArguments {
282 pub session_id: SessionId,
283 pub path: PathBuf,
284 #[serde(skip_serializing_if = "Option::is_none")]
285 pub line: Option<u32>,
286 #[serde(skip_serializing_if = "Option::is_none")]
287 pub limit: Option<u32>,
288}