skm_cli/commands/
index.rs1use clap::Args;
4use std::path::PathBuf;
5
6#[derive(Args)]
7pub struct IndexArgs {
8 #[arg(short, long, default_value = ".")]
10 skills: Vec<PathBuf>,
11
12 #[arg(short, long, default_value = ".skm-index.bin")]
14 output: PathBuf,
15
16 #[arg(short, long, default_value = "minilm")]
18 model: String,
19
20 #[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 #[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 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 ®istry,
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}