feat: add /debug slash command for all platforms

Adds /debug as a slash command available in CLI, Telegram, Discord,
Slack, and all other gateway platforms. Uploads debug report + full
logs to paste services and returns shareable URLs.

- commands.py: CommandDef in Info category (no cli_only/gateway_only)
- gateway/run.py: async handler with run_in_executor for blocking I/O
- cli.py: dispatch in process_command to run_debug_share
This commit is contained in:
Teknium
2026-04-12 18:08:45 -07:00
parent f724079d3b
commit 3cd6cbee5f
3 changed files with 69 additions and 0 deletions
+10
View File
@@ -5391,6 +5391,8 @@ class HermesCLI:
self._show_usage()
elif canonical == "insights":
self._show_insights(cmd_original)
elif canonical == "debug":
self._handle_debug_command()
elif canonical == "paste":
self._handle_paste_command()
elif canonical == "image":
@@ -6305,6 +6307,14 @@ class HermesCLI:
except Exception as e:
print(f" ❌ Compression failed: {e}")
def _handle_debug_command(self):
"""Handle /debug — upload debug report + logs and print paste URLs."""
from hermes_cli.debug import run_debug_share
from types import SimpleNamespace
args = SimpleNamespace(lines=200, expire=7, local=False)
run_debug_share(args)
def _show_usage(self):
"""Show rate limits (if available) and session token usage."""
if not self.agent:
+58
View File
@@ -2757,6 +2757,9 @@ class GatewayRunner:
if canonical == "update":
return await self._handle_update_command(event)
if canonical == "debug":
return await self._handle_debug_command(event)
if canonical == "title":
return await self._handle_title_command(event)
@@ -6428,6 +6431,61 @@ class GatewayRunner:
Platform.FEISHU, Platform.WECOM, Platform.WECOM_CALLBACK, Platform.WEIXIN, Platform.BLUEBUBBLES, Platform.LOCAL,
})
async def _handle_debug_command(self, event: MessageEvent) -> str:
"""Handle /debug — upload debug report + logs and return paste URLs."""
import asyncio
from hermes_cli.debug import (
_capture_dump, collect_debug_report, _read_full_log,
upload_to_pastebin,
)
loop = asyncio.get_running_loop()
# Run blocking I/O (dump capture, log reads, uploads) in a thread.
def _collect_and_upload():
dump_text = _capture_dump()
report = collect_debug_report(log_lines=200, dump_text=dump_text)
agent_log = _read_full_log("agent")
gateway_log = _read_full_log("gateway")
if agent_log:
agent_log = dump_text + "\n\n--- full agent.log ---\n" + agent_log
if gateway_log:
gateway_log = dump_text + "\n\n--- full gateway.log ---\n" + gateway_log
urls = {}
failures = []
try:
urls["Report"] = upload_to_pastebin(report)
except Exception as exc:
return f"✗ Failed to upload debug report: {exc}"
if agent_log:
try:
urls["agent.log"] = upload_to_pastebin(agent_log)
except Exception:
failures.append("agent.log")
if gateway_log:
try:
urls["gateway.log"] = upload_to_pastebin(gateway_log)
except Exception:
failures.append("gateway.log")
lines = ["**Debug report uploaded:**", ""]
label_width = max(len(k) for k in urls)
for label, url in urls.items():
lines.append(f"`{label:<{label_width}}` {url}")
if failures:
lines.append(f"\n_(failed to upload: {', '.join(failures)})_")
lines.append("\nShare these links with the Hermes team for support.")
return "\n".join(lines)
return await loop.run_in_executor(None, _collect_and_upload)
async def _handle_update_command(self, event: MessageEvent) -> str:
"""Handle /update command — update Hermes Agent to the latest version.
+1
View File
@@ -154,6 +154,7 @@ COMMAND_REGISTRY: list[CommandDef] = [
cli_only=True, args_hint="<path>"),
CommandDef("update", "Update Hermes Agent to the latest version", "Info",
gateway_only=True),
CommandDef("debug", "Upload debug report (system info + logs) and get shareable links", "Info"),
# Exit
CommandDef("quit", "Exit the CLI", "Exit",