When a Desktop-driven update fails at the Electron rebuild (updater exit 6, 'Code and dependencies updated, but the Desktop app REBUILD FAILED'), the only artifacts holding the root cause are ~/.hermes/logs/update.log (full stdout/stderr mirror of hermes update, written by _UpdateOutputStream) and ~/.hermes/logs/desktop-update-handoff.log (hand-off stages including the 'desktop --force-build --build-only' retry). Both the updater's failure messages and the Desktop error box direct users to 'hermes debug share', but the share captured neither file: LOG_FILES and the debug.py capture chain covered only the classic five logs, so update-failure issues (e.g. #100874) arrived with the diagnostics that matter most missing. Additionally, 'hermes logs list' (a directory scan) already listed both files while LOG_FILES had no readable key for them, so 'hermes logs update' failed with 'Unknown log' against a file the CLI itself displays. Wire both files through the whole chain: - hermes_cli/logs.py: add 'update' and 'handoff' LOG_FILES keys (fixes list-vs-read inconsistency; tail/follow/filters come free). - hermes_cli/debug.py: _capture_default_log_snapshots, collect_debug_report (512 KB snapshot cap and the 100-line tail budget both apply; a hand-built snapshot dict without the new keys degrades to the old five-section report instead of KeyError), collect_share_bundle full logs, the paste-upload label list in build_debug_share, and the --local print list. The --nous bundle and privacy notice inherit the new keys; force-redaction applies via _capture_log_snapshot as for every other log. - hermes_cli/subcommands/logs.py + website docs: name the new logs. Tests (tests/hermes_cli/test_debug_share_update_logs.py): 12 new tests — snapshot keys present with real content, missing files degrade to the honest note without raising, report sections appear, bundle keys omitted when absent, upload/--local label lists include the new logs, LOG_FILES keys resolve, tail_log end-to-end. Sabotage pass: 10 of 12 fail without the fix.
53 lines
2.6 KiB
Python
53 lines
2.6 KiB
Python
"""``hermes logs`` subcommand parser."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
from typing import Callable
|
|
|
|
|
|
def build_logs_parser(subparsers, *, cmd_logs: Callable) -> None:
|
|
"""Attach the ``logs`` subcommand to ``subparsers``."""
|
|
logs_parser = subparsers.add_parser(
|
|
"logs",
|
|
help="View and filter Hermes log files",
|
|
description="View, tail, and filter agent.log / errors.log / gateway.log / gui.log / desktop.log / update.log / desktop-update-handoff.log",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""\
|
|
Examples:
|
|
hermes logs Show last 50 lines of agent.log
|
|
hermes logs -f Follow agent.log in real time
|
|
hermes logs errors Show last 50 lines of errors.log
|
|
hermes logs gateway -n 100 Show last 100 lines of gateway.log
|
|
hermes logs gui -f Follow gui.log in real time
|
|
hermes logs desktop -f Follow desktop.log (Electron app boot/backend)
|
|
hermes logs update Show last 50 lines of update.log (hermes update mirror)
|
|
hermes logs handoff Show last 50 lines of desktop-update-handoff.log
|
|
hermes logs --level WARNING Only show WARNING and above
|
|
hermes logs --session abc123 Filter by session ID
|
|
hermes logs --component tools Only show tool-related lines
|
|
hermes logs --since 1h Lines from the last hour
|
|
hermes logs --since 30m -f Follow, starting from 30 min ago
|
|
hermes logs list List available log files with sizes
|
|
""")
|
|
logs_parser.add_argument(
|
|
"log_name",
|
|
nargs="?",
|
|
default="agent",
|
|
help="Log to view: agent (default), errors, gateway, gui, desktop, update, handoff, or 'list' to show available files",
|
|
)
|
|
logs_parser.add_argument(
|
|
"-n", "--lines", type=int, default=50, help="Number of lines to show (default: 50)")
|
|
logs_parser.add_argument(
|
|
"-f", "--follow", action="store_true", help="Follow the log in real time (like tail -f)")
|
|
logs_parser.add_argument(
|
|
"--level", metavar="LEVEL", help="Minimum log level to show (DEBUG, INFO, WARNING, ERROR)")
|
|
logs_parser.add_argument(
|
|
"--session", metavar="ID", help="Filter lines containing this session ID substring")
|
|
logs_parser.add_argument(
|
|
"--since", metavar="TIME", help="Show lines since TIME ago (e.g. 1h, 30m, 2d)")
|
|
logs_parser.add_argument(
|
|
"--component", metavar="NAME",
|
|
help="Filter by component: gateway, agent, tools, cli, cron, gui")
|
|
logs_parser.set_defaults(func=cmd_logs)
|