"""`agnes auth token` — manage personal access tokens (#12).""" import json as _json import re from typing import Optional import typer from cli.client import api_post, api_get, api_delete token_app = typer.Typer(help="Personal access tokens (long-lived CLI/CI auth)") def _parse_ttl(ttl: Optional[str]) -> Optional[int]: """Parse "30d", "90d", "365d", "never" → days (int) or None.""" if not ttl or ttl.lower() in ("never", "none", "no-expiry"): return None m = re.fullmatch(r"(\d+)d", ttl.lower().strip()) if not m: raise typer.BadParameter(f"Invalid TTL: {ttl}. Use e.g. 30d, 90d, 365d, or 'never'.") return int(m.group(1)) @token_app.command("create") def create( name: str = typer.Option(..., "--name", help="Human label for the token"), ttl: str = typer.Option("90d", "--ttl", help="Lifetime (e.g. 30d, 90d, 365d, never)"), raw: bool = typer.Option(False, "--raw", help="Print only the raw token (for CI)"), ): """Create a new personal access token.""" body = {"name": name, "expires_in_days": _parse_ttl(ttl)} resp = api_post("/auth/tokens", json=body) if resp.status_code != 201: typer.echo(f"Failed: {resp.json().get('detail', resp.text)}", err=True) raise typer.Exit(1) data = resp.json() if raw: typer.echo(data["token"]) return typer.echo("Personal access token created — this is shown ONCE:") typer.echo("") typer.echo(f" {data['token']}") typer.echo("") typer.echo(f"id: {data['id']}") typer.echo(f"name: {data['name']}") typer.echo(f"expires: {data.get('expires_at') or 'never'}") typer.echo("") typer.echo("Export it so `agnes` can use it:") typer.echo(f" export AGNES_TOKEN={data['token']}") @token_app.command("list") def list_tokens(as_json: bool = typer.Option(False, "--json")): """List your personal access tokens.""" resp = api_get("/auth/tokens") if resp.status_code != 200: typer.echo(f"Failed: {resp.json().get('detail', resp.text)}", err=True) raise typer.Exit(1) rows = resp.json() if as_json: typer.echo(_json.dumps(rows, indent=2)) return if not rows: typer.echo("No tokens yet. Create one with: agnes auth token create --name