atman_runtime/tools/
help.rs1use crate::error::RuntimeError;
2use crate::help;
3use crate::tool::{BoxFut, Tier, Tool, ToolArgs, ToolCtx, ToolResult};
4use crate::value::Value;
5
6pub struct HelpShow;
7
8impl Tool for HelpShow {
9 fn name(&self) -> &str {
10 "help.show"
11 }
12
13 fn tier(&self) -> Tier {
14 Tier::Zero
15 }
16
17 fn description(&self) -> Option<&str> {
18 Some(
19 "Show built-in help documentation. Pass `topic` to get specific docs: \
20 'index' (default), 'tools', 'cli', 'config', 'mcp', 'dsl', 'features'. \
21 Content is version-synced — dynamic topics are generated from the live \
22 ToolRegistry and META_COMMANDS, config/mcp topics are read from /// doc \
23 comments via the documented crate. Returns markdown text.",
24 )
25 }
26
27 fn input_schema(&self) -> serde_json::Value {
28 serde_json::json!({
29 "type": "object",
30 "properties": {
31 "topic": {
32 "type": "string",
33 "default": "index",
34 "enum": ["index", "tools", "cli", "config", "mcp", "dsl", "features"],
35 "description": "Help topic to display. Defaults to 'index' (topic list)."
36 }
37 }
38 })
39 }
40
41 fn call<'a>(&'a self, args: ToolArgs, ctx: &'a ToolCtx) -> BoxFut<'a, ToolResult> {
42 Box::pin(async move {
43 let topic = match args.named("topic") {
44 Some(Value::Str(s)) => s.as_str().to_string(),
45 _ => "index".to_string(),
46 };
47 match help::topic_content(&topic, ctx) {
48 Some(content) => Ok(Value::Str(content)),
49 None => {
50 let available: Vec<&str> = help::TOPICS.iter().map(|t| t.id).collect();
51 Err(RuntimeError::ToolFailed(format!(
52 "unknown help topic '{topic}'. available: {}",
53 available.join(", ")
54 )))
55 }
56 }
57 })
58 }
59}