fix: isolate empty-mention waiter by sender without changing default session scope - #9378
Open
hedssaz wants to merge 1 commit into
Open
fix: isolate empty-mention waiter by sender without changing default session scope#9378hedssaz wants to merge 1 commit into
hedssaz wants to merge 1 commit into
Conversation
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
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.
Fixes #9377
In group chats, an empty mention (
@botwith no text) starts a 60ssession_waiterto wait for follow-up content. The waiter is registered withDefaultSessionFilter, whose key isunified_msg_origin(group-level) and doesnot include the sender. As a result, the first non-empty message from any
other member during the wait window is intercepted, gets a bot
Atprepended,and is re-dispatched — producing a reply to the wrong user / wrong context. Full
analysis, reproduction and captured logs are in #9377.
This PR fixes the empty-mention flow without changing the default session
scope, so third-party plugins that rely on the current group-level default are
unaffected.
Why not simply change
DefaultSessionFilterChanging the default from
unified_msg_originto include the sender wouldchange the default runtime behavior of
session_waiter, which is exported toplugins through
astrbot.api.util. The group-level default has been in placesince v3.5.4 (~15 months, 138 stable releases) and is relied upon by real
plugins that omit
session_filter=, for example:astrbot_plugin_kimi_datasource_apiregisters a waiter manually withSessionWaiter(DefaultSessionFilter(), event.unified_msg_origin, ...). Theregistration key is the raw UMO while lookups go through
DefaultSessionFilter.filter(event). If the default changed, the keys would nolonger match and its login waiter would never trigger.
astrbot_plugin_decision_rouletteandastrbot_plugin_TurtleSoupuse thedefault filter to collect input from multiple group members; a per-sender
default would only accept the initiator.
So the fix is scoped to the one place that actually needs per-sender isolation.
Modifications
astrbot/core/utils/session_waiter.py: addSenderSessionFilter, a newoptional
SessionFilterkeyed byunified_msg_origin+sender_id.DefaultSessionFilteris unchanged, and no new names are added to thepublic
astrbot.api.utilsurface. This is purely additive.The key uses a length-prefixed encoding (
f"{len(umo)}:{umo}:{sender}")rather than plain concatenation: both the UMO and the sender id are arbitrary
platform strings (e.g. Telegram topic-group UMOs contain
#), so a plainseparator would allow constructible key collisions that defeat the isolation.
astrbot/builtin_stars/astrbot/main.py: the empty-mention waiter now passessession_filter=SenderSessionFilter(). When the sender id is unavailable itskips waiting entirely, to avoid silently degrading back to group scope.
tests/test_session_waiter_cross_user.py(new): 7 session-key regressiontests (module loaded standalone).
tests/unit/test_empty_mention_sender_scope.py(new): 3 production-wiringtests driving the real
Main.handle_empty_mentionandMain.handle_session_control_agent(following the existingMain.__new__(Main)pattern intests/unit/test_group_chat_context_wiring.py).The other issues noted in #9377 (empty-
message_strmessages being swallowedduring the wait window;
_cleanup/FILTERSbehavior with same-key waiters)are independent of the session key and will be handled in separate PRs.
Screenshots or Test Results
Session-key coverage (
tests/test_session_waiter_cross_user.py):test_default_filter_returns_umo_unchanged— the default filter still returnsunified_msg_origin(locks the default semantics in place);test_default_manual_umo_registration_still_triggers— reproduces thekimi_datasource_apimanual-registration pattern and asserts it stilltriggers (guards against regressing plugins that depend on the group default);
test_sender_filter_isolates_users_in_group— another member's message is nolonger intercepted (primary goal);
test_sender_filter_accepts_original_sender— the original sender's follow-upis still captured;
test_sender_filter_key_is_collision_free— UMOs / sender ids containingseparator characters (
#,:) cannot produce colliding keys;test_sender_filter_isolates_users_with_hash_in_umo— isolation holds forTelegram topic-group style UMOs that contain
#;test_sender_filter_does_not_leak_across_conversations— the same user'smessages in other groups / DMs are not intercepted.
Production-wiring coverage (
tests/unit/test_empty_mention_sender_scope.py,drives the real handlers rather than a re-implementation):
test_other_members_message_passes_through— BOB's message is not stopped,not modified, and not re-enqueued while ALICE's waiter is active;
test_original_senders_followup_is_redispatched— ALICE's follow-up gets thebot
Atinjected, is stopped and re-enqueued, and the waiter is cleaned up;test_empty_sender_id_skips_waiting— with no reliable sender id thehandler finishes immediately and registers no waiter.
Verified that the wiring tests actually guard the fix: with the
main.pychange reverted to master, tests 8 and 10 fail; with the fix in place all 10
pass.
Checklist
via issues/emails. (Bug fix, proposed in [Bug] 群聊中空提及等待器会截获其他成员的消息(session_waiter 未绑定发送者) #9377.)
provided above.
Summary by Sourcery
Fix empty-mention session handling in group chats by isolating the waiter per sender while preserving existing group-level session semantics.
Bug Fixes:
Enhancements:
Tests: