///|
async fn main {
let matches = skills_command().parse(env=@env.get_env_vars())
let client = @client.Client(
registry=matches.values["registry"][0],
moon_home?=matches.values.get("moon-home").map(values => values[0]),
)
@async.with_timeout(120000, () => {
match matches.subcommand {
Some(("publish", args)) => {
let result = client.publish(
args.values["directory"][0],
args.values["version"][0],
)
println("Published \{result.owner}/\{result.name}@\{result.version}")
}
Some(("list", args)) => {
let skills = client.list()
if args.flags.get("json").unwrap_or(false) {
println(Json(skills).stringify())
} else {
for skill in skills {
println(
"\{skill.owner}/\{skill.name}@\{skill.version}\n \{skill.description}",
)
}
println("\{skills.length()} skills")
}
}
Some(("download", args)) => {
let result = client.download(
args.values["reference"][0],
output?=args.values.get("output").map(values => values[0]),
extract?=args.values.get("extract").map(values => values[0]),
)
let skill = result.skill
println(
"Downloaded \{skill.owner}/\{skill.name}@\{skill.version} to \{result.path}",
)
}
_ => ()
}
})
}
///|
fn skills_command() -> @argparse.Command {
Command(
"skills",
about="Publish, list and download Agent Skills on mooncakes.io.",
arg_required_else_help=true,
subcommand_required=true,
options=[
OptionArg(
"registry",
about="Registry origin (HTTP is supported for local development).",
env="SKILLS_REGISTRY",
default_values=["https://mooncakes.io"],
global=true,
),
OptionArg(
"moon-home",
about="Moon home directory containing credentials.json.",
env="MOON_HOME",
global=true,
),
],
subcommands=[
Command(
"publish",
about="Publish a complete skill directory as an immutable version.",
positionals=[
PositionArg(
"directory",
about="Skill directory with SKILL.md (name and description required).",
num_args=@argparse.ValueRange::single(),
),
],
options=[
OptionArg("version", about="Release version (SemVer).", required=true),
],
),
Command("list", about="List all published skills.", flags=[
FlagArg("json", about="Print the JSON response."),
]),
Command(
"download",
about="Download a skill and verify its SHA-256 checksum.",
positionals=[
PositionArg(
"reference",
about="OWNER/NAME[@VERSION]; defaults to the highest stable SemVer.",
num_args=@argparse.ValueRange::single(),
),
],
options=[
OptionArg(
"output",
about="Save the ZIP to a new file (default: NAME-VERSION.zip).",
conflicts_with=["extract"],
),
OptionArg("extract", about="Extract into this new directory."),
],
),
],
)
}