fix: avoid false response-interrupted stale repair markers - #3046
Merged
4 commits merged intoMay 28, 2026
Merged
4 commits merged into
4 commits merged into
Conversation
6267716
Collaborator
|
Shipped in v0.51.154 / Release DZ (stage-batch36, commit 6267716). Thanks for the contribution! |
ai-ag2026
pushed a commit
to ai-ag2026/hermes-webui
that referenced
this pull request
May 28, 2026
# Conflicts: # CHANGELOG.md
ai-ag2026
pushed a commit
to ai-ag2026/hermes-webui
that referenced
this pull request
May 28, 2026
9-PR medium-risk cleanup: - nesquena#3037 routes.py: argv-style prefill hook + env-var override for notes drawer - nesquena#3046 models.py: compression parent not repaired as stale interrupted turn - nesquena#3048 session_discoverability.py: --repair-safe CLI with default dry-run - nesquena#3053 ui.js: streaming KaTeX guard for parser-owned equations - nesquena#3059 models.py: empty partial activity rows excluded from sidebar recency - nesquena#3060 profiles.py: API key writes to .env (chmod 600), not config.yaml - nesquena#3064 routes.py: MEDIA: image tokens allow exact session-referenced paths - nesquena#3069 models.py: cron sessions with project_id surface via Cron Jobs chip - nesquena#3077 gateway_chat.py: HTTP 401 maps to gateway_auth_error event
SysAdminDoc
pushed a commit
to SysAdminDoc/hermes-webui
that referenced
this pull request
Jun 26, 2026
# Conflicts: # CHANGELOG.md
SysAdminDoc
pushed a commit
to SysAdminDoc/hermes-webui
that referenced
this pull request
Jun 26, 2026
9-PR medium-risk cleanup: - nesquena#3037 routes.py: argv-style prefill hook + env-var override for notes drawer - nesquena#3046 models.py: compression parent not repaired as stale interrupted turn - nesquena#3048 session_discoverability.py: --repair-safe CLI with default dry-run - nesquena#3053 ui.js: streaming KaTeX guard for parser-owned equations - nesquena#3059 models.py: empty partial activity rows excluded from sidebar recency - nesquena#3060 profiles.py: API key writes to .env (chmod 600), not config.yaml - nesquena#3064 routes.py: MEDIA: image tokens allow exact session-referenced paths - nesquena#3069 models.py: cron sessions with project_id surface via Cron Jobs chip - nesquena#3077 gateway_chat.py: HTTP 401 maps to gateway_auth_error event
bernyforce
pushed a commit
to bernyforce/hermes-webui
that referenced
this pull request
Jul 29, 2026
# Conflicts: # CHANGELOG.md
bernyforce
pushed a commit
to bernyforce/hermes-webui
that referenced
this pull request
Jul 29, 2026
9-PR medium-risk cleanup: - nesquena#3037 routes.py: argv-style prefill hook + env-var override for notes drawer - nesquena#3046 models.py: compression parent not repaired as stale interrupted turn - nesquena#3048 session_discoverability.py: --repair-safe CLI with default dry-run - nesquena#3053 ui.js: streaming KaTeX guard for parser-owned equations - nesquena#3059 models.py: empty partial activity rows excluded from sidebar recency - nesquena#3060 profiles.py: API key writes to .env (chmod 600), not config.yaml - nesquena#3064 routes.py: MEDIA: image tokens allow exact session-referenced paths - nesquena#3069 models.py: cron sessions with project_id surface via Cron Jobs chip - nesquena#3077 gateway_chat.py: HTTP 401 maps to gateway_auth_error event
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pre_compression_snapshotflag on the live continuation after preserving the archived snapshotACTIVE_RUNSworker bookkeeping as authoritative liveness in_clear_stale_stream_state()before writing an interrupted-turn marker_clear_stale_stream_state()so fresh turns are not marked interrupted just because the SSE channel is temporarily missingcompletedrun journal before manufacturing an interrupted-turn marker, clearing stale pending runtime fields without altering a completed transcriptWhy
A live auto-compression rotation can leave the archived parent with a pending/stale-looking runtime shape while the real response continues in the child session. The recovery pass should not repair that parent as an interrupted turn. Doing so creates a false "Response interrupted" marker and can hide or confuse the visible continuation.
A second observed path produced the same user-visible false marker without compression:
_clear_stale_stream_state()checked only whether the SSE stream id was present inSTREAMS. If that channel was gone or not visible while the worker was still alive inACTIVE_RUNS, the route-level cleanup could call the core sync/error-marker repair path immediately and append a false "Response interrupted" marker even though the worker continued running API calls and tools.A third observed path happened after a turn had already completed: the run journal contained a terminal
completedevent and the assistant answer was already in the transcript, but the sidecar still had stalepending_user_message/active_stream_id. A later stale cleanup saw no live stream/worker and appended a false marker. This PR now treats a completed journal as authoritative and clears the stale runtime fields without adding an interruption marker.This is a concrete run-state consistency slice under #2361. It is adjacent to, but separate from, #2980: #2980 handles reload/sidebar continuation recovery, while this PR prevents backend stale-repair paths from manufacturing the bad interrupted state in the first place.
Refs #2361
Validation
python3 -m pytest tests/test_stale_stream_writeback.py::test_stale_stream_clear_trusts_completed_run_journal_instead_of_adding_marker -q→ 1 passedpython3 -m pytest tests/test_stale_stream_writeback.py -q→ 8 passedpython3 -m pytest tests/test_stale_stream_writeback.py tests/test_session_sidecar_repair.py tests/test_session_lost_response_regression.py tests/test_issue2157_sessions_list_stale_stream_state.py -q→ 91 passed3469a2f: Python 3.11, 3.12, and 3.13 passed