use std::fmt::Write;
use crate::capability::SkillCapability;
use crate::family::FamilyMeta;
use crate::skill::Skill;
use crate::validation::rules_to_json;
pub fn render_skill<S: 'static>(
skill: &dyn Skill<S>,
family: Option<&str>,
gating: Option<&str>,
) -> String {
let mut out = String::new();
let _ = writeln!(out, "Tool: {}", skill.name());
if let Some(f) = family {
let _ = writeln!(out, "Family: {f}");
}
if let Some(g) = gating {
let _ = writeln!(out, "{g}");
}
let _ = writeln!(out);
let _ = writeln!(out, "Description:");
let _ = writeln!(out, " {}", skill.description());
let use_cases = skill.use_cases();
if !use_cases.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, "Use cases:");
for uc in use_cases {
let _ = writeln!(out, " - {uc}");
}
}
let examples = skill.examples();
if !examples.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, "Examples:");
for (i, ex) in examples.iter().enumerate() {
let _ = writeln!(out, " {}. {}", i + 1, ex.title);
let _ = writeln!(out, " args: {}", ex.args);
if let Some(note) = ex.note {
let _ = writeln!(out, " note: {note}");
}
}
}
let rules = skill.validation_rules();
if !rules.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, "Validation rules:");
let rules_json = rules_to_json(rules);
let rules_pretty = serde_json::to_string_pretty(&rules_json)
.unwrap_or_else(|_| "<could not serialize rules>".into());
let _ = writeln!(out, "{rules_pretty}");
}
let schema_json = serde_json::to_value(skill.schema().as_ref())
.ok()
.and_then(|v| serde_json::to_string_pretty(&v).ok())
.unwrap_or_else(|| "<could not serialize schema>".into());
let _ = writeln!(out);
let _ = writeln!(out, "Argument schema (JSON):");
let _ = writeln!(out, "{schema_json}");
out
}
pub fn render_family(fam: &dyn FamilyMeta, gating: Option<&str>) -> String {
let mut out = String::new();
let _ = writeln!(out, "Family: {}", fam.family());
let _ = writeln!(out, "Description:");
let _ = writeln!(out, " {}", fam.description());
let cap_line = match fam.check_capability() {
SkillCapability::Ready => "Capability: Ready".to_string(),
SkillCapability::Unavailable { reason, hint } => {
let mut s = format!("Capability: Unavailable — {reason}");
if let Some(h) = hint {
s.push_str(&format!("\n Hint: {h}"));
}
s
}
};
let _ = writeln!(out, "{cap_line}");
if let Some(g) = gating {
let _ = writeln!(out, "{g}");
}
let tools = fam.tools();
let _ = writeln!(out);
let _ = writeln!(out, "Tools ({}):", tools.len());
for t in &tools {
let _ = writeln!(out, " - {t}");
}
if let Some(flow) = fam.example_flow() {
let _ = writeln!(out);
let _ = writeln!(out, "Example flow:");
for line in flow.lines() {
let _ = writeln!(out, " {line}");
}
}
out
}