pub mod adaptive;
pub mod agent;
pub mod agent_classifier;
pub mod agent_formatter;
pub mod code_tokenizer;
pub mod colbert_plaid_backend;
pub mod deep;
pub mod dense_backend;
pub mod fastembed_reranker;
pub mod federation;
pub mod graph_propagation;
pub mod graph_stage;
pub mod hybrid;
pub mod mmr;
pub mod onnx_reranker;
pub mod path_signals;
pub mod plaid_search;
pub mod planner;
pub mod query_classifier;
pub mod query_expander;
pub mod regex_semantic;
pub mod reranker_download;
pub mod reranker_engine;
pub mod reranker_model;
pub mod ripgrep_fallback;
pub mod semantic_cache;
pub mod simd;
pub mod sparse_search;
pub mod summarize;
pub mod triple_fusion;
use crate::types::{FileFilter, SearchResult};
use anyhow::Result;
#[cfg(test)]
pub(crate) static RERANKER_TEST_ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchMetrics {
pub total_ms: u64,
#[serde(default)]
pub dense_ms: Option<u64>,
#[serde(default)]
pub sparse_ms: Option<u64>,
#[serde(default)]
pub exact_ms: Option<u64>,
#[serde(default)]
pub fusion_ms: Option<u64>,
#[serde(default)]
pub rerank_ms: Option<u64>,
pub dense_count: usize,
pub sparse_count: usize,
pub exact_count: usize,
pub fused_count: usize,
pub result_count: usize,
pub query_type: String,
#[serde(default)]
pub response_bytes: Option<usize>,
}
pub struct SearchOutput {
pub results: Vec<SearchResult>,
pub metrics: SearchMetrics,
}
#[derive(Debug, Clone)]
pub struct SearchQuery {
pub text: String,
pub max_results: usize,
pub use_dense: bool,
pub use_sparse: bool,
pub use_rerank: bool,
pub file_filter: Option<FileFilter>,
pub grep_mode: bool,
pub regex_pattern: Option<String>,
pub disable_adaptive: bool,
}
impl SearchQuery {
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
max_results: 10,
use_dense: true,
use_sparse: true,
use_rerank: true,
file_filter: None,
grep_mode: false,
regex_pattern: None,
disable_adaptive: false,
}
}
pub fn max_results(mut self, n: usize) -> Self {
self.max_results = n;
self
}
pub fn disable_adaptive(mut self) -> Self {
self.disable_adaptive = true;
self
}
pub fn dense_only(mut self) -> Self {
self.use_sparse = false;
self.use_rerank = false;
self
}
pub fn sparse_only(mut self) -> Self {
self.use_dense = false;
self.use_rerank = false;
self
}
pub fn no_rerank(mut self) -> Self {
self.use_rerank = false;
self
}
pub fn grep_mode(mut self) -> Self {
self.grep_mode = true;
self.use_dense = false;
self.use_sparse = true;
self.use_rerank = false;
self.max_results = 50;
self
}
pub fn regex_pattern(mut self, pattern: Option<String>) -> Self {
self.regex_pattern = pattern;
self
}
pub fn include_types(mut self, extensions: Vec<String>) -> Self {
let filter = self.file_filter.get_or_insert_with(FileFilter::default);
filter.include_extensions = extensions;
self
}
pub fn exclude_types(mut self, extensions: Vec<String>) -> Self {
let filter = self.file_filter.get_or_insert_with(FileFilter::default);
filter.exclude_extensions = extensions;
self
}
pub fn code_only(self) -> Self {
self.exclude_types(
FileFilter::NON_CODE_EXTENSIONS
.iter()
.map(std::string::ToString::to_string)
.collect(),
)
}
}
pub trait Searcher: Send + Sync {
fn search(&self, query: &SearchQuery) -> Result<Vec<SearchResult>>;
}
#[cfg(test)]
mod query_builder_tests {
use super::SearchQuery;
#[test]
fn disable_adaptive_defaults_to_false() {
let q = SearchQuery::new("x");
assert!(
!q.disable_adaptive,
"disable_adaptive must default to false"
);
}
#[test]
fn disable_adaptive_builder_sets_flag() {
let q = SearchQuery::new("x").disable_adaptive();
assert!(
q.disable_adaptive,
"disable_adaptive() builder must set the flag true"
);
}
}