From b9522e0a4d13ab47a99b9b3d6485b9356ca42d35 Mon Sep 17 00:00:00 2001 From: chengyongru Date: Fri, 15 May 2026 13:33:12 +0800 Subject: [PATCH] refactor(pairing): remove redundant CLI commands CLI pairing commands (list/approve/deny/revoke) are fully replaceable by `nanobot agent -m "/pairing ..."`, which routes through the same CommandRouter and handle_pairing_command() backend. Removing them cuts 86 lines of duplicate surface area without losing any functionality. - Remove pairing_app and its 4 subcommands from cli/commands.py - Update format_pairing_reply() to drop the "Via CLI" line --- nanobot/cli/commands.py | 86 ---------------------------------------- nanobot/pairing/store.py | 3 +- 2 files changed, 1 insertion(+), 88 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index d072877bf..e02653bf9 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -1620,91 +1620,5 @@ def _login_github_copilot() -> None: raise typer.Exit(1) -# ============================================================================ -# Pairing Commands -# ============================================================================ - -pairing_app = typer.Typer(help="Manage DM pairing approvals") -app.add_typer(pairing_app, name="pairing") - - -@pairing_app.command("list") -def pairing_list(): - """Show pending pairing requests.""" - from nanobot.pairing import format_expiry, list_pending - - pending = list_pending() - if not pending: - console.print("[dim]No pending pairing requests.[/dim]") - return - - table = Table(title="Pending Pairing Requests") - table.add_column("Code", style="cyan") - table.add_column("Channel", style="magenta") - table.add_column("Sender ID", style="yellow") - table.add_column("Expires", style="green") - - for item in pending: - expiry = format_expiry(item.get("expires_at", 0)) - table.add_row( - item["code"], - item["channel"], - item["sender_id"], - expiry, - ) - - console.print(table) - - -@pairing_app.command("approve") -def pairing_approve( - code: str = typer.Argument(..., help="Pairing code to approve"), -): - """Approve a pending pairing code.""" - from nanobot.pairing import approve_code - - result = approve_code(code) - if result is None: - console.print(f"[red]✗[/red] Invalid or expired pairing code: {code}") - raise typer.Exit(1) - - channel, sender_id = result - console.print( - f"[green]✓[/green] Approved pairing code {code} — " - f"{sender_id} can now access {channel}" - ) - - -@pairing_app.command("deny") -def pairing_deny( - code: str = typer.Argument(..., help="Pairing code to deny"), -): - """Deny and discard a pending pairing code.""" - from nanobot.pairing import deny_code - - if deny_code(code): - console.print(f"[green]✓[/green] Denied pairing code {code}") - else: - console.print(f"[yellow]! Pairing code {code} not found or already expired[/yellow]") - - -@pairing_app.command("revoke") -def pairing_revoke( - channel: str = typer.Argument(..., help="Channel name (e.g. telegram)"), - user_id: str = typer.Argument(..., help="User ID to revoke"), -): - """Revoke an approved sender from a channel.""" - from nanobot.pairing import revoke - - if revoke(channel, user_id): - console.print( - f"[green]✓[/green] Revoked {user_id} from {channel}" - ) - else: - console.print( - f"[yellow]! {user_id} was not in the approved list for {channel}[/yellow]" - ) - - if __name__ == "__main__": app() diff --git a/nanobot/pairing/store.py b/nanobot/pairing/store.py index 78e041612..5ca9c629e 100644 --- a/nanobot/pairing/store.py +++ b/nanobot/pairing/store.py @@ -187,8 +187,7 @@ def format_pairing_reply(code: str) -> str: "Hi there! This assistant only responds to approved users.\n\n" f"Your pairing code is: `{code}`\n\n" "To get access, ask the owner to approve this code:\n" - f"- In this chat: send `/pairing approve {code}`\n" - f"- Via CLI: run `nanobot pairing approve {code}`" + f"- In this chat: send `/pairing approve {code}`" )