use std::path::PathBuf;
use anyhow::Result;
use clap::{Args, Subcommand, ValueEnum};
pub use claudex::filter::ResolvedFilter;
use claudex::filter::{ProviderKind, parse_when};
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ProviderArg {
Claude,
Codex,
#[value(name = "openclaw")]
OpenClaw,
Pi,
}
impl From<ProviderArg> for ProviderKind {
fn from(provider: ProviderArg) -> Self {
match provider {
ProviderArg::Claude => ProviderKind::Claude,
ProviderArg::Codex => ProviderKind::Codex,
ProviderArg::OpenClaw => ProviderKind::OpenClaw,
ProviderArg::Pi => ProviderKind::Pi,
}
}
}
#[derive(Args, Clone, Debug, Default)]
pub struct FilterArgs {
#[arg(long, value_enum, value_delimiter = ',')]
pub provider: Vec<ProviderArg>,
#[arg(long)]
pub model: Option<String>,
#[arg(long, value_parser = validate_when_arg)]
pub since: Option<String>,
#[arg(long, value_parser = validate_when_arg)]
pub until: Option<String>,
#[arg(long)]
pub on_disk_only: bool,
}
impl FilterArgs {
pub fn resolve(&self) -> Result<ResolvedFilter> {
let mut providers: Vec<String> = self
.provider
.iter()
.map(|p| ProviderKind::from(*p).id().to_string())
.collect();
providers.sort();
providers.dedup();
Ok(ResolvedFilter {
providers,
model: self.model.clone(),
since_ms: self
.since
.as_deref()
.map(|s| parse_when(s, false))
.transpose()?,
until_ms: self
.until
.as_deref()
.map(|s| parse_when(s, true))
.transpose()?,
on_disk_only: self.on_disk_only,
})
}
}
#[derive(Subcommand, Debug)]
pub enum SkillCommand {
#[command(after_long_help = crate::cli_help::SKILLS_GENERATE_EXAMPLES)]
Generate(SkillArgs),
#[command(after_long_help = crate::cli_help::SKILLS_INSTALL_EXAMPLES)]
Install(SkillArgs),
}
#[derive(Args, Debug, Clone)]
pub struct SkillArgs {
#[arg(long, value_enum, value_delimiter = ',', default_value = "all")]
pub target: Vec<SkillTarget>,
#[arg(long)]
pub dir: Option<PathBuf>,
#[arg(long)]
pub global: bool,
#[arg(long)]
pub force: bool,
#[arg(long)]
pub json: bool,
}
#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
pub enum SkillTarget {
ClaudeCode,
Codex,
Pi,
#[value(name = "openclaw")]
OpenClaw,
AgentsMd,
Plugin,
All,
}
pub fn validate_when_arg(value: &str) -> std::result::Result<String, String> {
parse_when(value, false)
.map(|_| value.to_string())
.map_err(|e| e.to_string())
}