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}
72
73#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
74pub struct StartupRequest {
76 #[serde(default)]
77 pub budget: Option<usize>,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
81pub struct SurfaceRequest {
83 #[serde(default)]
84 pub task: Option<String>,
85 #[serde(default)]
86 pub budget: Option<usize>,
87 #[serde(default)]
88 pub explain: bool,
89 #[serde(default)]
92 pub stages: Option<SurfaceStages>,
93}
94
95#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
97pub struct SurfaceStages {
99 #[serde(default = "stage_on")]
100 pub lexical: bool,
101 #[serde(default = "stage_on")]
102 pub global_ppr: bool,
103 #[serde(default = "stage_on")]
104 pub task_ppr: bool,
105 #[serde(default = "stage_on")]
106 pub mmr: bool,
107 #[serde(default = "stage_on")]
108 pub quotas: bool,
109 #[serde(default = "stage_on")]
110 pub optimizer: bool,
111}
112
113fn stage_on() -> bool { true }
115
116#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
117pub struct DetailRequest {
119 pub id: String,
120 #[serde(default)]
121 pub unbounded: bool,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
125pub struct ImpactRequest {
127 #[serde(default)]
128 pub files: Vec<String>,
129 #[serde(default)]
130 pub symbols: Vec<String>,
131 #[serde(default)]
132 pub diff: Option<String>,
133 #[serde(default)]
134 pub unbounded: bool,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
138pub struct StructuralRequest {
140 #[serde(default)]
141 pub files: Vec<String>,
142 #[serde(default)]
143 pub task: Option<String>,
144 #[serde(default)]
145 pub budget: Option<usize>,
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
149pub struct QueryRequest {
151 pub query: String,
152 #[serde(default)]
153 pub limit: usize,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
157pub struct DiffRequest {
159 pub from: i64,
160 pub to: i64,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
164pub struct SnapshotSaveRequest {
166 pub task: String,
167 #[serde(default)]
168 pub budget: Option<usize>,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
172pub struct ExportRequest {
174 pub format: String,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
178pub struct IndexPathsRequest {
180 pub paths: Vec<String>,
181 #[serde(default)]
182 pub quiet: bool,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
186pub struct RankRequest {
188 #[serde(default)]
189 pub goal: Option<String>,
190 #[serde(default)]
191 pub profile: Option<String>,
192 #[serde(default)]
193 pub limit: usize,
194 #[serde(default)]
195 pub explain: bool,
196 #[serde(default)]
197 pub include_features: bool,
198 #[serde(default)]
199 pub include_intermediate: bool,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
203pub struct RankItem {
205 pub id: String,
206 pub rank: f64,
207 pub position: usize,
208 pub features: RankFeatures,
209 pub specificity: f64,
210 pub reasons: Vec<String>,
211 #[serde(default)]
212 pub plugin_features: std::collections::BTreeMap<String, f64>,
213}
214
215#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
216pub struct RankFeatures {
218 pub task_ppr: f64,
219 pub global_ppr: f64,
220 pub lexical: f64,
221 pub semantic: f64,
222 pub confidence: f64,
223 pub criticality: f64,
224 pub change_risk: f64,
225 pub novelty: f64,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
229pub struct RankResult {
231 pub items: Vec<RankItem>,
232 #[serde(default)]
233 pub omitted_ids: Vec<String>,
234 #[serde(default)]
235 pub warnings: Vec<String>,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
239pub struct SelectionRequest {
241 pub ranked: Vec<RankedEntry>,
242 pub budget: usize,
243 #[serde(default)]
244 pub lambda: Option<f64>,
245 #[serde(default)]
246 pub quotas: Option<Vec<QuotaEntry>>,
247}
248
249#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
250pub struct RankedEntry {
252 pub id: String,
253 pub value: f64,
254 #[serde(default)]
255 pub token_cost: usize,
256 #[serde(default)]
257 pub kind: String,
258 #[serde(default)]
259 pub group: Option<String>,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
263pub struct QuotaEntry {
265 pub kind: String,
266 pub fraction: f64,
267}
268
269#[cfg(test)]
270mod tests {
271 #[test]
272 fn request_schemas_generate() {
274 let schemas = [
276 schemars::schema_for!(crate::TaskContextRequest),
277 schemars::schema_for!(crate::StartupRequest),
278 schemars::schema_for!(crate::SurfaceRequest),
279 schemars::schema_for!(crate::DetailRequest),
280 schemars::schema_for!(crate::ImpactRequest),
281 schemars::schema_for!(crate::StructuralRequest),
282 schemars::schema_for!(crate::QueryRequest),
283 schemars::schema_for!(crate::DiffRequest),
284 schemars::schema_for!(crate::SnapshotSaveRequest),
285 schemars::schema_for!(crate::ExportRequest),
286 schemars::schema_for!(crate::IndexPathsRequest),
287 schemars::schema_for!(crate::RankRequest),
288 schemars::schema_for!(crate::SelectionRequest),
289 schemars::schema_for!(crate::ContextPack),
290 schemars::schema_for!(crate::SystemIr),
291 schemars::schema_for!(crate::SystemAtlas),
292 schemars::schema_for!(crate::SystemSurfaceMap),
293 schemars::schema_for!(crate::SurfaceRenderResult),
294 ];
295 for s in &schemas {
296 let v = serde_json::to_value(s).unwrap();
297 assert!(v.get("$schema").is_some(), "{v}");
298 }
299 }
300}