Files
Teknium a070a5be33 refactor(health): offset FILE_LINES growth by moving cohesive groups into topical siblings
main's ratchet caps every >2000-line facade at its main value; the PR grew seven.

- config.py: `hermes config show` rendering -> hermes_cli/config_show.py (reads config names via
  the module at call time so hermes_cli.config.<name> patch seams hold).
- backup.py: the cron prompt-field safety net -> hermes_cli/backup_cron_prompts.py; also drops a
  dead duplicate _PROTECTED_CONFIG_PATHS left by an earlier merge (the later definition won).
  restore_config_model_settings_* stay in backup: they are on the frozen old-updater surface.
- profiles.py: Honcho host migration on rename -> hermes_cli/profiles_honcho.py.
- plugins.py: resolve_plugin_command_result -> plugins_dispatch.py (re-exported from plugins,
  the public import path for cli/tui_gateway/plugins).
- main.py: --query-file reader -> hermes_cli/main_query_file.py.
- kanban_db.py: worker-context section renderers (_ctx_* + caps) -> hermes_cli/kanban_db_context.py;
  build_worker_context stays in kanban_db.
- config_defaults.py: drop the blank line the gateway block gained.

Patch-target retargets (moved symbols only): test_plugins.py (asyncio / await timeout now in
plugins_dispatch), test_managed_scope_surfacing.py (show_config import), test_backup.py
(restore_cron_prompt_fields_if_degraded import).

(cherry picked from commit 4079d422e0c2283c500c16885e959f5c170eb6cf)
2026-10-07 10:57:35 -07:00

37 lines
1.3 KiB
Python

"""``--query-file``: the single-query transport that never passes through a shell.
Split out of ``hermes_cli/main.py``.
"""
import sys
def _read_query_file(args) -> None:
"""--query-file: read the single query from a file (or stdin via '-').
Callers never have to shell-quote message bodies — this is the transport
the Bot Mode DM protocol uses; interpolating arbitrary text into a
double-quoted shell argument truncates on quotes and executes $(...)
(see tools/bot_mode_probe.py).
"""
_qfile = getattr(args, "query_file", None)
if not _qfile:
return
if args.query:
# argparse's mutually-exclusive group catches the normal CLI path;
# this guards programmatic callers that fill the namespace directly.
print("Error: -q/--query and --query-file are mutually exclusive", file=sys.stderr)
sys.exit(2)
try:
if _qfile == "-":
args.query = sys.stdin.read()
else:
with open(_qfile, "r", encoding="utf-8-sig", errors="replace") as _fh:
args.query = _fh.read()
except OSError as _e:
print(f"Error: cannot read --query-file {_qfile}: {_e}", file=sys.stderr)
sys.exit(2)
if not (args.query or "").strip():
print(f"Error: --query-file {_qfile} is empty", file=sys.stderr)
sys.exit(2)