use serde::Serialize;
pub use crate::circular::CircularDependency;
pub use crate::git::ChangedFile;
pub use crate::lsp::types::LspDiagnostic;
pub use crate::rename::RenameEdit;
pub use crate::search::SearchResult;
pub use crate::symbols::{RankedContextEntry, SymbolInfo, SymbolKind};
#[derive(Debug, Clone, Serialize)]
pub struct Relation {
pub source: String,
pub target: String,
pub kind: RelationKind,
pub file_path: Option<String>,
pub line: Option<usize>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum RelationKind {
Calls,
CalledBy,
Imports,
ImportedBy,
Inherits,
Implements,
References,
Contains,
}
#[derive(Debug, Clone, Serialize)]
pub struct IrCallEdge {
pub caller: String,
pub callee: String,
pub caller_file: String,
pub callee_file: Option<String>,
pub line: usize,
}
#[derive(Debug, Clone, Serialize)]
pub struct ImpactNode {
pub file_path: String,
pub symbol: Option<String>,
pub depth: usize,
pub impact_kind: ImpactKind,
pub affected_symbols: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum ImpactKind {
Direct,
Caller,
Importer,
TypeChild,
Transitive,
}
#[derive(Debug, Clone, Serialize)]
pub struct EditPlan {
pub description: String,
pub edits: Vec<EditAction>,
}
#[derive(Debug, Clone, Serialize)]
pub struct EditAction {
pub file_path: String,
pub kind: EditActionKind,
pub line: Option<usize>,
pub old_text: Option<String>,
pub new_text: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum EditActionKind {
Insert,
Replace,
Delete,
Create,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum RetrievalStage {
Lexical,
SymbolScore,
DenseRetrieval,
Rerank,
GraphExpand,
}
#[derive(Debug, Clone, Serialize)]
pub struct RetrievalConfig {
pub stages: Vec<RetrievalStage>,
pub max_results: usize,
pub token_budget: usize,
pub include_body: bool,
pub weights: RetrievalWeights,
}
#[derive(Debug, Clone, Serialize)]
pub struct RetrievalWeights {
pub text: f64,
pub pagerank: f64,
pub recency: f64,
pub semantic: f64,
}
impl Default for RetrievalWeights {
fn default() -> Self {
Self {
text: 0.40,
pagerank: 0.20,
recency: 0.10,
semantic: 0.30,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum IntelligenceSource {
TreeSitter,
Lsp,
Scip,
Semantic,
Hybrid,
}
#[derive(Debug, Clone, Serialize)]
pub struct SearchCandidate {
pub name: String,
pub kind: String,
pub file_path: String,
pub line: usize,
pub signature: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<String>,
pub score: f64,
pub source: IntelligenceSource,
}
impl From<crate::search::SearchResult> for SearchCandidate {
fn from(r: crate::search::SearchResult) -> Self {
Self {
name: r.name,
kind: r.kind,
file_path: r.file,
line: r.line,
signature: r.signature,
name_path: Some(r.name_path),
body: None,
score: r.score,
source: IntelligenceSource::TreeSitter,
}
}
}
impl From<crate::embedding_store::ScoredChunk> for SearchCandidate {
fn from(c: crate::embedding_store::ScoredChunk) -> Self {
Self {
name: c.symbol_name,
kind: c.kind,
file_path: c.file_path,
line: c.line,
signature: c.signature,
name_path: Some(c.name_path),
body: None,
score: c.score,
source: IntelligenceSource::Semantic,
}
}
}
#[derive(Debug, Clone, Serialize)]
pub struct CodeDiagnostic {
pub file_path: String,
pub line: usize,
pub column: usize,
pub severity: DiagnosticSeverity,
pub message: String,
pub source: IntelligenceSource,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub enum DiagnosticSeverity {
Error,
Warning,
Info,
Hint,
}
pub trait PreciseBackend: Send + Sync {
fn find_definitions(
&self,
symbol: &str,
file_path: &str,
line: usize,
) -> anyhow::Result<Vec<SearchCandidate>>;
fn find_references(
&self,
symbol: &str,
file_path: &str,
line: usize,
) -> anyhow::Result<Vec<SearchCandidate>>;
fn hover(&self, file_path: &str, line: usize, column: usize) -> anyhow::Result<Option<String>>;
fn diagnostics(&self, file_path: &str) -> anyhow::Result<Vec<CodeDiagnostic>>;
fn source(&self) -> IntelligenceSource;
fn has_index_for(&self, file_path: &str) -> bool;
}
impl Default for RetrievalConfig {
fn default() -> Self {
Self {
stages: vec![
RetrievalStage::Lexical,
RetrievalStage::SymbolScore,
RetrievalStage::DenseRetrieval,
RetrievalStage::Rerank,
],
max_results: 20,
token_budget: 4000,
include_body: true,
weights: RetrievalWeights::default(),
}
}
}