1use schemars::JsonSchema;
2use serde::{Deserialize, Deserializer, Serialize};
3
4#[derive(Debug, Clone, Deserialize, Serialize)]
7pub struct OpenProjectOutput {
8 pub status: String,
9 pub project_root: String,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub detected_lsp_language: Option<String>,
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub lsp: Option<String>,
14}
15
16#[derive(Debug, Clone, Deserialize)]
17#[serde(deny_unknown_fields)]
18pub struct ReadCodeInput {
19 pub path: String,
20 pub anchor: String,
21 pub mode: ReadCodeMode,
22}
23
24#[derive(Debug, Clone, Copy, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
25#[serde(rename_all = "lowercase")]
26pub enum ReadCodeMode {
27 Around,
28 Full,
29}
30
31#[derive(Debug, Clone, Deserialize, Serialize)]
32pub struct ReadCodeOutput {
33 pub content: String,
35}
36
37#[derive(Debug, Clone, Deserialize, Serialize)]
38pub struct SearchCodeOutput {
39 pub matches: Vec<SearchHit>,
40}
41
42#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
43pub struct SearchHit {
44 pub path: String,
45 pub hit: String,
46}
47
48#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
49#[serde(rename_all = "lowercase")]
50pub enum SearchMode {
51 #[default]
52 Literal,
53 Regex,
54}
55
56#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
57#[serde(rename_all = "lowercase")]
58pub enum SearchCase {
59 Sensitive,
60 Insensitive,
61 #[default]
62 Smart,
63}
64
65#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
66pub struct SearchCodeInput {
67 pub query: String,
68 #[serde(default)]
69 pub mode: SearchMode,
70 pub path: Option<String>,
71 #[serde(default, deserialize_with = "deserialize_string_list")]
72 pub include: Vec<String>,
73 #[serde(default, deserialize_with = "deserialize_string_list")]
74 pub exclude: Vec<String>,
75 #[serde(default, deserialize_with = "deserialize_string_list")]
76 pub types: Vec<String>,
77 #[serde(default, deserialize_with = "deserialize_string_list")]
78 pub type_not: Vec<String>,
79 #[serde(default, rename = "case")]
80 pub case_mode: SearchCase,
81 #[serde(default)]
82 pub word: bool,
83 #[serde(default)]
84 pub whole_line: bool,
85 #[serde(default)]
86 pub hidden: bool,
87 #[serde(default = "default_respect_ignore")]
88 pub respect_ignore: bool,
89 #[serde(default)]
90 pub follow: bool,
91 pub limit: Option<usize>,
92}
93
94impl Default for SearchCodeInput {
95 fn default() -> Self {
96 Self {
97 query: String::new(),
98 mode: SearchMode::default(),
99 path: None,
100 include: Vec::new(),
101 exclude: Vec::new(),
102 types: Vec::new(),
103 type_not: Vec::new(),
104 case_mode: SearchCase::default(),
105 word: false,
106 whole_line: false,
107 hidden: false,
108 respect_ignore: true,
109 follow: false,
110 limit: None,
111 }
112 }
113}
114
115fn default_respect_ignore() -> bool {
116 true
117}
118
119fn deserialize_string_list<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
120where
121 D: Deserializer<'de>,
122{
123 #[derive(Deserialize)]
124 #[serde(untagged)]
125 enum StringList {
126 One(String),
127 Many(Vec<String>),
128 }
129
130 let Some(value) = Option::<StringList>::deserialize(deserializer)? else {
131 return Ok(Vec::new());
132 };
133 Ok(match value {
134 StringList::One(value) => vec![value],
135 StringList::Many(values) => values,
136 })
137}
138
139#[derive(Debug, Clone, Deserialize)]
140pub struct EditCodeInput {
141 pub edits: Vec<StructuredEdit>,
142}
143
144#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
146#[serde(rename_all = "lowercase")]
147pub enum EditOp {
148 Replace,
149 Append,
150 Prepend,
151}
152
153#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
155#[serde(untagged)]
156pub enum EditContent {
157 Lines(Vec<String>),
158 Text(String),
159}
160
161impl EditContent {
162 pub fn into_lines(self) -> Vec<String> {
163 match self {
164 EditContent::Lines(lines) => lines,
165 EditContent::Text(text) => text.lines().map(str::to_string).collect(),
166 }
167 }
168}
169
170#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
172pub struct StructuredEdit {
173 pub path: String,
175 #[serde(default)]
177 pub op: Option<EditOp>,
178 #[serde(default)]
181 pub start: Option<String>,
182 #[serde(skip_serializing_if = "Option::is_none")]
184 pub end: Option<String>,
185 #[serde(skip_serializing_if = "Option::is_none")]
188 pub content: Option<EditContent>,
189}
190
191#[derive(Debug, Clone, Deserialize)]
192pub struct SourceResponsibilityInput {
193 pub path: String,
194}
195
196#[derive(Debug, Clone, Deserialize, Serialize)]
197pub struct SourceResponsibility {
198 pub is_responsible: bool,
199 pub path: String,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub extension: Option<String>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub language: Option<String>,
204 pub reason: String,
205}
206
207#[derive(Debug, Clone, Serialize, PartialEq)]
210#[serde(rename_all = "snake_case")]
211pub enum PropagationSource {
212 Lsp,
213 OpenEnded,
214}
215
216#[derive(Debug, Clone, Serialize)]
217pub struct EditCodeOutput {
218 pub propagation_results: Vec<PropagationResult>,
219 pub applied_summary: AppliedStructuredEditSummary,
220}
221
222#[derive(Debug, Clone, Serialize)]
223pub struct PropagationResult {
224 pub selector: String,
225 pub reason: String,
226 pub source: PropagationSource,
227 #[serde(skip_serializing_if = "Option::is_none")]
228 pub lsp_references: Option<Vec<(String, usize, String)>>,
229 #[serde(skip_serializing_if = "Option::is_none")]
230 pub diff_summary: Option<String>,
231 #[serde(skip_serializing_if = "Option::is_none")]
232 pub file_snippet: Option<String>,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 pub project_files: Option<Vec<String>>,
235}
236
237#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
238#[serde(rename_all = "snake_case")]
239pub enum AppliedStructuredEditOperation {
240 Add,
241 Update,
242}
243
244#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
245pub struct AppliedStructuredEditFile {
246 pub path: String,
247 pub operation: AppliedStructuredEditOperation,
248 pub added_lines: usize,
249 pub removed_lines: usize,
250 pub original_content: String,
251 pub new_content: String,
252}
253
254#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
255pub struct AppliedStructuredEditSummary {
256 pub files: Vec<AppliedStructuredEditFile>,
257}
258
259#[derive(Debug, Clone, Serialize)]
260pub struct ReviewBatch {
261 pub review: Option<ReviewEvent>,
262 pub reviews: Vec<ReviewEvent>,
263 pub returned: usize,
264 pub remaining: usize,
265}
266
267#[derive(Debug, Clone, Serialize)]
268pub struct Reference {
269 pub selector: String,
270 pub line: usize,
271 pub context: String,
272}
273
274#[derive(Debug, Clone, Serialize)]
275#[serde(tag = "type")]
276#[serde(rename_all = "snake_case")]
277pub enum ReviewEvent {
278 KnownReferences {
279 modified_symbol: String,
280 change_summary: String,
281 references: Vec<Reference>,
282 file_snippet: String,
283 },
284 InvestigateImpact {
285 modified_symbol: String,
286 change_summary: String,
287 diff_summary: String,
288 file_snippet: String,
289 project_files: Vec<String>,
290 },
291}