1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum OutputFormat {
7 Table,
8 Json,
9 Markdown,
10}
11
12#[derive(Debug, Clone)]
13pub struct ReportConfig {
14 pub provider: crate::embeddings::ProviderKind,
15 pub model: Option<String>,
16 pub ollama_host: String,
17 pub allow_nonlocal_ollama_host: bool,
18 pub ollama_timeout_secs: u64,
19 pub ollama_keep_alive: Option<String>,
20 pub ollama_dimensions: Option<usize>,
21 pub ollama_truncate: bool,
22 pub model_cache_dir: Option<PathBuf>,
23 pub native_threads: Option<usize>,
24 pub threshold: f32,
25 pub top_k: usize,
26 pub min_lines: usize,
27 pub min_tokens: usize,
28 pub cache_dir: Option<PathBuf>,
29 pub allow_source_upload: bool,
30}
31
32impl Default for ReportConfig {
33 fn default() -> Self {
34 Self {
35 provider: crate::embeddings::ProviderKind::Lexical,
36 model: None,
37 ollama_host: default_ollama_host(),
38 allow_nonlocal_ollama_host: false,
39 ollama_timeout_secs: 120,
40 ollama_keep_alive: None,
41 ollama_dimensions: None,
42 ollama_truncate: true,
43 model_cache_dir: None,
44 native_threads: None,
45 threshold: 0.72,
46 top_k: 25,
47 min_lines: 3,
48 min_tokens: 12,
49 cache_dir: None,
50 allow_source_upload: false,
51 }
52 }
53}
54
55pub fn default_ollama_host() -> String {
56 std::env::var("OLLAMA_HOST").unwrap_or_else(|_| "http://127.0.0.1:11434".to_owned())
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct FunctionRecord {
61 pub id: String,
62 pub name: String,
63 pub file: PathBuf,
64 pub start_line: usize,
65 pub end_line: usize,
66 pub source: String,
67 pub normalized: String,
68 pub token_count: usize,
69 pub line_count: usize,
70 pub content_hash: String,
71 pub expected_group: Option<String>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct FunctionSummary {
76 pub id: String,
77 pub name: String,
78 pub file: PathBuf,
79 pub start_line: usize,
80 pub end_line: usize,
81 pub token_count: usize,
82 pub line_count: usize,
83 pub expected_group: Option<String>,
84}
85
86impl From<&FunctionRecord> for FunctionSummary {
87 fn from(function: &FunctionRecord) -> Self {
88 Self {
89 id: function.id.clone(),
90 name: function.name.clone(),
91 file: function.file.clone(),
92 start_line: function.start_line,
93 end_line: function.end_line,
94 token_count: function.token_count,
95 line_count: function.line_count,
96 expected_group: function.expected_group.clone(),
97 }
98 }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ScoreBreakdown {
103 pub clone: f32,
104 pub semantic: Option<f32>,
105 pub hybrid: f32,
106 pub clone_flag: bool,
107 pub semantic_flag: bool,
108 pub hybrid_flag: bool,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct Candidate {
113 pub id: String,
114 pub left: FunctionRecord,
115 pub right: FunctionRecord,
116 pub scores: ScoreBreakdown,
117 pub reasons: Vec<String>,
118 pub expected_match: bool,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct Report {
123 pub project_root: PathBuf,
124 pub provider: String,
125 pub model: Option<String>,
126 pub functions_count: usize,
127 pub embedding_stats: EmbeddingStats,
128 pub candidates: Vec<Candidate>,
129}
130
131#[derive(Debug, Clone, Default, Serialize, Deserialize)]
132pub struct EmbeddingStats {
133 pub cache_hits: usize,
134 pub cache_misses: usize,
135 pub dimensions: Option<usize>,
136 pub elapsed_ms: u64,
137 pub model_digest: Option<String>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct StrategyEval {
142 pub flagged: usize,
143 pub true_positives: usize,
144 pub false_positives: usize,
145 pub known_pairs: usize,
146 pub precision: f32,
147 pub recall: f32,
148 pub f1: f32,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct EvalReport {
153 pub report: Report,
154 pub functions: Vec<FunctionSummary>,
155 pub clone: StrategyEval,
156 pub semantic: StrategyEval,
157 pub hybrid: StrategyEval,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct EvalMatrixReport {
162 pub project_root: PathBuf,
163 pub provider: String,
164 pub functions_count: usize,
165 pub known_pairs: usize,
166 pub threshold: f32,
167 pub top_k: usize,
168 pub functions: Vec<FunctionSummary>,
169 pub models: Vec<ModelEvalResult>,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct ModelEvalResult {
174 pub model: String,
175 pub status: ModelEvalStatus,
176 pub error_kind: Option<String>,
177 pub error: Option<String>,
178 pub report: Option<Report>,
179 pub clone: Option<StrategyEval>,
180 pub semantic: Option<StrategyEval>,
181 pub hybrid: Option<StrategyEval>,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
185#[serde(rename_all = "snake_case")]
186pub enum ModelEvalStatus {
187 Success,
188 Failure,
189}