Skip to main content

skm_cli/commands/
index.rs

1//! Index command: build/rebuild embedding index.
2
3use clap::Args;
4use std::path::PathBuf;
5
6#[derive(Args)]
7pub struct IndexArgs {
8    /// Skill directories
9    #[arg(short, long, default_value = ".")]
10    skills: Vec<PathBuf>,
11
12    /// Output index file
13    #[arg(short, long, default_value = ".skm-index.bin")]
14    output: PathBuf,
15
16    /// Embedding model (bge-m3, minilm)
17    #[arg(short, long, default_value = "minilm")]
18    model: String,
19
20    /// Force rebuild even if cache is valid
21    #[arg(short, long)]
22    force: bool,
23}
24
25pub async fn index(args: IndexArgs) -> anyhow::Result<()> {
26    println!("Building embedding index...");
27    println!("  Skills: {:?}", args.skills);
28    println!("  Output: {:?}", args.output);
29    println!("  Model: {}", args.model);
30    println!("  Force: {}", args.force);
31    println!();
32
33    // Check if we have embedding features
34    #[cfg(not(any(feature = "embed-bge-m3", feature = "embed-minilm")))]
35    {
36        println!("Warning: No embedding providers compiled in.");
37        println!("Rebuild with --features embed-bge-m3 or --features embed-minilm");
38        return Ok(());
39    }
40
41    #[cfg(any(feature = "embed-bge-m3", feature = "embed-minilm"))]
42    {
43        use skm_core::SkillRegistry;
44        use skm_embed::{ComponentWeights, EmbeddingIndex, EmbeddingProvider};
45
46        let registry = SkillRegistry::new(&args.skills).await?;
47        println!("Found {} skills", registry.len().await);
48
49        // Create provider based on model
50        let provider: Box<dyn EmbeddingProvider> = match args.model.as_str() {
51            #[cfg(feature = "embed-bge-m3")]
52            "bge-m3" | "bge" => {
53                println!("Loading BGE-M3 model...");
54                Box::new(skm_embed::BgeM3Provider::new()?)
55            }
56            #[cfg(feature = "embed-minilm")]
57            "minilm" | "mini" => {
58                println!("Loading MiniLM model...");
59                Box::new(skm_embed::MiniLmProvider::new()?)
60            }
61            other => {
62                anyhow::bail!("Unknown model: {}. Use 'bge-m3' or 'minilm'", other);
63            }
64        };
65
66        println!("Building index (this may take a while)...");
67        let index = EmbeddingIndex::build(
68            &registry,
69            provider.as_ref(),
70            ComponentWeights::default(),
71        )
72        .await?;
73
74        println!("Saving index to {:?}...", args.output);
75        index.save(&args.output)?;
76
77        println!("✓ Index built successfully ({} skills)", index.len());
78    }
79
80    Ok(())
81}