Skip to content

fix(gateway): preserve internal events during active sessions - #75849

Open
jackroofan wants to merge 1 commit into
NousResearch:mainfrom
jackroofan:fix/internal-event-user-input-guard-20260801
Open

jackroofan wants to merge 1 commit into
NousResearch:mainfrom
jackroofan:fix/internal-event-user-input-guard-20260801

Conversation

@jackroofan

Copy link
Copy Markdown

Summary

  • prevent internal synthetic events from being treated as user replies, approvals, interrupts, or slash commands
  • preserve pending-input and active-session safety boundaries across gateway platforms
  • add focused regression coverage for command, clarify, approval, race, image, and Yuanbao paths

Tests

  • python -m pytest -q tests/gateway/test_internal_event_never_interrupts_busy_session.py tests/gateway/test_internal_event_bypass_pairing.py tests/gateway/test_clarify_active_session_bypass.py tests/gateway/test_command_bypass_active_session.py tests/gateway/test_interrupt_key_match.py tests/gateway/test_plaintext_approval_routing.py tests/gateway/test_queued_native_image_session_key.py tests/gateway/test_session_race_guard.py tests/test_yuanbao_pipeline.py
  • python -m compileall -q gateway
  • git diff --check origin/main...HEAD

@teknium1

teknium1 commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the focused regression coverage. The premise is confirmed on current origin/main (991f5f1e): gateway/run.py:8362-8473 processes authorization and plain-text approval before its existing internal-event guard at gateway/run.py:8486-8498; gateway/platforms/base.py:5546, :5580, and :5644-5685 also treat internal text as commands or clarify input.

The diff closes those control paths in both adapter and direct-runner entry points. It also preserves the distinct Yuanbao recall cancellation path: current gateway/platforms/yuanbao.py:1107-1118 explicitly queues a recall event and signals the active session, so classifying that event as non-internal keeps it eligible under the proposed has_pending_interrupt rule. The added tests cover each changed boundary, including queue draining of command-shaped internal evidence.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit area/sessions Session lifecycle, resume, persistence, history labels Aug 1, 2026
@Adolanium

Copy link
Copy Markdown

I checked this against current main. The bug is still there: an internal event (a background completion or watch notification) can still answer a pending clarify prompt or the /update prompt. But gateway/run.py has been split, and part of this PR is now already on main, so it needs a rebase with a smaller scope.

Already on main, drop these hunks:

  • The busy-handler change. Commit d6867ab now admits event.internal and event.allow_gateway_control wakes at the very top of _handle_active_session_busy_message (gateway/run_busy.py, around line 785), before auth and approval routing. Moving the internal early return there again would conflict with that. The internal check later in the same function also already queues these events.

Still needed, at the new locations:

  • gateway/run_inbound.py: skip internal events in _hm_update_prompt_reply (around line 319), _hm_clarify_reply (around line 364) and _hm_slash_confirm_reply plus the has_blocking_approval check (around line 454). These are the old _handle_message intercepts.
  • gateway/platforms/base.py: skip coerce_plaintext_gateway_command(event) (around line 3972) and the text clarify bypass (around line 4031) for internal events, as this PR does.
  • gateway/run_turn.py: the pending / command check (around line 3695) should ignore internal events, same as your run.py hunk.

Suggest splitting out: the has_pending_interrupt change and the Yuanbao recall flip to internal=False. They change interrupt behavior for every adapter, which is wider than this bug, so they will be easier to review on their own.

The clarify test here is a good invariant test. A matching one for the /update prompt would cover the idle path too. I have not opened a competing PR, so this one can carry the fix.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels Sep 27, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/sessions Session lifecycle, resume, persistence, history comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants