Files
AIPass/src/aipass/drone/cli.py
T
AIOSAIandClaude Opus 4.6 866b0596aa feat(drone): rename routing → drone and add CLI entry point
BREAKING: aipass.routing renamed to aipass.drone. Routing IS drone —
the command routing engine IS the CLI command center. No reason to
keep them separate.

Adds `drone` CLI entry point:
  drone systems          — list registered branches
  drone @branch command  — route command to branch
  drone @branch --help   — get branch help
  drone --version        — show version

406 tests pass (20 new CLI tests). All imports updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:14:32 -08:00

136 lines
3.6 KiB
Python

"""
Drone CLI — command-line interface for aipass.drone.
Entry point: `drone` (wired via pyproject.toml console_scripts to cli.main).
Usage:
drone Show available commands
drone --help Show help
drone --version Show version
drone systems List registered branches
drone @branch command [args] Route command to branch
drone @branch --help Show help for branch
Zero external dependencies — stdlib only (sys).
"""
from __future__ import annotations
import sys
import aipass
from aipass.drone import (
CommandExecutionError,
BranchNotFoundError,
get_help,
list_branches,
route_command,
)
_HELP_TEXT = """\
drone — AIPass branch command router
Usage:
drone Show this help
drone --help Show this help
drone --version Show version
drone systems List registered branches
drone @branch command [args] Route command to branch
drone @branch --help Show help for branch
Examples:
drone systems
drone @flow status
drone @flow run --verbose
drone @flow --help
"""
def main() -> None:
"""Entry point for the `drone` CLI command.
Parses sys.argv manually and dispatches to the appropriate handler.
Exits with the command's exit code on branch commands, 0 on success,
1 on error.
"""
args = sys.argv[1:]
# No args or explicit --help
if not args or args == ["--help"]:
print(_HELP_TEXT, end="")
sys.exit(0)
# --version
if args == ["--version"]:
print(aipass.__version__)
sys.exit(0)
# systems — list registered branches
if args[0] == "systems":
_cmd_systems()
return
# @branch ... — route to a branch
if args[0].startswith("@"):
_cmd_branch(args)
return
# Unknown command
print(f"drone: unknown command '{args[0]}'", file=sys.stderr)
print("Run 'drone --help' for usage.", file=sys.stderr)
sys.exit(1)
def _cmd_systems() -> None:
"""Handle `drone systems` — list registered branches."""
branches = list_branches()
if not branches:
print("No branches registered.")
sys.exit(0)
print(f"Registered branches ({len(branches)}):")
for name in sorted(branches):
print(f" {name}")
sys.exit(0)
def _cmd_branch(args: list[str]) -> None:
"""Handle `drone @branch command [args]` or `drone @branch --help`."""
target = args[0]
rest = args[1:]
# drone @branch --help
if not rest or rest == ["--help"]:
try:
result = get_help(target)
if result.text:
print(result.text, end="")
else:
print(f"No help available for {target}.")
except BranchNotFoundError as exc:
print(f"drone: {exc}", file=sys.stderr)
sys.exit(1)
except CommandExecutionError as exc:
print(f"drone: {exc}", file=sys.stderr)
sys.exit(1)
sys.exit(0)
# drone @branch command [args...]
command = rest[0]
cmd_args = rest[1:]
try:
result = route_command(target, command, args=cmd_args if cmd_args else None)
except BranchNotFoundError as exc:
print(f"drone: {exc}", file=sys.stderr)
sys.exit(1)
except CommandExecutionError as exc:
print(f"drone: {exc}", file=sys.stderr)
sys.exit(1)
if result.stdout:
print(result.stdout, end="")
if result.stderr:
print(result.stderr, end="", file=sys.stderr)
sys.exit(result.exit_code)