use serde::{Deserialize, Serialize};
pub type ApiVersion = u32;
pub const API_VERSION: ApiVersion = 1;
pub const PLUGIN_API_VERSION: ApiVersion = 1;
pub use scc_context::ContextPack;
pub use scc_core::{SurfaceRenderResult, SystemAtlas, SystemIr, SystemSurfaceMap};
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ModelIdentity {
pub epoch: String,
pub graph_revision: i64,
pub repository_revision: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct OperationResponse<T> {
pub operation: String,
pub api_version: ApiVersion,
pub scc_version: String,
pub model: ModelIdentity,
pub output: T,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TaskContextRequest {
pub goal: String,
#[serde(default)]
pub files: Vec<String>,
#[serde(default)]
pub symbols: Vec<String>,
#[serde(default)]
pub budget: Option<usize>,
#[serde(default)]
pub hook: bool,
#[serde(default = "record_visible_on")]
pub record_visibility: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct StartupRequest {
#[serde(default)]
pub budget: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct SurfaceRequest {
#[serde(default)]
pub task: Option<String>,
#[serde(default)]
pub budget: Option<usize>,
#[serde(default)]
pub explain: bool,
#[serde(default)]
pub stages: Option<SurfaceStages>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
pub struct SurfaceStages {
#[serde(default = "stage_on")]
pub lexical: bool,
#[serde(default = "stage_on")]
pub global_ppr: bool,
#[serde(default = "stage_on")]
pub task_ppr: bool,
#[serde(default = "stage_on")]
pub mmr: bool,
#[serde(default = "stage_on")]
pub quotas: bool,
#[serde(default = "stage_on")]
pub optimizer: bool,
}
fn stage_on() -> bool { true }
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct DetailRequest {
pub id: String,
#[serde(default)]
pub unbounded: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ImpactRequest {
#[serde(default)]
pub files: Vec<String>,
#[serde(default)]
pub symbols: Vec<String>,
#[serde(default)]
pub diff: Option<String>,
#[serde(default)]
pub unbounded: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct StructuralRequest {
#[serde(default)]
pub files: Vec<String>,
#[serde(default)]
pub task: Option<String>,
#[serde(default)]
pub budget: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct QueryRequest {
pub query: String,
#[serde(default)]
pub limit: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TraverseStep {
pub dir: String,
#[serde(default)]
pub predicate: Option<String>,
#[serde(default)]
pub where_kind: Option<String>,
#[serde(default)]
pub limit: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct TraverseRequest {
#[serde(default)]
pub kind: Option<String>,
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub from_ids: Vec<String>,
#[serde(default)]
pub steps: Vec<TraverseStep>,
#[serde(default)]
pub limit: usize,
#[serde(default = "trusted_on")]
pub trusted_only: bool,
}
fn trusted_on() -> bool { true }
fn record_visible_on() -> bool { true }
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct DiffRequest {
pub from: i64,
pub to: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct SnapshotSaveRequest {
pub task: String,
#[serde(default)]
pub budget: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ExportRequest {
pub format: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct IndexPathsRequest {
pub paths: Vec<String>,
#[serde(default)]
pub quiet: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RankRequest {
#[serde(default)]
pub goal: Option<String>,
#[serde(default)]
pub profile: Option<String>,
#[serde(default)]
pub limit: usize,
#[serde(default)]
pub explain: bool,
#[serde(default)]
pub include_features: bool,
#[serde(default)]
pub include_intermediate: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RankItem {
pub id: String,
pub rank: f64,
pub position: usize,
pub features: RankFeatures,
pub specificity: f64,
pub reasons: Vec<String>,
#[serde(default)]
pub plugin_features: std::collections::BTreeMap<String, f64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RankFeatures {
pub task_ppr: f64,
pub global_ppr: f64,
pub lexical: f64,
pub semantic: f64,
pub confidence: f64,
pub criticality: f64,
pub change_risk: f64,
pub novelty: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RankResult {
pub items: Vec<RankItem>,
#[serde(default)]
pub omitted_ids: Vec<String>,
#[serde(default)]
pub warnings: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct SelectionRequest {
pub ranked: Vec<RankedEntry>,
pub budget: usize,
#[serde(default)]
pub lambda: Option<f64>,
#[serde(default)]
pub quotas: Option<Vec<QuotaEntry>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct RankedEntry {
pub id: String,
pub value: f64,
#[serde(default)]
pub token_cost: usize,
#[serde(default)]
pub kind: String,
#[serde(default)]
pub group: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct QuotaEntry {
pub kind: String,
pub fraction: f64,
}
#[cfg(test)]
mod tests {
#[test]
fn request_schemas_generate() {
let schemas = [
schemars::schema_for!(crate::TaskContextRequest),
schemars::schema_for!(crate::StartupRequest),
schemars::schema_for!(crate::SurfaceRequest),
schemars::schema_for!(crate::DetailRequest),
schemars::schema_for!(crate::ImpactRequest),
schemars::schema_for!(crate::StructuralRequest),
schemars::schema_for!(crate::QueryRequest),
schemars::schema_for!(crate::DiffRequest),
schemars::schema_for!(crate::SnapshotSaveRequest),
schemars::schema_for!(crate::ExportRequest),
schemars::schema_for!(crate::IndexPathsRequest),
schemars::schema_for!(crate::RankRequest),
schemars::schema_for!(crate::SelectionRequest),
schemars::schema_for!(crate::ContextPack),
schemars::schema_for!(crate::SystemIr),
schemars::schema_for!(crate::SystemAtlas),
schemars::schema_for!(crate::SystemSurfaceMap),
schemars::schema_for!(crate::SurfaceRenderResult),
];
for s in &schemas {
let v = serde_json::to_value(s).unwrap();
assert!(v.get("$schema").is_some(), "{v}");
}
}
}