#![expect(dead_code, reason = "example data types are reflected rather than executed")]
use clap::{Args, Parser, Subcommand};
use clap_schema::{CliSchema, CommandSchema, SchemaDocument, SchemaRequest, schema_handler};
use schemars::JsonSchema;
use serde::Serialize;
#[derive(Debug, Parser, CliSchema)]
#[command(name = "agentctl")]
struct Cli {
#[arg(long, global = true)]
json: bool,
#[command(subcommand)]
command: Commands,
}
#[derive(Debug, Subcommand, CommandSchema)]
enum Commands {
Get(GetArgs),
Schema(SchemaArgs),
}
#[derive(Debug, Args)]
struct GetArgs {
id: String,
}
#[derive(Debug, Args)]
struct SchemaArgs {
#[arg(long)]
full: bool,
path: Vec<String>,
}
#[derive(Debug, Serialize, JsonSchema)]
struct Resource {
id: String,
name: String,
}
#[schema_handler(GetArgs)]
fn get(command: GetArgs) -> Result<Resource, std::io::Error> {
Ok(Resource { id: command.id, name: "Example resource".to_owned() })
}
#[schema_handler(SchemaArgs)]
fn schema(command: SchemaArgs) -> Result<SchemaDocument, clap_schema::Error> {
let request = SchemaRequest::new(command.path).with_full(command.full);
Cli::schema()?.schema(&request)
}
fn print_schema(document: &SchemaDocument) -> Result<(), Box<dyn std::error::Error>> {
println!("{}", serde_json::to_string_pretty(document)?);
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = if std::env::args_os().len() == 1 {
Cli::parse_from(["agentctl", "schema"])
} else {
Cli::parse()
};
let Cli { json, command } = cli;
match command {
Commands::Schema(request) => {
let document = schema(request)?;
print_schema(&document)?;
}
Commands::Get(request) => {
let result = get(request);
let resource = result?;
if json {
serde_json::to_writer(std::io::stdout().lock(), &resource)?;
} else {
println!("{}: {}", resource.id, resource.name);
}
}
}
Ok(())
}