Skip to content

fix(gateway): plain text while busy interrupts by default again#40590

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-bafe0126
Jun 6, 2026
Merged

fix(gateway): plain text while busy interrupts by default again#40590
teknium1 merged 2 commits into
mainfrom
hermes/hermes-bafe0126

Conversation

@teknium1

@teknium1 teknium1 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Plain text messages sent while the agent is busy now interrupt by default again — the advertised busy_input_mode: interrupt default is no longer silently overridden.

Root cause: A second knob, busy_text_mode (added in 7abd627, default queue), short-circuited every plain TEXT message in _handle_active_session_busy_message before busy_input_mode was ever consulted. So even users on the default interrupt mode saw plain follow-ups silently queued instead of interrupting. Two contradicting knobs with opposite defaults — the newer one quietly won.

Changes

  • gateway/run.py: busy_input_mode is now the single source of truth. _load_busy_text_mode() follows it; the legacy busy_text_mode knob is honored only when explicitly set (env or config) so existing queue setups keep working. Busy-gate fallback default flipped queueinterrupt.
  • gateway/platforms/base.py: adapter init default + debounce-candidate gate flipped queueinterrupt. Debounce mechanism preserved, now keyed off the resolved mode.
  • Tests: updated to the new contract (default follows busy_input_mode; legacy override still wins).

/stop and /new are unaffected — they always went through the slash-command bypass, not this gate.

Validation

Config busy_input_mode busy_text_mode (resolved)
fresh install (nothing set) interrupt interrupt
busy_input_mode: queue queue queue
legacy busy_text_mode: queue interrupt queue (back-compat)
busy_input_mode: steer steer interrupt (steer handled upstream)

55 targeted gateway tests pass; E2E resolution verified with real imports + isolated config.

Fixes #38390, #31588.

Infographic

one-knob-one-truth

teknium1 added 2 commits June 4, 2026 17:11
Port from anomalyco/opencode#30749.

When compression.enabled is false, NO automatic compaction trigger may
fire. The proactive token-threshold paths (preflight + post-response
should_compress gate) already honoured the setting, but the three
provider-overflow recovery paths in the agent loop — long-context-tier
429, 413 payload-too-large, and context-overflow — called
_compress_context() unconditionally, silently compressing and rotating
the session against the user's explicit choice.

Add a single guard at the top of the overflow-recovery dispatch: when
compression is disabled and the error is one of those three overflow
classes, surface a terminal error (compaction_disabled: True) telling the
user to /compress manually, /new, switch to a larger-context model, or
reduce attachments. Manual /compress (force=True) is unaffected — it never
enters this loop.

Tests: new TestOverflowWithCompactionDisabled (413 + 400 overflow don't
compress when disabled; control case still compresses when enabled).
Existing overflow-recovery tests updated to enable compaction explicitly
(they verify the recovery fires); fixture defaults flipped to True to
match production (compression.enabled defaults to True).
busy_input_mode (default 'interrupt') was advertised as the busy-behavior
knob, but a second knob added in 7abd627 — busy_text_mode, defaulting to
'queue' — short-circuited every plain TEXT message before busy_input_mode
was consulted. Result: plain follow-ups silently queued instead of
interrupting, even with busy_input_mode left at its 'interrupt' default
(regression #38390, silent-queue #31588).

Collapse to one source of truth: busy_input_mode drives text handling.
busy_text_mode is kept only as a legacy explicit override for back-compat
(existing queue setups keep working); when unset it follows busy_input_mode.
All default fallbacks flipped queue->interrupt. The debounce mechanism is
preserved and now keyed off the resolved mode.

Fixes #38390, #31588.
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-bafe0126 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9962 on HEAD, 9962 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5167 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery comp/agent Core agent loop, run_agent.py, prompt builder labels Jun 6, 2026
@teknium1 teknium1 merged commit 54e7b74 into main Jun 6, 2026
23 checks passed
@teknium1 teknium1 deleted the hermes/hermes-bafe0126 branch June 6, 2026 16:00
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…Research#40590)

* fix: respect disabled auto-compaction on context overflow

Port from anomalyco/opencode#30749.

When compression.enabled is false, NO automatic compaction trigger may
fire. The proactive token-threshold paths (preflight + post-response
should_compress gate) already honoured the setting, but the three
provider-overflow recovery paths in the agent loop — long-context-tier
429, 413 payload-too-large, and context-overflow — called
_compress_context() unconditionally, silently compressing and rotating
the session against the user's explicit choice.

Add a single guard at the top of the overflow-recovery dispatch: when
compression is disabled and the error is one of those three overflow
classes, surface a terminal error (compaction_disabled: True) telling the
user to /compress manually, /new, switch to a larger-context model, or
reduce attachments. Manual /compress (force=True) is unaffected — it never
enters this loop.

Tests: new TestOverflowWithCompactionDisabled (413 + 400 overflow don't
compress when disabled; control case still compresses when enabled).
Existing overflow-recovery tests updated to enable compaction explicitly
(they verify the recovery fires); fixture defaults flipped to True to
match production (compression.enabled defaults to True).

* fix(gateway): plain text while busy interrupts by default again

busy_input_mode (default 'interrupt') was advertised as the busy-behavior
knob, but a second knob added in 7abd627 — busy_text_mode, defaulting to
'queue' — short-circuited every plain TEXT message before busy_input_mode
was consulted. Result: plain follow-ups silently queued instead of
interrupting, even with busy_input_mode left at its 'interrupt' default
(regression NousResearch#38390, silent-queue NousResearch#31588).

Collapse to one source of truth: busy_input_mode drives text handling.
busy_text_mode is kept only as a legacy explicit override for back-compat
(existing queue setups keep working); when unset it follows busy_input_mode.
All default fallbacks flipped queue->interrupt. The debounce mechanism is
preserved and now keyed off the resolved mode.

Fixes NousResearch#38390, NousResearch#31588.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression: busy_input_mode=interrupt broken in v2026.5.29 (worked in v2026.5.16)

2 participants