the_code_graph_cli/commands/
search.rs1use domain::error::Result;
2use domain::use_cases::query::QueryUseCase;
3
4use crate::commands::helpers::open_graph;
5use crate::commands::SearchArgs;
6use crate::output::{print, OutputFormat};
7
8pub fn run_search(args: &SearchArgs, output_format: OutputFormat) -> Result<()> {
9 if args.semantic_only && args.fts_only {
10 return Err(domain::error::CodeGraphError::Other(
11 "--semantic-only and --fts-only are mutually exclusive".into(),
12 ));
13 }
14
15 let (store, _root) = open_graph()?;
16
17 #[cfg(feature = "embeddings")]
18 {
19 use std::sync::Arc;
20
21 use crate::config::load_config;
22 use domain::model::{HybridSearchConfig, SearchMode};
23 use domain::ports::VectorStore;
24
25 let config = load_config(&_root)?;
26 let mode = match (args.semantic_only, args.fts_only) {
27 (true, false) => SearchMode::SemanticOnly,
28 (false, true) => SearchMode::FtsOnly,
29 _ => SearchMode::Hybrid,
30 };
31
32 let hybrid_config = HybridSearchConfig {
33 rrf_k: config.search.as_ref().and_then(|s| s.rrf_k).unwrap_or(60),
34 kind_boost: config
35 .search
36 .as_ref()
37 .and_then(|s| s.kind_boost)
38 .unwrap_or(true),
39 };
40
41 let vs: Arc<dyn VectorStore> = Arc::new(store.clone());
42 if vs.has_embeddings() {
43 let model = config
44 .embeddings
45 .as_ref()
46 .and_then(|e| e.model.clone())
47 .unwrap_or_else(|| "all-MiniLM-L6-v2".into());
48 let ep: Arc<dyn domain::ports::EmbeddingProvider> = Arc::new(
49 embeddings::OnnxEmbeddingProvider::from_model_name(&model, 384)
50 .map_err(|e| domain::error::CodeGraphError::Other(e.to_string()))?,
51 );
52 let uc = QueryUseCase::with_hybrid(store.clone(), store, Some(vs), Some(ep));
53 let results = uc.hybrid_search(&args.query, args.limit, mode, &hybrid_config)?;
54 print(&results, output_format);
55 return Ok(());
56 }
57 }
58
59 if args.semantic_only {
60 return Err(domain::error::CodeGraphError::Other(
61 "no embeddings found; run 'code-graph index --embed' first".into(),
62 ));
63 }
64 let uc = QueryUseCase::new(store.clone(), store);
65 let results = uc.search(&args.query, args.limit)?;
66 print(&results, output_format);
67 Ok(())
68}