skm_cli/commands/
select.rs1use clap::Args;
4use std::path::PathBuf;
5
6use skm_core::SkillRegistry;
7use skm_select::{CascadeSelector, SelectionContext, TriggerStrategy};
8
9#[derive(Args)]
10pub struct SelectArgs {
11 query: String,
13
14 #[arg(short, long, default_value = ".")]
16 skills: Vec<PathBuf>,
17
18 #[arg(short = 'k', long, default_value = "5")]
20 top_k: usize,
21
22 #[arg(long)]
24 verbose: bool,
25
26 #[arg(long, default_value = "text")]
28 format: String,
29}
30
31pub async fn select(args: SelectArgs) -> anyhow::Result<()> {
32 let registry = SkillRegistry::new(&args.skills).await?;
33
34 let trigger = TriggerStrategy::from_registry(®istry).await?;
36
37 let selector = CascadeSelector::builder().with_triggers(trigger).build();
39
40 let ctx = SelectionContext::new();
42 let outcome = selector.select(&args.query, ®istry, &ctx).await?;
43
44 match args.format.as_str() {
45 "json" => {
46 let results: Vec<serde_json::Value> = outcome
47 .selected
48 .iter()
49 .take(args.top_k)
50 .map(|r| {
51 serde_json::json!({
52 "skill": r.skill.as_str(),
53 "score": r.score,
54 "confidence": format!("{:?}", r.confidence),
55 "strategy": r.strategy,
56 "reasoning": r.reasoning
57 })
58 })
59 .collect();
60
61 let output = serde_json::json!({
62 "query": args.query,
63 "results": results,
64 "latency_ms": outcome.total_latency.as_millis(),
65 "strategies_used": outcome.strategies_used,
66 "fallback_used": outcome.fallback_used
67 });
68
69 println!("{}", serde_json::to_string_pretty(&output)?);
70 }
71 _ => {
72 println!("Query: {}\n", args.query);
73
74 if outcome.selected.is_empty() {
75 println!("No matching skills found.");
76 } else {
77 println!("Results:");
78 for (i, r) in outcome.selected.iter().take(args.top_k).enumerate() {
79 println!(
80 " {}. {} (score: {:.2}, confidence: {:?}, strategy: {})",
81 i + 1,
82 r.skill,
83 r.score,
84 r.confidence,
85 r.strategy
86 );
87 if args.verbose {
88 if let Some(ref reasoning) = r.reasoning {
89 println!(" reasoning: {}", reasoning);
90 }
91 }
92 }
93 }
94
95 println!("\nLatency: {:?}", outcome.total_latency);
96 println!("Strategies: {:?}", outcome.strategies_used);
97 }
98 }
99
100 Ok(())
101}