diff --git a/hermes_cli/secrets_cli.py b/hermes_cli/secrets_cli.py index dc07681741..3b528899b0 100644 --- a/hermes_cli/secrets_cli.py +++ b/hermes_cli/secrets_cli.py @@ -59,9 +59,7 @@ def __getattr__(name: str): raise AttributeError(f"module {__name__!r} has no attribute {name!r}") -# --------------------------------------------------------------------------- -# Argparse wiring — called from hermes_cli.main -# --------------------------------------------------------------------------- +# ── Argparse wiring — called from hermes_cli.main ── def register_cli(parent_parser: argparse.ArgumentParser) -> None: @@ -92,9 +90,7 @@ def register_cli(parent_parser: argparse.ArgumentParser) -> None: )) -# --------------------------------------------------------------------------- -# Handlers -# --------------------------------------------------------------------------- +# ── Handlers ── def _step(console: Console, n: int, title: str) -> None: @@ -422,9 +418,7 @@ def cmd_install(args: argparse.Namespace) -> int: return 1 -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- +# ── Helpers ── def _token_validation_status( diff --git a/hermes_cli/send_cmd.py b/hermes_cli/send_cmd.py index fbad9cc143..49dea16a32 100644 --- a/hermes_cli/send_cmd.py +++ b/hermes_cli/send_cmd.py @@ -128,18 +128,15 @@ def _list_targets(platform_filter: Optional[str], *, json_mode: bool) -> int: return _SUCCESS_EXIT for plat_name in sorted(platforms): - channels = platforms[plat_name] print(f"{plat_name}:") - if not channels: + if not platforms[plat_name]: print(" (no channels discovered yet)") continue - for ch in channels: + for ch in platforms[plat_name]: name = ch.get("name", "?") chat_id = ch.get("id") or ch.get("chat_id") or "" - suffix = f" [{chat_id}]" if chat_id and chat_id != name else "" - print(f" {plat_name}:{name}{suffix}") + print(f" {plat_name}:{name}" + (f" [{chat_id}]" if chat_id and chat_id != name else "")) print() - return _SUCCESS_EXIT @@ -253,30 +250,18 @@ def cmd_send(args: argparse.Namespace) -> None: # (flags, add_argument kwargs) in --help order. _SEND_ARGUMENTS = ( - (("-t", "--to"), dict( - metavar="TARGET", - default=None, - help=( - "Delivery target. Format: 'platform' (home channel), " - "'platform:chat_id', 'platform:chat_id:thread_id', or " - "'platform:#channel-name'. Examples: telegram, " - "telegram:-1001234567890:17585, discord:#ops, slack:C0123ABCD, signal:+15551234567." - ), - )), + (("-t", "--to"), dict(metavar="TARGET", default=None, help=( + "Delivery target. Format: 'platform' (home channel), " + "'platform:chat_id', 'platform:chat_id:thread_id', or " + "'platform:#channel-name'. Examples: telegram, " + "telegram:-1001234567890:17585, discord:#ops, slack:C0123ABCD, signal:+15551234567."))), (("message",), dict(nargs="?", default=None, help="Message text. If omitted, read from --file or stdin.")), - (("-f", "--file"), dict( - metavar="PATH", - default=None, - help=( - "Read message body from PATH (text only). Use '-' to force stdin. " - "To send an image/document as an attachment, use MEDIA: in the message text instead." - ), - )), + (("-f", "--file"), dict(metavar="PATH", default=None, help=( + "Read message body from PATH (text only). Use '-' to force stdin. " + "To send an image/document as an attachment, use MEDIA: in the message text instead."))), (("-s", "--subject"), dict(metavar="LINE", default=None, help="Prepend a subject/header line before the message body.")), - (("-l", "--list"), dict( - dest="list_targets", action="store_true", default=False, - help="List available targets. Optional positional filter: `hermes send --list telegram`.", - )), + (("-l", "--list"), dict(dest="list_targets", action="store_true", default=False, + help="List available targets. Optional positional filter: `hermes send --list telegram`.")), (("-q", "--quiet"), dict(action="store_true", default=False, help="Suppress stdout on success (exit code only).")), (("--json",), dict(action="store_true", default=False, help="Emit raw JSON result instead of human-readable output.")), ) diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 292250a2c8..d3cd3a090a 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -718,13 +718,13 @@ def _run_full_setup(config: dict, hermes_home, *, is_existing: bool, migration_r _step("tools", "Tools", lambda: setup_tools(config, first_install=not is_existing))]) -# First-time mode picker: (menu label, runner) — a None runner falls through to Full Setup. +# First-time mode picker: (menu label, runner name on this module) — None falls through to Full +# Setup; runners resolve at call time so test patches on hermes_cli.setup apply. _FIRST_TIME_MODES = ( ("Quick Setup (Nous Portal) — free OAuth login, no API keys, model + tools (recommended)", - lambda *a: _run_first_time_quick_setup(*a)), + "_run_first_time_quick_setup"), ("Full setup — configure every provider, tool & option yourself (bring your own keys)", None), - ("Blank Slate — everything off except the bare minimum; opt in to each capability", - lambda *a: _run_blank_slate_setup(*a)), + ("Blank Slate — everything off except the bare minimum; opt in to each capability", "_run_blank_slate_setup"), ) @@ -794,7 +794,7 @@ def _run_setup_wizard_impl(args): setup_mode = prompt_choice("How would you like to set up Hermes?", [label for label, _ in _FIRST_TIME_MODES], 0) label, runner = _FIRST_TIME_MODES[setup_mode] if runner is not None: - _run_setup_steps([(label, lambda: runner(config, hermes_home, is_existing))]) + _run_setup_steps([(label, lambda: globals()[runner](config, hermes_home, is_existing))]) return _run_full_setup(config, hermes_home, is_existing=is_existing, migration_ran=migration_ran) diff --git a/hermes_cli/setup_quick.py b/hermes_cli/setup_quick.py index cb5f1d191b..ba8d32e32a 100644 --- a/hermes_cli/setup_quick.py +++ b/hermes_cli/setup_quick.py @@ -371,11 +371,8 @@ def _run_quick_setup(config: dict, hermes_home): if missing_tools: # checklist, then the API-key screen for each pick print_header("Tool API Keys", gap=True) - labels = [] - for var in missing_tools: - tools = var.get("tools", []) - tools_str = f" → {', '.join(tools[:2])}" if tools else "" - labels.append(f"{var.get('description', var['name'])}{tools_str}") + labels = [var.get("description", var["name"]) + (f" → {', '.join(var['tools'][:2])}" if var.get("tools") else "") + for var in missing_tools] for idx in prompt_checklist("Which tools would you like to configure?", labels): _prompt_api_key(missing_tools[idx]) @@ -387,11 +384,10 @@ def _run_quick_setup(config: dict, hermes_home): grouped: dict[str, list] = {} emojis = {} for var in missing_messaging: - for needle, plat, emoji in _MESSAGING_PLATFORMS: - if needle in var["name"]: - grouped.setdefault(plat, []).append(var) - emojis[plat] = emoji - break + match = next(((plat, emoji) for needle, plat, emoji in _MESSAGING_PLATFORMS if needle in var["name"]), None) + if match: + grouped.setdefault(match[0], []).append(var) + emojis[match[0]] = match[1] platform_order = list(grouped) labels = [f"{emojis[p]} {p}" for p in platform_order] for idx in prompt_checklist("Which platforms would you like to set up?", labels):