use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum CacheMode {
#[default]
Platform,
Local,
Off,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexWarning {
pub path: String,
pub message: String,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Chunk {
pub content: String,
pub file_path: String,
pub start_line: usize,
pub end_line: usize,
pub language: Option<String>,
}
impl Chunk {
pub fn location(&self) -> String {
format!("{}:{}-{}", self.file_path, self.start_line, self.end_line)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SearchMode {
Hybrid,
Semantic,
Bm25,
}
impl std::str::FromStr for SearchMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"hybrid" => Ok(Self::Hybrid),
"semantic" => Ok(Self::Semantic),
"bm25" => Ok(Self::Bm25),
_ => Err(format!("Unknown search mode: {s}")),
}
}
}
impl std::fmt::Display for SearchMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Hybrid => write!(f, "hybrid"),
Self::Semantic => write!(f, "semantic"),
Self::Bm25 => write!(f, "bm25"),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct SearchOptions {
pub top_k: usize,
pub mode: SearchMode,
pub alpha: Option<f32>,
pub filter_languages: Vec<String>,
pub filter_paths: Vec<String>,
pub use_query_cache: bool,
}
impl Default for SearchOptions {
fn default() -> Self {
Self {
top_k: 5,
mode: SearchMode::Hybrid,
alpha: None,
filter_languages: Vec::new(),
filter_paths: Vec::new(),
use_query_cache: true,
}
}
}
impl SearchOptions {
pub fn new(top_k: usize) -> Self {
Self {
top_k,
..Self::default()
}
}
pub fn with_mode(mut self, mode: SearchMode) -> Self {
self.mode = mode;
self
}
pub fn with_alpha(mut self, alpha: f32) -> Self {
self.alpha = Some(alpha);
self
}
pub fn with_languages(mut self, languages: impl IntoIterator<Item = String>) -> Self {
self.filter_languages = languages.into_iter().collect();
self
}
pub fn with_paths(mut self, paths: impl IntoIterator<Item = String>) -> Self {
self.filter_paths = paths.into_iter().collect();
self
}
pub fn with_cache(mut self, use_query_cache: bool) -> Self {
self.use_query_cache = use_query_cache;
self
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SearchResult {
pub chunk: Chunk,
pub score: f32,
pub source: SearchMode,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct IndexStats {
pub indexed_files: usize,
pub total_chunks: usize,
pub languages: std::collections::BTreeMap<String, usize>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IndexOptions {
pub cache_mode: CacheMode,
}
impl Default for IndexOptions {
fn default() -> Self {
Self {
cache_mode: CacheMode::Platform,
}
}
}