the-code-graph-cli 0.1.2

Command-line interface for The Code Graph
Documentation
use domain::error::Result;
use domain::use_cases::query::QueryUseCase;

use crate::commands::helpers::open_graph;
use crate::commands::SearchArgs;
use crate::output::{print, OutputFormat};

pub fn run_search(args: &SearchArgs, output_format: OutputFormat) -> Result<()> {
    if args.semantic_only && args.fts_only {
        return Err(domain::error::CodeGraphError::Other(
            "--semantic-only and --fts-only are mutually exclusive".into(),
        ));
    }

    let (store, _root) = open_graph()?;

    #[cfg(feature = "embeddings")]
    {
        use std::sync::Arc;

        use crate::config::load_config;
        use domain::model::{HybridSearchConfig, SearchMode};
        use domain::ports::VectorStore;

        let config = load_config(&_root)?;
        let mode = match (args.semantic_only, args.fts_only) {
            (true, false) => SearchMode::SemanticOnly,
            (false, true) => SearchMode::FtsOnly,
            _ => SearchMode::Hybrid,
        };

        let hybrid_config = HybridSearchConfig {
            rrf_k: config.search.as_ref().and_then(|s| s.rrf_k).unwrap_or(60),
            kind_boost: config
                .search
                .as_ref()
                .and_then(|s| s.kind_boost)
                .unwrap_or(true),
        };

        let vs: Arc<dyn VectorStore> = Arc::new(store.clone());
        if vs.has_embeddings() {
            let model = config
                .embeddings
                .as_ref()
                .and_then(|e| e.model.clone())
                .unwrap_or_else(|| "all-MiniLM-L6-v2".into());
            let ep: Arc<dyn domain::ports::EmbeddingProvider> = Arc::new(
                embeddings::OnnxEmbeddingProvider::from_model_name(&model, 384)
                    .map_err(|e| domain::error::CodeGraphError::Other(e.to_string()))?,
            );
            let uc = QueryUseCase::with_hybrid(store.clone(), store, Some(vs), Some(ep));
            let results = uc.hybrid_search(&args.query, args.limit, mode, &hybrid_config)?;
            print(&results, output_format);
            return Ok(());
        }
    }

    if args.semantic_only {
        return Err(domain::error::CodeGraphError::Other(
            "no embeddings found; run 'code-graph index --embed' first".into(),
        ));
    }
    let uc = QueryUseCase::new(store.clone(), store);
    let results = uc.search(&args.query, args.limit)?;
    print(&results, output_format);
    Ok(())
}