1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::api::{AgentRetrievalResult, CodeGraphContextResponse, RuntimeIdentity};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8pub struct AcpInitializeResponse {
9 #[serde(rename = "_meta")]
10 pub meta: AcpInitializeMeta,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub struct AcpInitializeMeta {
15 #[serde(rename = "relayKnowledge")]
16 pub relay_knowledge: AcpRelayKnowledgeCapability,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20pub struct AcpRelayKnowledgeCapability {
21 #[serde(rename = "graphRetrieval")]
22 pub graph_retrieval: bool,
23 #[serde(rename = "readOnly")]
24 pub read_only: bool,
25 #[serde(rename = "supportsCancellation")]
26 pub supports_cancellation: bool,
27 #[serde(rename = "supportsIndexRefreshPermission")]
28 pub supports_index_refresh_permission: bool,
29}
30
31#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
33pub struct AcpSessionRequest {
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub client_name: Option<String>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub client_version: Option<String>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub actor_id: Option<String>,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
44pub struct AcpSession {
45 pub session_id: String,
46 pub runtime_identity: RuntimeIdentity,
47 pub policy_id: String,
48 pub authorized_scope_count: usize,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
53pub struct AcpPromptRequest {
54 pub prompt: String,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub request_id: Option<String>,
57 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
58 pub meta: Option<AcpPromptMeta>,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
62pub struct AcpPromptMeta {
63 #[serde(rename = "relayKnowledge", skip_serializing_if = "Option::is_none")]
64 pub relay_knowledge: Option<AcpRelayKnowledgePrompt>,
65}
66
67#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
68pub struct AcpRelayKnowledgePrompt {
69 #[serde(skip_serializing_if = "Option::is_none")]
70 pub query: Option<String>,
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub source_scope: Option<String>,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub repository: Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub ref_selector: Option<String>,
77 #[serde(default, skip_serializing_if = "Vec::is_empty")]
78 pub path_filters: Vec<String>,
79 #[serde(default, skip_serializing_if = "Vec::is_empty")]
80 pub language_filters: Vec<String>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub limit: Option<usize>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub freshness: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub max_context_bytes: Option<usize>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub include_code: Option<bool>,
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub exclude_generated: Option<bool>,
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct AcpPromptResponse {
96 pub session_id: String,
97 pub request_id: String,
98 pub updates: Vec<AcpSessionUpdate>,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub context_artifact: Option<AcpContextArtifact>,
101 pub stop_reason: AcpStopReason,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub error: Option<AcpErrorPayload>,
104}
105
106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107pub struct AcpContextArtifact {
108 pub artifact_id: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub result: Option<AgentRetrievalResult>,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub codegraph_context: Option<CodeGraphContextResponse>,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
116#[serde(rename_all = "snake_case")]
117pub enum AcpStopReason {
118 Completed,
119 Failed,
120 Cancelled,
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct AcpErrorPayload {
125 pub error_kind: String,
126 pub message: String,
127}
128
129#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
130pub struct AcpSessionUpdate {
131 pub request_id: String,
132 pub kind: AcpSessionUpdateKind,
133 pub status: AcpSessionUpdateStatus,
134 pub message: String,
135 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
136 pub meta: Option<Value>,
137}
138
139impl AcpSessionUpdate {
140 pub(super) fn pending(request_id: &str, message: &str) -> Self {
141 Self::new(
142 request_id,
143 AcpSessionUpdateKind::ToolCallUpdate,
144 AcpSessionUpdateStatus::Pending,
145 message,
146 None,
147 )
148 }
149
150 pub(super) fn in_progress(request_id: &str, message: &str) -> Self {
151 Self::new(
152 request_id,
153 AcpSessionUpdateKind::ToolCallUpdate,
154 AcpSessionUpdateStatus::InProgress,
155 message,
156 None,
157 )
158 }
159
160 pub(super) fn meta(request_id: &str, message: &str, meta: Value) -> Self {
161 Self::new(
162 request_id,
163 AcpSessionUpdateKind::SessionUpdate,
164 AcpSessionUpdateStatus::InProgress,
165 message,
166 Some(meta),
167 )
168 }
169
170 pub(super) fn completed(request_id: &str, message: &str) -> Self {
171 Self::new(
172 request_id,
173 AcpSessionUpdateKind::ToolCallUpdate,
174 AcpSessionUpdateStatus::Completed,
175 message,
176 None,
177 )
178 }
179
180 pub(super) fn failed(request_id: &str, message: &str, status: AcpSessionUpdateStatus) -> Self {
181 Self::new(
182 request_id,
183 AcpSessionUpdateKind::ToolCallUpdate,
184 status,
185 message,
186 None,
187 )
188 }
189
190 fn new(
191 request_id: &str,
192 kind: AcpSessionUpdateKind,
193 status: AcpSessionUpdateStatus,
194 message: &str,
195 meta: Option<Value>,
196 ) -> Self {
197 Self {
198 request_id: request_id.to_owned(),
199 kind,
200 status,
201 message: message.to_owned(),
202 meta,
203 }
204 }
205}
206
207#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
208#[serde(rename_all = "snake_case")]
209pub enum AcpSessionUpdateKind {
210 SessionUpdate,
211 ToolCallUpdate,
212}
213
214#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
215#[serde(rename_all = "snake_case")]
216pub enum AcpSessionUpdateStatus {
217 Pending,
218 InProgress,
219 Completed,
220 Failed,
221 Cancelled,
222}
223
224#[cfg(test)]
225#[path = "protocol_tests.rs"]
226mod tests;