fix(api): render 4 module --help functions in Rich (caught by tightened CLI checker)

The CLI help-checker fix (4d41065) immediately surfaced the same
console.print(parser.format_help()) laundering in 4 @api modules on its first
audit run — exactly the latent stragglers the static-scan loophole had been
hiding. Rewrote each print_help() to hand-rolled Rich markup (content was
already in the argparse epilogs); removed the help-only argparse parsers.

- api_key.py, usage_tracker.py, google_client.py, openrouter_client.py
- @api audit Cli + Overall back to 100% (38/38), 504 tests pass, no bypass

DPLAN-0217 (follow-on).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QEQZXCtgnF3NQtcttTErpq
This commit is contained in:
AIOSAI
2026-06-24 12:26:34 -07:00
co-authored by Claude Opus 4.8
parent 4d4106505f
commit 57767cc2a9
5 changed files with 139 additions and 204 deletions
+3 -1
View File
@@ -24,7 +24,9 @@ PyPI version — not the changelog header.
`print_help()`, +2 regression tests. Also rewrote `@ai_mail`'s `print_help()`
to render hand-rolled Rich (the `--help` content was complete, just unstyled).
A behavioral `--help` check (run it, assert not raw argparse) is noted as a
follow-up. (DPLAN-0217)
follow-up. (DPLAN-0217) On its first CI run the tightened checker immediately
surfaced the same pattern in 4 `@api` modules (`api_key`, `usage_tracker`,
`google_client`, `openrouter_client`) — migrated to Rich, `@api` back to 100%.
- **seedgo `readme_check` ignored the `(disabled)` marker in self-scans** — its
module-list and test-count scans now skip `foo(disabled).py`, matching the
central audit collector. An in-place disabled module no longer trips a false
+42 -49
View File
@@ -250,55 +250,48 @@ def get_validation_rules(provider: str) -> dict:
def print_help():
"""Print help output for API key management"""
import argparse
parser = argparse.ArgumentParser(
prog="drone @api",
description="API Key Management Module - Manage API keys and credentials",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
COMMANDS:
get-key - Retrieve API key for a provider
get-secret - Read secret from provider store
validate - Validate API key
list-providers - List available providers
init - Initialize .env template
USAGE:
drone @api <command> [args]
drone @api --help
EXAMPLES:
# Get key for provider
drone @api get-key openrouter
# Check if a secret exists (masked summary, no raw value)
drone @api get-secret telegram/bot
# Write secret to a protected file
drone @api get-secret telegram/bot --out /tmp/token.txt
# Write secret as JSON to a protected file
drone @api get-secret telegram/bot --out /tmp/bot.json --json
# List secrets for a provider
drone @api get-secret telegram --list
# Programmatic access (in-process, no stdout):
# from aipass.api.apps.modules.secrets import get_secret
# Validate key
drone @api validate openrouter
# List providers
drone @api list-providers
# Initialize environment
drone @api init
""",
)
console.print(parser.format_help())
"""Print drone-compliant help output with Rich markup"""
console.print()
console.print("[bold cyan]API_KEY — Manage API keys and credentials[/bold cyan]")
console.print()
console.print("[yellow]COMMANDS:[/yellow]")
console.print(" [cyan]get-key[/cyan] [dim]Retrieve API key for a provider[/dim]")
console.print(" [cyan]get-secret[/cyan] [dim]Read secret from provider store[/dim]")
console.print(" [cyan]validate[/cyan] [dim]Validate API key[/dim]")
console.print(" [cyan]list-providers[/cyan] [dim]List available providers[/dim]")
console.print(" [cyan]init[/cyan] [dim]Initialize .env template[/dim]")
console.print()
console.print("[yellow]USAGE:[/yellow]")
console.print(" [cyan]drone @api[/cyan] <command> [args]")
console.print(" [cyan]drone @api[/cyan] --help")
console.print()
console.print("[yellow]EXAMPLES:[/yellow]")
console.print(" [cyan]drone @api get-key openrouter[/cyan]")
console.print()
console.print(" [dim]# Check if a secret exists (masked summary, no raw value)[/dim]")
console.print(" [cyan]drone @api get-secret telegram/bot[/cyan]")
console.print()
console.print(" [dim]# Write secret to a protected file[/dim]")
console.print(" [cyan]drone @api get-secret telegram/bot --out /tmp/token.txt[/cyan]")
console.print()
console.print(" [dim]# Write secret as JSON to a protected file[/dim]")
console.print(" [cyan]drone @api get-secret telegram/bot --out /tmp/bot.json --json[/cyan]")
console.print()
console.print(" [dim]# List secrets for a provider[/dim]")
console.print(" [cyan]drone @api get-secret telegram --list[/cyan]")
console.print()
console.print(" [dim]# Programmatic access (in-process, no stdout):[/dim]")
console.print(" [dim]from aipass.api.apps.modules.secrets import get_secret[/dim]")
console.print()
console.print(" [dim]# Validate key[/dim]")
console.print(" [cyan]drone @api validate openrouter[/cyan]")
console.print()
console.print(" [dim]# List providers[/dim]")
console.print(" [cyan]drone @api list-providers[/cyan]")
console.print()
console.print(" [dim]# Initialize environment[/dim]")
console.print(" [cyan]drone @api init[/cyan]")
console.print()
if __name__ == "__main__":
+19 -25
View File
@@ -82,31 +82,25 @@ def print_introspection() -> None:
def print_help() -> None:
"""Print module help."""
import argparse
parser = argparse.ArgumentParser(
prog="drone @api",
description="Google Client - Google API authentication and service access",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
COMMANDS (via drone @api):
validate google - Check Google OAuth2 credentials
reauth google - Re-run OAuth2 flow for Google
CROSS-BRANCH API:
from aipass.api.apps.modules.google_client import get_drive_service
service = get_drive_service()
CREDENTIAL SETUP:
1. Get OAuth client secret from Google Cloud Console
2. Save as: ~/.secrets/aipass/google_client_secret.json
3. Run: drone @api reauth google
4. Complete OAuth consent in browser
5. Credentials saved to: ~/.secrets/aipass/google_creds.json
""",
)
console.print(parser.format_help())
"""Print drone-compliant help output with Rich markup"""
console.print()
console.print("[bold cyan]GOOGLE_CLIENT — Google API authentication and service access[/bold cyan]")
console.print()
console.print("[yellow]COMMANDS:[/yellow] [dim](via drone @api)[/dim]")
console.print(" [cyan]validate google[/cyan] [dim]Check Google OAuth2 credentials[/dim]")
console.print(" [cyan]reauth google[/cyan] [dim]Re-run OAuth2 flow for Google[/dim]")
console.print()
console.print("[yellow]CROSS-BRANCH API:[/yellow]")
console.print(" [dim]from aipass.api.apps.modules.google_client import get_drive_service[/dim]")
console.print(" [dim]service = get_drive_service()[/dim]")
console.print()
console.print("[yellow]CREDENTIAL SETUP:[/yellow]")
console.print(" [dim]1.[/dim] Get OAuth client secret from Google Cloud Console")
console.print(" [dim]2.[/dim] Save as: [cyan]~/.secrets/aipass/google_client_secret.json[/cyan]")
console.print(" [dim]3.[/dim] Run: [cyan]drone @api reauth google[/cyan]")
console.print(" [dim]4.[/dim] Complete OAuth consent in browser")
console.print(" [dim]5.[/dim] Credentials saved to: [cyan]~/.secrets/aipass/google_creds.json[/cyan]")
console.print()
# =============================================
@@ -52,62 +52,39 @@ def print_introspection():
def print_help():
"""Print module help with argparse"""
import argparse
parser = argparse.ArgumentParser(
prog="drone @api",
description="OpenRouter Client - Manage LLM API connections",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
COMMANDS:
test - Test OpenRouter connection
call - Make API call to model
models - List available models
status - Check connection status
USAGE:
drone @api test
drone @api call <prompt> [--model MODEL]
drone @api models
drone @api status
ARGUMENTS:
prompt - Prompt to send to the model
--model - Model to use (optional)
EXAMPLES:
# Test OpenRouter connection
drone @api test
# Make an API call
drone @api call "What is AI?" --model gpt-4
# List available models
drone @api models
# Check connection status
drone @api status
""",
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")
# test command
subparsers.add_parser("test", help="Test OpenRouter connection")
# call command
call_parser = subparsers.add_parser("call", help="Make API call to model")
call_parser.add_argument("prompt", help="Prompt to send")
call_parser.add_argument("--model", help="Model to use")
# models command
subparsers.add_parser("models", help="List available models")
# status command
subparsers.add_parser("status", help="Check connection status")
console.print(parser.format_help())
"""Print drone-compliant help output with Rich markup"""
console.print()
console.print("[bold cyan]OPENROUTER_CLIENT — Manage LLM API connections[/bold cyan]")
console.print()
console.print("[yellow]COMMANDS:[/yellow]")
console.print(" [cyan]test[/cyan] [dim]Test OpenRouter connection[/dim]")
console.print(" [cyan]call[/cyan] [dim]Make API call to model[/dim]")
console.print(" [cyan]models[/cyan] [dim]List available models[/dim]")
console.print(" [cyan]status[/cyan] [dim]Check connection status[/dim]")
console.print()
console.print("[yellow]USAGE:[/yellow]")
console.print(" [cyan]drone @api test[/cyan]")
console.print(" [cyan]drone @api call[/cyan] <prompt> [--model MODEL]")
console.print(" [cyan]drone @api models[/cyan]")
console.print(" [cyan]drone @api status[/cyan]")
console.print()
console.print("[yellow]ARGUMENTS:[/yellow]")
console.print(" [cyan]prompt[/cyan] [dim]Prompt to send to the model[/dim]")
console.print(" [cyan]--model[/cyan] [dim]Model to use (optional)[/dim]")
console.print()
console.print("[yellow]EXAMPLES:[/yellow]")
console.print(" [dim]# Test OpenRouter connection[/dim]")
console.print(" [cyan]drone @api test[/cyan]")
console.print()
console.print(" [dim]# Make an API call[/dim]")
console.print(' [cyan]drone @api call "What is AI?" --model gpt-4[/cyan]')
console.print()
console.print(" [dim]# List available models[/dim]")
console.print(" [cyan]drone @api models[/cyan]")
console.print()
console.print(" [dim]# Check connection status[/dim]")
console.print(" [cyan]drone @api status[/cyan]")
console.print()
def handle_command(command: str, args: List[str]) -> bool:
+42 -73
View File
@@ -53,76 +53,44 @@ def print_introspection():
def print_help():
"""Print module help with argparse"""
import argparse
parser = argparse.ArgumentParser(
prog="drone @api",
description="Usage Tracker - Monitor API usage and costs",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
COMMANDS:
track - Track API usage
stats - Show usage statistics
session - Show session data
caller-usage - Show usage by caller
cleanup - Clean up old usage data
USAGE:
drone @api track <caller>
drone @api stats
drone @api session
drone @api caller-usage <caller>
drone @api cleanup [days]
ARGUMENTS:
caller - Caller identifier
days - Number of days to retain (default: 30)
EXAMPLES:
# Track usage for a caller
drone @api track my_application
# Show usage statistics
drone @api stats
# Show session data
drone @api session
# Show usage for specific caller
drone @api caller-usage my_application
# Cleanup data older than 60 days
drone @api cleanup 60
""",
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")
# track command
track_parser = subparsers.add_parser("track", help="Track API usage")
track_parser.add_argument("caller", help="Caller identifier")
# stats command
subparsers.add_parser("stats", help="Show usage statistics")
# session command
subparsers.add_parser("session", help="Show session data")
# caller-usage command
caller_parser = subparsers.add_parser("caller-usage", help="Show usage by caller")
caller_parser.add_argument("caller", help="Caller identifier")
# cleanup command
cleanup_parser = subparsers.add_parser("cleanup", help="Clean up old usage data")
cleanup_parser.add_argument(
"days",
nargs="?",
default=str(DEFAULT_RETENTION_DAYS),
help=f"Days to retain (default: {DEFAULT_RETENTION_DAYS})",
)
console.print(parser.format_help())
"""Print drone-compliant help output with Rich markup"""
console.print()
console.print("[bold cyan]USAGE_TRACKER — Monitor API usage and costs[/bold cyan]")
console.print()
console.print("[yellow]COMMANDS:[/yellow]")
console.print(" [cyan]track[/cyan] [dim]Track API usage[/dim]")
console.print(" [cyan]stats[/cyan] [dim]Show usage statistics[/dim]")
console.print(" [cyan]session[/cyan] [dim]Show session data[/dim]")
console.print(" [cyan]caller-usage[/cyan] [dim]Show usage by caller[/dim]")
console.print(" [cyan]cleanup[/cyan] [dim]Clean up old usage data[/dim]")
console.print()
console.print("[yellow]USAGE:[/yellow]")
console.print(" [cyan]drone @api track[/cyan] <caller>")
console.print(" [cyan]drone @api stats[/cyan]")
console.print(" [cyan]drone @api session[/cyan]")
console.print(" [cyan]drone @api caller-usage[/cyan] <caller>")
console.print(" [cyan]drone @api cleanup[/cyan] [days]")
console.print()
console.print("[yellow]ARGUMENTS:[/yellow]")
console.print(" [cyan]caller[/cyan] [dim]Caller identifier[/dim]")
console.print(" [cyan]days[/cyan] [dim]Number of days to retain (default: 30)[/dim]")
console.print()
console.print("[yellow]EXAMPLES:[/yellow]")
console.print(" [dim]# Track usage for a caller[/dim]")
console.print(" [cyan]drone @api track my_application[/cyan]")
console.print()
console.print(" [dim]# Show usage statistics[/dim]")
console.print(" [cyan]drone @api stats[/cyan]")
console.print()
console.print(" [dim]# Show session data[/dim]")
console.print(" [cyan]drone @api session[/cyan]")
console.print()
console.print(" [dim]# Show usage for specific caller[/dim]")
console.print(" [cyan]drone @api caller-usage my_application[/cyan]")
console.print()
console.print(" [dim]# Cleanup data older than 60 days[/dim]")
console.print(" [cyan]drone @api cleanup 60[/cyan]")
console.print()
def handle_command(command: str, args: List[str]) -> bool:
@@ -194,9 +162,10 @@ def track_usage(args: List[str]):
if result.get("success"):
metrics = result.get("metrics", {})
success(
f"Tracked: {metrics.get('tokens_prompt', 0)} prompt + {metrics.get('tokens_completion', 0)} completion tokens, ${metrics.get('total_cost', 0):.6f}"
)
prompt_t = metrics.get("tokens_prompt", 0)
comp_t = metrics.get("tokens_completion", 0)
cost = metrics.get("total_cost", 0)
success(f"Tracked: {prompt_t} prompt + {comp_t} completion tokens, ${cost:.6f}")
else:
error(f"Tracking failed: {result.get('error', 'unknown')}")