Print a grouped list of every available tool. Tools annotated as `alwaysLoad` come first since they're the most commonly used; everything else is alphabetized.
(defs: &[ToolDefinition])
| 322 | /// `alwaysLoad` come first since they're the most commonly used; everything |
| 323 | /// else is alphabetized. |
| 324 | fn print_tool_list(defs: &[ToolDefinition]) { |
| 325 | let mut groups: BTreeMap<&str, Vec<&ToolDefinition>> = BTreeMap::new(); |
| 326 | let mut always = Vec::new(); |
| 327 | for def in defs { |
| 328 | let is_always = def |
| 329 | .meta |
| 330 | .as_ref() |
| 331 | .and_then(|m| m.get("anthropic/alwaysLoad")) |
| 332 | .and_then(Value::as_bool) |
| 333 | .unwrap_or(false); |
| 334 | if is_always { |
| 335 | always.push(def); |
| 336 | continue; |
| 337 | } |
| 338 | let group = group_for(def); |
| 339 | groups.entry(group).or_default().push(def); |
| 340 | } |
| 341 | |
| 342 | println!("Available tools — run `tracedecay tool <name> --help` for parameters, then"); |
| 343 | println!("invoke with `tracedecay tool <name> --args '<json>'` (the same JSON arguments"); |
| 344 | println!("object as the MCP tool; `--args -` reads a heredoc from stdin) or, for quick"); |
| 345 | println!("scalar calls, `--key value` flags.\n"); |
| 346 | |
| 347 | if !always.is_empty() { |
| 348 | println!("[always-loaded]"); |
| 349 | for def in &always { |
| 350 | println!( |
| 351 | " {:<32} {}", |
| 352 | short_tool_name(&def.name), |
| 353 | first_line(&def.description) |
| 354 | ); |
| 355 | } |
| 356 | println!(); |
| 357 | } |
| 358 | |
| 359 | for (group, mut list) in groups { |
| 360 | list.sort_by_key(|d| d.name.clone()); |
| 361 | println!("[{group}]"); |
| 362 | for def in list { |
| 363 | println!( |
| 364 | " {:<32} {}", |
| 365 | short_tool_name(&def.name), |
| 366 | first_line(&def.description) |
| 367 | ); |
| 368 | } |
| 369 | println!(); |
| 370 | } |
| 371 | |
| 372 | println!("{RESERVED_FLAGS_FOOTER}"); |
| 373 | } |
| 374 | |
| 375 | /// First line of a (possibly multi-line) description, truncated for layout. |
| 376 | fn first_line(s: &str) -> String { |