mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
fix(gateway): let /btw dispatch mid-turn instead of being rejected
/btw spawns a parallel ephemeral side-question task (self-guarded against
concurrent /btw on the same chat) — exactly like /background. But it was
missing from the running-agent bypass list in _handle_message(), so it
fell through to the catch-all and returned:
⏳ Agent is running — /btw can't run mid-turn. Wait for the current
response or /stop first.
That's the opposite of what /btw is for — asking a side question while
the main turn is still working. Add the bypass next to /background and a
regression test covering the mid-turn dispatch path.
Reported by @IuriiTiunov on Telegram.
This commit is contained in:
@@ -3501,6 +3501,14 @@ class GatewayRunner:
|
||||
if _cmd_def_inner and _cmd_def_inner.name == "background":
|
||||
return await self._handle_background_command(event)
|
||||
|
||||
# /btw must bypass the running-agent guard for the same reason
|
||||
# as /background: it spawns a parallel ephemeral side-question
|
||||
# task (see _handle_btw_command) that doesn't interrupt the
|
||||
# active conversation and self-guards against concurrent /btw
|
||||
# on the same chat.
|
||||
if _cmd_def_inner and _cmd_def_inner.name == "btw":
|
||||
return await self._handle_btw_command(event)
|
||||
|
||||
# Session-level toggles that are safe to run mid-agent —
|
||||
# /yolo can unblock a pending approval prompt, /verbose cycles
|
||||
# the tool-progress display mode for the ongoing stream.
|
||||
|
||||
@@ -165,3 +165,27 @@ async def test_reasoning_rejected_mid_run():
|
||||
assert result is not None
|
||||
assert "can't run mid-turn" in result
|
||||
assert "/reasoning" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_btw_dispatches_mid_run():
|
||||
"""/btw mid-run must dispatch to its handler, not hit the catch-all.
|
||||
|
||||
/btw spawns a parallel ephemeral side-question task that does NOT
|
||||
interrupt the active conversation (see _handle_btw_command). It's the
|
||||
whole point of the command — asking a side question while the main
|
||||
turn is still working. Before the mid-turn bypass was added, /btw
|
||||
fell through to the "Agent is running — wait or /stop first" catch-all,
|
||||
making it useless in exactly the scenario it was designed for.
|
||||
"""
|
||||
runner = _make_runner()
|
||||
runner._handle_btw_command = AsyncMock(
|
||||
return_value='💬 /btw: "what module owns titles?"\nReply will appear here shortly.'
|
||||
)
|
||||
|
||||
result = await runner._handle_message(_make_event("/btw what module owns titles?"))
|
||||
|
||||
runner._handle_btw_command.assert_awaited_once()
|
||||
assert result is not None
|
||||
assert "💬 /btw" in result
|
||||
assert "can't run mid-turn" not in result
|
||||
|
||||
Reference in New Issue
Block a user