mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(debug): sweep expired pending pastes on slash debug paths
This commit is contained in:
parent
921133cfa5
commit
61d0a99c11
4 changed files with 110 additions and 1 deletions
|
|
@ -7645,13 +7645,14 @@ class GatewayRunner:
|
|||
from hermes_cli.debug import (
|
||||
_capture_dump, collect_debug_report,
|
||||
upload_to_pastebin, _schedule_auto_delete,
|
||||
_GATEWAY_PRIVACY_NOTICE,
|
||||
_GATEWAY_PRIVACY_NOTICE, _best_effort_sweep_expired_pastes,
|
||||
)
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
|
||||
# Run blocking I/O (dump capture, log reads, uploads) in a thread.
|
||||
def _collect_and_upload():
|
||||
_best_effort_sweep_expired_pastes()
|
||||
dump_text = _capture_dump()
|
||||
report = collect_debug_report(log_lines=200, dump_text=dump_text)
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,14 @@ def _sweep_expired_pastes(now: Optional[float] = None) -> tuple[int, int]:
|
|||
return (deleted, len(remaining))
|
||||
|
||||
|
||||
def _best_effort_sweep_expired_pastes() -> None:
|
||||
"""Attempt pending-paste cleanup without letting /debug fail offline."""
|
||||
try:
|
||||
_sweep_expired_pastes()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Privacy / delete helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -518,6 +526,8 @@ def collect_debug_report(
|
|||
|
||||
def run_debug_share(args):
|
||||
"""Collect debug report + full logs, upload each, print URLs."""
|
||||
_best_effort_sweep_expired_pastes()
|
||||
|
||||
log_lines = getattr(args, "lines", 200)
|
||||
expiry = getattr(args, "expire", 7)
|
||||
local_only = getattr(args, "local", False)
|
||||
|
|
|
|||
60
tests/gateway/test_debug_command.py
Normal file
60
tests/gateway/test_debug_command.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""Tests for the gateway /debug command."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from gateway.config import GatewayConfig, Platform
|
||||
from gateway.platforms.base import MessageEvent
|
||||
from gateway.session import SessionSource
|
||||
|
||||
|
||||
def _make_event(text="/debug", platform=Platform.TELEGRAM,
|
||||
user_id="12345", chat_id="67890"):
|
||||
source = SessionSource(
|
||||
platform=platform,
|
||||
user_id=user_id,
|
||||
chat_id=chat_id,
|
||||
user_name="testuser",
|
||||
)
|
||||
return MessageEvent(text=text, source=source)
|
||||
|
||||
|
||||
def _make_runner():
|
||||
from gateway.run import GatewayRunner
|
||||
|
||||
runner = object.__new__(GatewayRunner)
|
||||
runner.config = GatewayConfig()
|
||||
runner.adapters = {}
|
||||
return runner
|
||||
|
||||
|
||||
class TestHandleDebugCommand:
|
||||
@pytest.mark.asyncio
|
||||
async def test_debug_sweeps_expired_pastes_before_upload(self):
|
||||
runner = _make_runner()
|
||||
event = _make_event()
|
||||
|
||||
with patch("hermes_cli.debug._sweep_expired_pastes", return_value=(0, 0)) as mock_sweep, \
|
||||
patch("hermes_cli.debug._capture_dump", return_value="dump"), \
|
||||
patch("hermes_cli.debug.collect_debug_report", return_value="report"), \
|
||||
patch("hermes_cli.debug.upload_to_pastebin", return_value="https://paste.rs/report"), \
|
||||
patch("hermes_cli.debug._schedule_auto_delete"):
|
||||
result = await runner._handle_debug_command(event)
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
assert "https://paste.rs/report" in result
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_debug_survives_sweep_failure(self):
|
||||
runner = _make_runner()
|
||||
event = _make_event()
|
||||
|
||||
with patch("hermes_cli.debug._sweep_expired_pastes", side_effect=RuntimeError("offline")), \
|
||||
patch("hermes_cli.debug._capture_dump", return_value="dump"), \
|
||||
patch("hermes_cli.debug.collect_debug_report", return_value="report"), \
|
||||
patch("hermes_cli.debug.upload_to_pastebin", return_value="https://paste.rs/report"), \
|
||||
patch("hermes_cli.debug._schedule_auto_delete"):
|
||||
result = await runner._handle_debug_command(event)
|
||||
|
||||
assert "https://paste.rs/report" in result
|
||||
|
|
@ -283,6 +283,44 @@ class TestCollectDebugReport:
|
|||
class TestRunDebugShare:
|
||||
"""Test the run_debug_share CLI handler."""
|
||||
|
||||
def test_share_sweeps_expired_pastes(self, hermes_home, capsys):
|
||||
"""Slash-command path should sweep old pending deletes before uploading."""
|
||||
from hermes_cli.debug import run_debug_share
|
||||
|
||||
args = MagicMock()
|
||||
args.lines = 50
|
||||
args.expire = 7
|
||||
args.local = False
|
||||
|
||||
with patch("hermes_cli.dump.run_dump"), \
|
||||
patch("hermes_cli.debug._sweep_expired_pastes", return_value=(0, 0)) as mock_sweep, \
|
||||
patch("hermes_cli.debug.upload_to_pastebin",
|
||||
return_value="https://paste.rs/test"):
|
||||
run_debug_share(args)
|
||||
|
||||
mock_sweep.assert_called_once()
|
||||
assert "Debug report uploaded" in capsys.readouterr().out
|
||||
|
||||
def test_share_survives_sweep_failure(self, hermes_home, capsys):
|
||||
"""Expired-paste cleanup is best-effort and must not block sharing."""
|
||||
from hermes_cli.debug import run_debug_share
|
||||
|
||||
args = MagicMock()
|
||||
args.lines = 50
|
||||
args.expire = 7
|
||||
args.local = False
|
||||
|
||||
with patch("hermes_cli.dump.run_dump"), \
|
||||
patch(
|
||||
"hermes_cli.debug._sweep_expired_pastes",
|
||||
side_effect=RuntimeError("offline"),
|
||||
), \
|
||||
patch("hermes_cli.debug.upload_to_pastebin",
|
||||
return_value="https://paste.rs/test"):
|
||||
run_debug_share(args)
|
||||
|
||||
assert "https://paste.rs/test" in capsys.readouterr().out
|
||||
|
||||
def test_local_flag_prints_full_logs(self, hermes_home, capsys):
|
||||
"""--local prints the report plus full log contents."""
|
||||
from hermes_cli.debug import run_debug_share
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue