use clap::{Parser, Subcommand};
use std::path::PathBuf;
mod skills {
include!(concat!(env!("OUT_DIR"), "/skills.rs"));
pub fn get(name: &str) -> Option<&'static str> {
SKILL_DIRS.iter().find(|s| s.name == name).map(|s| s.body)
}
}
#[derive(Parser, Debug)]
#[command(
name = "dial9",
about = "Trace browser and viewer for dial9-tokio-telemetry"
)]
pub struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
Agents {
#[command(subcommand)]
action: Option<AgentsAction>,
},
Serve {
#[arg(long, default_value = "3000")]
port: u16,
#[arg(long)]
bucket: Option<String>,
#[arg(long)]
prefix: Option<String>,
#[arg(long, conflicts_with = "bucket")]
local_dir: Option<PathBuf>,
#[arg(long)]
dev: bool,
},
}
#[derive(Subcommand, Debug)]
enum AgentsAction {
Toolkit {
path: PathBuf,
},
Skill {
name: String,
},
Skills {
path: PathBuf,
},
}
pub async fn run() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Commands::Agents { action } => match action {
None => print!("{}", skills::HEADER),
Some(AgentsAction::Toolkit { path }) => {
std::fs::create_dir_all(&path)?;
for (name, content) in skills::TOOLKIT_FILES {
std::fs::write(path.join(name), content)?;
}
let abs = std::fs::canonicalize(&path)?;
eprintln!("Toolkit written to {}", abs.display());
eprintln!(
"Run: node {}/analyze.js <trace.bin or directory>",
abs.display()
);
}
Some(AgentsAction::Skill { name }) => match skills::get(&name) {
Some(content) => print!("{}", content),
None => {
eprintln!("Unknown skill: {name}");
eprintln!("Available skills:");
for skill in skills::SKILL_DIRS {
eprintln!(" {:24} {}", skill.name, skill.description);
}
std::process::exit(1);
}
},
Some(AgentsAction::Skills { path }) => {
for skill in skills::SKILL_DIRS {
let skill_dir = path.join(skill.name);
for (rel_path, content) in skill.files {
let file_path = skill_dir.join(rel_path);
if let Some(parent) = file_path.parent() {
std::fs::create_dir_all(parent)?;
}
std::fs::write(&file_path, content)?;
}
}
let abs = std::fs::canonicalize(&path)?;
eprintln!("Skills unpacked to {}", abs.display());
eprintln!("Add to .kiro/skills/ or point your agent at this directory.");
}
},
Commands::Serve {
port,
bucket,
prefix,
local_dir,
dev,
} => {
return crate::serve(port, bucket, prefix, local_dir, dev).await;
}
}
Ok(())
}