Skip to content

fix(gateway): strip cursor from frozen message on empty fallback continuation (#7183)#12472

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-a845df96
Apr 19, 2026
Merged

fix(gateway): strip cursor from frozen message on empty fallback continuation (#7183)#12472
teknium1 merged 1 commit into
mainfrom
hermes/hermes-a845df96

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

A streaming message is no longer left frozen with a visible cursor when fallback mode kicks in and has nothing new to send at stream end. The cursor-stripping edit that was missing from the empty-continuation early-return path is now attempted before returning.

Changes

  • gateway/stream_consumer.py — in _send_fallback_final(), when continuation.strip() == "" and final_text doesn't differ meaningfully from the visible prefix, attempt a best-effort edit to strip the cursor before the early return. Harmless when fallback wasn't armed or the cursor isn't present; crash-proof if the edit itself fails.
  • tests/gateway/test_stream_consumer.py — 3 regression tests in TestCursorStrippingOnFallback: cursor stripped on empty continuation, no edit attempted when cursor is not configured, edit-failure handled without corrupting _last_sent_text.

Validation

Before After
tests/gateway/test_stream_consumer.py 64 passing 67 passing (3 new)
Cursor edit attempt in _send_fallback_final empty-continuation path not attempted attempted (best-effort)

Live-tested against the Phase 1 integration harness (real agent on OpenRouter → real GatewayStreamConsumer → mock adapter with simulated flood control): all three scenarios — no flood, flood@1, flood@2 — deliver content correctly without regressions. The remaining cursor residue visible in the live test is on a separate code path (_try_strip_cursor() inside the #8124 segment-flush helper hitting an active flood window), outside the scope of this fix.

Closes

Credit

Relationship to recent streaming fixes

This is the last defense-in-depth piece for the Discord "section-header with stuck cursor" pattern:

…inuation (#7183)

When _send_fallback_final() is called with nothing new to deliver
(the visible partial already matches final_text), the last edit may
still show the cursor character because fallback mode was entered
after a failed edit.  Before this fix the early-return path left
_already_sent = True without attempting to strip the cursor, so the
message stayed frozen with a visible ▉ permanently.

Adds a best-effort edit inside the empty-continuation branch to clean
the cursor off the last-sent text.  Harmless when fallback mode
wasn't actually armed or when the cursor isn't present.  If the strip
edit itself fails (flood still active), we return without crashing
and without corrupting _last_sent_text.

Adapted from PR #7429 onto current main — the surrounding fallback
block grew the #10807 stale-prefix handling since #7429 was written,
so the cursor strip lives in the new else-branch where we still
return early.

3 unit tests covering: cursor stripped on empty continuation, no edit
attempted when cursor is not configured, cursor-strip edit failure
handled without crash.

Originally proposed as PR #7429.
@teknium1 teknium1 merged commit b668c09 into main Apr 19, 2026
3 of 5 checks passed
@teknium1 teknium1 deleted the hermes/hermes-a845df96 branch April 19, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants