Files
hermes-agent/hermes_cli/subcommands/secrets.py
T
Teknium b81ab901f3 refactor(cli): extract the last 16 inline parser groups from main() into hermes_cli/subcommands/
moa, fallback, worktree, browser, secrets, egress, migrate, whatsapp-cloud,
checkpoints, bundles, curator, pets, journey, computer-use, sessions and
completion each become a build_<group>_parser() builder. Closure handlers
that only closed over their own parser moved verbatim; sessions/completion
take the handler by injection. --help/usage/defaults byte-identical for all
399 parsers in the tree (in-process dump before/after).
2026-09-02 13:29:44 -07:00

56 lines
2.1 KiB
Python

"""``hermes secrets`` subcommand parser.
Extracted from ``hermes_cli/main.py:main()`` (god-file Phase 2 follow-up).
Handlers are injected or imported lazily so this module never imports ``main``.
"""
from __future__ import annotations
def build_secrets_parser(subparsers) -> None:
"""Attach the ``secrets`` subcommand to ``subparsers``."""
secrets_parser = subparsers.add_parser(
"secrets",
help="Manage external secret sources (Bitwarden, 1Password)",
description=(
"Pull API keys from an external secret manager at process startup "
"instead of storing them in ~/.hermes/.env. Supports Bitwarden "
"Secrets Manager and 1Password. See: "
"https://hermes-agent.nousresearch.com/docs/user-guide/secrets/"
),
)
secrets_subparsers = secrets_parser.add_subparsers(dest="secrets_command")
secrets_bw = secrets_subparsers.add_parser(
"bitwarden",
aliases=["bw"],
help="Bitwarden Secrets Manager integration",
)
secrets_op = secrets_subparsers.add_parser(
"onepassword",
aliases=["op", "1password"],
help="1Password (op:// references) integration",
)
# Lazy-import secrets_cli: the module imports agent.secret_sources.bitwarden
# which loads cryptography._rust.pyd. On Windows this maps the native
# extension into the updater process, causing the self-lock preflight to
# defer (#86781). secrets_cli defers its backend import to first use
# (module-level __getattr__ + handler-level _load_bw()), so register_cli
# at parse time only wires argparse structure with no crypto cost.
from hermes_cli import secrets_cli as _secrets_cli
from hermes_cli import onepassword_secrets_cli as _op_secrets_cli
_secrets_cli.register_cli(secrets_bw)
_op_secrets_cli.register_cli(secrets_op)
def _dispatch_secrets(args): # noqa: ANN001
sub = getattr(args, "secrets_command", None)
if sub is None:
secrets_parser.print_help()
return 0
return args.func(args)
secrets_parser.set_defaults(func=_dispatch_secrets)