use crate::activity::ActivityStateValue;
use clap::{Args, Command, CommandFactory, Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "agent-id",
version,
about = "Portable identity registry for coding-agent sessions",
long_about = "agent-id assigns permanent human-readable names to stable agent-harness session IDs."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Debug, Subcommand)]
pub enum Commands {
Register(RegisterArgs),
Lookup(LookupArgs),
Current(CurrentArgs),
Annotate(AnnotateArgs),
Discover(DiscoverArgs),
Prune(PruneArgs),
Prime(PrimeArgs),
}
#[derive(Debug, Args)]
pub struct CurrentArgs {
#[arg(long)]
pub json: bool,
}
#[derive(Debug, Args)]
pub struct RegisterArgs {
#[arg(value_name = "SESSION_ID", conflicts_with = "session_id")]
pub session: Option<String>,
#[arg(long = "session-id", value_name = "ID")]
pub session_id: Option<String>,
#[arg(long, value_name = "NAME")]
pub family: Option<String>,
#[arg(long, value_name = "NAME")]
pub realm: Option<String>,
#[arg(long)]
pub json: bool,
}
impl RegisterArgs {
pub fn explicit_session(&self) -> Option<&str> {
self.session.as_deref().or(self.session_id.as_deref())
}
}
#[derive(Debug, Args)]
pub struct LookupArgs {
#[arg(value_name = "IDENTIFIER", conflicts_with = "session_id")]
pub input: Option<String>,
#[arg(long = "session-id", value_name = "ID")]
pub session_id: Option<String>,
#[arg(long)]
pub json: bool,
}
impl LookupArgs {
pub fn explicit_input(&self) -> Option<&str> {
self.input.as_deref().or(self.session_id.as_deref())
}
}
#[derive(Debug, Args)]
pub struct AnnotateArgs {
#[arg(value_name = "SESSION_ID", conflicts_with = "session_id")]
pub session: Option<String>,
#[arg(long = "session-id", value_name = "ID")]
pub session_id: Option<String>,
#[arg(long, value_name = "TEXT", conflicts_with = "clear_summary")]
pub summary: Option<String>,
#[arg(long, conflicts_with = "summary")]
pub clear_summary: bool,
#[arg(long, value_name = "VALUE", conflicts_with = "clear_state")]
pub state: Option<ActivityStateValue>,
#[arg(long, conflicts_with = "state")]
pub clear_state: bool,
#[arg(long, value_name = "PATH", conflicts_with = "clear_cwd")]
pub cwd: Option<String>,
#[arg(long, conflicts_with = "cwd")]
pub clear_cwd: bool,
#[arg(long = "extension", value_name = "OWNER=JSON")]
pub extensions: Vec<String>,
#[arg(long = "clear-extension", value_name = "OWNER")]
pub clear_extensions: Vec<String>,
#[arg(long)]
pub json: bool,
}
impl AnnotateArgs {
pub fn explicit_session(&self) -> Option<&str> {
self.session.as_deref().or(self.session_id.as_deref())
}
}
#[derive(Debug, Args)]
#[command(
about = "Find identity assignments for related work",
after_help = "Neighbor selection: prefer an agent whose current work is related to the request. Do not contact arbitrary agents merely because they are idle or discoverable. If no suitable neighbor is apparent, do not broadcast; ask the user or report that no suitable neighbor was found. An explicit recipient chosen by the user takes precedence."
)]
pub struct DiscoverArgs {
#[arg(long, default_value_t = 20)]
pub limit: usize,
#[arg(long, value_name = "HOURS")]
pub recent: Option<i64>,
#[arg(long, value_name = "NAME")]
pub realm: Option<String>,
#[arg(long)]
pub all: bool,
#[arg(long)]
pub json: bool,
}
#[derive(Debug, Args)]
pub struct PruneArgs {
#[arg(long, value_name = "TIMESTAMP", required = true)]
pub before: String,
#[arg(long)]
pub dry_run: bool,
#[arg(long)]
pub json: bool,
}
#[derive(Debug, Args)]
#[command(about = "Output the agent-facing identity workflow manual")]
pub struct PrimeArgs {
#[arg(long)]
pub prelude: bool,
#[arg(long)]
pub json: bool,
}
pub fn build_cli() -> Command {
Cli::command()
}