1use serde::{Deserialize, Serialize};
11
12pub type ApiVersion = u32;
15
16pub const API_VERSION: ApiVersion = 1;
19
20pub const PLUGIN_API_VERSION: ApiVersion = 1;
23
24pub use scc_context::ContextPack;
30pub use scc_core::{SurfaceRenderResult, SystemAtlas, SystemIr, SystemSurfaceMap};
32
33#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
38pub struct ModelIdentity {
40 pub epoch: String,
41 pub graph_revision: i64,
42 pub repository_revision: String,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
46pub struct OperationResponse<T> {
48 pub operation: String,
49 pub api_version: ApiVersion,
50 pub scc_version: String,
51 pub model: ModelIdentity,
52 pub output: T,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
60pub struct TaskContextRequest {
62 pub goal: String,
63 #[serde(default)]
64 pub files: Vec<String>,
65 #[serde(default)]
66 pub symbols: Vec<String>,
67 #[serde(default)]
68 pub budget: Option<usize>,
69 #[serde(default)]
70 pub hook: bool,
71 #[serde(default = "record_visible_on")]
74 pub record_visibility: bool,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
78pub struct StartupRequest {
80 #[serde(default)]
81 pub budget: Option<usize>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
85pub struct SurfaceRequest {
87 #[serde(default)]
88 pub task: Option<String>,
89 #[serde(default)]
90 pub budget: Option<usize>,
91 #[serde(default)]
92 pub explain: bool,
93 #[serde(default)]
96 pub stages: Option<SurfaceStages>,
97}
98
99#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
101pub struct SurfaceStages {
103 #[serde(default = "stage_on")]
104 pub lexical: bool,
105 #[serde(default = "stage_on")]
106 pub global_ppr: bool,
107 #[serde(default = "stage_on")]
108 pub task_ppr: bool,
109 #[serde(default = "stage_on")]
110 pub mmr: bool,
111 #[serde(default = "stage_on")]
112 pub quotas: bool,
113 #[serde(default = "stage_on")]
114 pub optimizer: bool,
115}
116
117fn stage_on() -> bool { true }
119
120#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
121pub struct DetailRequest {
123 pub id: String,
124 #[serde(default)]
125 pub unbounded: bool,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
129pub struct ImpactRequest {
131 #[serde(default)]
132 pub files: Vec<String>,
133 #[serde(default)]
134 pub symbols: Vec<String>,
135 #[serde(default)]
136 pub diff: Option<String>,
137 #[serde(default)]
138 pub unbounded: bool,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
142pub struct StructuralRequest {
144 #[serde(default)]
145 pub files: Vec<String>,
146 #[serde(default)]
147 pub task: Option<String>,
148 #[serde(default)]
149 pub budget: Option<usize>,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
153pub struct QueryRequest {
155 pub query: String,
156 #[serde(default)]
157 pub limit: usize,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
166pub struct TraverseStep {
168 pub dir: String,
170 #[serde(default)]
172 pub predicate: Option<String>,
173 #[serde(default)]
175 pub where_kind: Option<String>,
176 #[serde(default)]
178 pub limit: usize,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
182pub struct TraverseRequest {
184 #[serde(default)]
186 pub kind: Option<String>,
187 #[serde(default)]
189 pub name: Option<String>,
190 #[serde(default)]
192 pub from_ids: Vec<String>,
193 #[serde(default)]
195 pub steps: Vec<TraverseStep>,
196 #[serde(default)]
198 pub limit: usize,
199 #[serde(default = "trusted_on")]
202 pub trusted_only: bool,
203}
204
205fn trusted_on() -> bool { true }
207
208fn record_visible_on() -> bool { true }
210
211#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
212pub struct DiffRequest {
214 pub from: i64,
215 pub to: i64,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
219pub struct SnapshotSaveRequest {
221 pub task: String,
222 #[serde(default)]
223 pub budget: Option<usize>,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
227pub struct ExportRequest {
229 pub format: String,
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
233pub struct IndexPathsRequest {
235 pub paths: Vec<String>,
236 #[serde(default)]
237 pub quiet: bool,
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
241pub struct RankRequest {
243 #[serde(default)]
244 pub goal: Option<String>,
245 #[serde(default)]
246 pub profile: Option<String>,
247 #[serde(default)]
248 pub limit: usize,
249 #[serde(default)]
250 pub explain: bool,
251 #[serde(default)]
252 pub include_features: bool,
253 #[serde(default)]
254 pub include_intermediate: bool,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
258pub struct RankItem {
260 pub id: String,
261 pub rank: f64,
262 pub position: usize,
263 pub features: RankFeatures,
264 pub specificity: f64,
265 pub reasons: Vec<String>,
266 #[serde(default)]
267 pub plugin_features: std::collections::BTreeMap<String, f64>,
268}
269
270#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
271pub struct RankFeatures {
273 pub task_ppr: f64,
274 pub global_ppr: f64,
275 pub lexical: f64,
276 pub semantic: f64,
277 pub confidence: f64,
278 pub criticality: f64,
279 pub change_risk: f64,
280 pub novelty: f64,
281}
282
283#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
284pub struct RankResult {
286 pub items: Vec<RankItem>,
287 #[serde(default)]
288 pub omitted_ids: Vec<String>,
289 #[serde(default)]
290 pub warnings: Vec<String>,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
294pub struct SelectionRequest {
296 pub ranked: Vec<RankedEntry>,
297 pub budget: usize,
298 #[serde(default)]
299 pub lambda: Option<f64>,
300 #[serde(default)]
301 pub quotas: Option<Vec<QuotaEntry>>,
302}
303
304#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
305pub struct RankedEntry {
307 pub id: String,
308 pub value: f64,
309 #[serde(default)]
310 pub token_cost: usize,
311 #[serde(default)]
312 pub kind: String,
313 #[serde(default)]
314 pub group: Option<String>,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
318pub struct QuotaEntry {
320 pub kind: String,
321 pub fraction: f64,
322}
323
324#[cfg(test)]
325mod tests {
326 #[test]
327 fn request_schemas_generate() {
329 let schemas = [
331 schemars::schema_for!(crate::TaskContextRequest),
332 schemars::schema_for!(crate::StartupRequest),
333 schemars::schema_for!(crate::SurfaceRequest),
334 schemars::schema_for!(crate::DetailRequest),
335 schemars::schema_for!(crate::ImpactRequest),
336 schemars::schema_for!(crate::StructuralRequest),
337 schemars::schema_for!(crate::QueryRequest),
338 schemars::schema_for!(crate::DiffRequest),
339 schemars::schema_for!(crate::SnapshotSaveRequest),
340 schemars::schema_for!(crate::ExportRequest),
341 schemars::schema_for!(crate::IndexPathsRequest),
342 schemars::schema_for!(crate::RankRequest),
343 schemars::schema_for!(crate::SelectionRequest),
344 schemars::schema_for!(crate::ContextPack),
345 schemars::schema_for!(crate::SystemIr),
346 schemars::schema_for!(crate::SystemAtlas),
347 schemars::schema_for!(crate::SystemSurfaceMap),
348 schemars::schema_for!(crate::SurfaceRenderResult),
349 ];
350 for s in &schemas {
351 let v = serde_json::to_value(s).unwrap();
352 assert!(v.get("$schema").is_some(), "{v}");
353 }
354 }
355}