From 2d71e9e9bc3d4183b3fd586a4ce12fb3aab98a4e Mon Sep 17 00:00:00 2001 From: luyifan Date: Wed, 22 Jul 2026 04:15:37 -0700 Subject: [PATCH] fix(slack): ignore stale thread sessions when gating thread-context reseed A session key that exists in the store but would be rolled to a fresh session by the reset policy (daily/idle/suspended) is not an active session. Treating it as active suppressed the first-turn Slack thread-history reseed after reset (#55239). _has_active_session_for_thread() now consults SessionStore._should_reset so a stale entry gates like a missing one, letting _fetch_thread_context reseed the fresh session with recent thread history. Fixes #55239. Salvaged from #55240 by @ooiuuii. --- plugins/platforms/slack/adapter.py | 15 ++++++++++- tests/gateway/test_slack_approval_buttons.py | 28 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/plugins/platforms/slack/adapter.py b/plugins/platforms/slack/adapter.py index 72f90124cd76..0d55878d5975 100644 --- a/plugins/platforms/slack/adapter.py +++ b/plugins/platforms/slack/adapter.py @@ -5357,7 +5357,20 @@ class SlackAdapter(BasePlatformAdapter): ) session_store._ensure_loaded() - return session_key in session_store._entries + entry = session_store._entries.get(session_key) + if entry is None: + return False + + # A key that exists but would be rolled to a fresh session by the + # reset policy (daily/idle/suspended) is NOT an active session: + # get_or_create_session() will reset it on the next real message, + # so treating it as active here would suppress the first-turn + # thread-history reseed (#55239). + should_reset = getattr(type(session_store), "_should_reset", None) + if callable(should_reset) and should_reset(session_store, entry, source): + return False + + return True except Exception: return False diff --git a/tests/gateway/test_slack_approval_buttons.py b/tests/gateway/test_slack_approval_buttons.py index 1d770ccf96ca..099139ee03b8 100644 --- a/tests/gateway/test_slack_approval_buttons.py +++ b/tests/gateway/test_slack_approval_buttons.py @@ -933,6 +933,34 @@ class TestSessionKeyFix: ) assert result is False + def test_stale_session_returns_false(self): + """A session key that exists but would be rolled by the reset policy + must NOT count as active — otherwise the reset-time first turn skips + the thread-history reseed (#55239).""" + adapter = _make_adapter() + + class Store: + config = MagicMock() + config.group_sessions_per_user = False + config.thread_sessions_per_user = False + _entries = { + "agent:main:slack:group:C1:1000.0": MagicMock() + } + + def _ensure_loaded(self): + return None + + def _should_reset(self, entry, source): + return "idle" + + adapter._session_store = Store() + + result = adapter._has_active_session_for_thread( + channel_id="C1", thread_ts="1000.0", user_id="U123" + ) + + assert result is False + # =========================================================================== # Thread engagement — bot-started threads & mentioned threads