From d365b84885553971ead63a73471dba9c5c1ee268 Mon Sep 17 00:00:00 2001 From: aitbc Date: Tue, 26 May 2026 12:36:26 +0200 Subject: [PATCH] fix: add TTY handling for password prompts and config get alias - Fixed getpass TTY error by checking sys.stdin.isatty() before prompting - Added environment variable fallback for non-interactive environments (AITBC_WALLET_PASSWORD) - Added config get command as alias for show command - Wrapped getpass calls in try/except for better error handling - Fixes termios.error in non-interactive environments like CI/scripts --- cli/aitbc_cli/commands/config.py | 7 +++++++ cli/aitbc_cli/commands/wallet.py | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cli/aitbc_cli/commands/config.py b/cli/aitbc_cli/commands/config.py index 307f3f00..6876ffd5 100644 --- a/cli/aitbc_cli/commands/config.py +++ b/cli/aitbc_cli/commands/config.py @@ -34,6 +34,13 @@ def show(ctx): output(config_dict, ctx.obj['output_format']) +@config.command(name="get") +@click.pass_context +def get(ctx): + """Get current configuration (alias for show)""" + return ctx.invoke(show) + + @config.command() @click.argument("key") @click.argument("value") diff --git a/cli/aitbc_cli/commands/wallet.py b/cli/aitbc_cli/commands/wallet.py index 4f003be2..ae69d236 100644 --- a/cli/aitbc_cli/commands/wallet.py +++ b/cli/aitbc_cli/commands/wallet.py @@ -43,9 +43,28 @@ def _get_wallet_password(wallet_name: str) -> str: except Exception: pass + # Check if we're in a TTY environment + import sys + if not sys.stdin.isatty(): + # Non-interactive: try environment variable + password = os.environ.get(f"AITBC_WALLET_PASSWORD_{wallet_name.upper()}") + if password: + return password + # Try generic password env var + password = os.environ.get("AITBC_WALLET_PASSWORD") + if password: + return password + error("No TTY available for password prompt. Set AITBC_WALLET_PASSWORD environment variable.") + raise click.Abort() + # Prompt for password while True: - password = getpass.getpass(f"Enter password for wallet '{wallet_name}': ") + try: + password = getpass.getpass(f"Enter password for wallet '{wallet_name}': ") + except Exception as e: + error(f"Password prompt failed: {e}") + raise click.Abort() + if not password: error("Password cannot be empty") continue