feat: /btw now answers side questions with conversation context; /background renamed to /bg
/bg (formerly /background, which is retired) keeps the existing semantics: spawn a fresh, independent agent session in the background. /btw is now its own command matching the convention other harnesses use: ask a quick side question ABOUT the current conversation without interrupting it. A one-shot auxiliary LLM call (main model by default, overridable via auxiliary.side_question.* in config.yaml) answers from a read-only transcript snapshot — the live session's history, role alternation, and prompt cache are untouched, and the current turn keeps running. Surfaces wired: CLI (inline mid-run dispatch), gateway (all messengers, busy-dispatch table + idle dispatch, i18n across all 17 locales), TUI (prompt.btw RPC + btw.complete event), Discord native slash, relay command manifest, desktop exec routing, docs (EN + zh-Hans).
This commit is contained in:
@@ -6396,7 +6396,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Count live /background tasks. The dict entry is removed in the
|
||||
# Count live /bg tasks. The dict entry is removed in the
|
||||
# task thread's finally block, so len() reflects truly-running tasks.
|
||||
# len() on a CPython dict is atomic; safe to read without a lock.
|
||||
try:
|
||||
@@ -11947,20 +11947,20 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
def _should_handle_background_command_inline(
|
||||
self, text: str, has_images: bool = False
|
||||
) -> bool:
|
||||
"""Return True when /background should be dispatched while the agent runs.
|
||||
"""Return True when /bg or /btw should be dispatched while the agent runs.
|
||||
|
||||
Same queue problem /steer had. ``/background`` (``/bg``, ``/btw``)
|
||||
exists to start independent work *without* waiting for the current
|
||||
turn, but a slash command typed while the agent is busy goes into
|
||||
``_pending_input``, and ``process_loop`` is blocked inside
|
||||
``self.chat()`` for the whole run. The background task therefore only
|
||||
starts once the foreground turn has finished, which is the one moment
|
||||
it was not needed.
|
||||
Same queue problem /steer had. ``/bg`` exists to start independent
|
||||
work *without* waiting for the current turn, and ``/btw`` exists to
|
||||
answer a side question about the in-flight conversation, but a slash
|
||||
command typed while the agent is busy goes into ``_pending_input``,
|
||||
and ``process_loop`` is blocked inside ``self.chat()`` for the whole
|
||||
run. The side task would therefore only start once the foreground
|
||||
turn has finished, which is the one moment it was not needed.
|
||||
|
||||
The command's own ``CommandDef`` already declares
|
||||
Both commands' ``CommandDef`` entries already declare
|
||||
``busy_policy="dispatch"``; the gateway honours that, the classic CLI
|
||||
never consulted it. Dispatching inline on the UI thread starts the
|
||||
background session immediately and leaves the foreground turn running
|
||||
side session immediately and leaves the foreground turn running
|
||||
untouched: no interrupt, no steer.
|
||||
"""
|
||||
if not text or has_images or not _looks_like_slash_command(text):
|
||||
@@ -11971,7 +11971,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
from hermes_cli.commands import resolve_command
|
||||
base = text.split(None, 1)[0].lower().lstrip('/')
|
||||
cmd = resolve_command(base)
|
||||
return bool(cmd and cmd.name == "background")
|
||||
return bool(cmd and cmd.name in ("bg", "btw"))
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@@ -12575,8 +12575,10 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
self._handle_agents_command()
|
||||
elif canonical == "journey":
|
||||
self._handle_journey_command(cmd_original)
|
||||
elif canonical == "background":
|
||||
elif canonical == "bg":
|
||||
self._handle_background_command(cmd_original)
|
||||
elif canonical == "btw":
|
||||
self._handle_btw_command(cmd_original)
|
||||
elif canonical == "queue":
|
||||
# Extract prompt after "/queue " or "/q "
|
||||
parts = cmd_original.split(None, 1)
|
||||
@@ -18213,12 +18215,12 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
event.app.invalidate()
|
||||
return
|
||||
|
||||
# Same treatment for /background (/bg, /btw) while the agent is
|
||||
# running. Queuing it defeats the entire point of the command:
|
||||
# process_loop is blocked inside self.chat(), so the background
|
||||
# task would only start once the foreground turn it was meant to
|
||||
# run alongside has already finished (#75221). The foreground
|
||||
# turn is left alone: no interrupt, no steer.
|
||||
# Same treatment for /bg and /btw while the agent is
|
||||
# running. Queuing them defeats the entire point of the
|
||||
# commands: process_loop is blocked inside self.chat(), so the
|
||||
# side task would only start once the foreground turn it was
|
||||
# meant to run alongside has already finished (#75221). The
|
||||
# foreground turn is left alone: no interrupt, no steer.
|
||||
if self._should_handle_background_command_inline(
|
||||
text, has_images=has_images
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user