diff --git a/CHANGELOG.md b/CHANGELOG.md index c86c32d2..e5541acb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ ### Fixed +- **PR TBD** by @franksong2702 — Clearing stale stream runtime flags no longer refreshes a session's `updated_at`, so old compressed continuations should not jump back to the top of the sidebar just because WebUI repaired a dead `active_stream_id` during a read/list request. + - **PR #2322** by @Michaelyklam (refs #2271) — LAN Ollama models selected from endpoint-discovered `custom:-` / `custom::` picker entries now route through the configured `ollama` provider and base URL instead of surfacing a missing `CUSTOM_*_API_KEY` error. The picker still surfaces endpoint-discovered entries; the fix is to recognize them as UI routing hints matching the configured local-server base URL and resolve them via the actual `ollama` provider. - **PR #2326** by @Michaelyklam (closes #2232) — Legacy `hermes` CLI toolset alias is now normalized to `hermes-cli` + `hermes-api-server` when WebUI resolves CLI toolsets from shared Hermes config. Modern Hermes Agent exposes the composite under those two names; older configs that still contain the legacy `hermes` toolset name no longer surface as "unknown toolset" warnings. diff --git a/api/routes.py b/api/routes.py index ebcd3a9d..9ced2a75 100644 --- a/api/routes.py +++ b/api/routes.py @@ -1012,7 +1012,10 @@ def _clear_stale_stream_state(session) -> bool: if hasattr(session, "pending_started_at"): session.pending_started_at = None try: - session.save() + # Runtime cleanup is not user activity; do not bubble old sessions + # to the top of the sidebar just because a stale stream flag was + # repaired during a read/list path. + session.save(touch_updated_at=False) except Exception: logger.exception( "_clear_stale_stream_state: save() failed for session %s", diff --git a/tests/test_stale_stream_cleanup.py b/tests/test_stale_stream_cleanup.py index 5f294789..c66098e7 100644 --- a/tests/test_stale_stream_cleanup.py +++ b/tests/test_stale_stream_cleanup.py @@ -37,10 +37,13 @@ class _FakeSession: self.pending_user_message = "old prompt" self.pending_attachments = ["old.txt"] self.pending_started_at = 123 + self.messages = [] self.saved_stream_ids = [] + self.saved_touch_updated_at = [] - def save(self): + def save(self, *, touch_updated_at=True): self.saved_stream_ids.append(self.active_stream_id) + self.saved_touch_updated_at.append(touch_updated_at) def test_stale_stream_cleanup_helper_exists(): @@ -50,7 +53,18 @@ def test_stale_stream_cleanup_helper_exists(): assert "session.pending_user_message = None" in ROUTES_SRC assert "session.pending_attachments = []" in ROUTES_SRC assert "session.pending_started_at = None" in ROUTES_SRC - assert "session.save()" in ROUTES_SRC + assert "session.save(touch_updated_at=False)" in ROUTES_SRC + + +def test_stale_stream_cleanup_does_not_refresh_sidebar_timestamp(): + config.STREAMS.clear() + config.SESSION_AGENT_LOCKS.clear() + session = _FakeSession() + + assert routes._clear_stale_stream_state(session) is True + + assert session.active_stream_id is None + assert session.saved_touch_updated_at == [False] def test_session_load_clears_stale_stream_before_response():