Repository navigation
fix(channel): cancel queued work under the agent-scoped session key - #3316
Merged
zhayujie merged 1 commit intoSep 29, 2026
Merged
Conversation
ChatChannel.produce() files a session's queue under the routed Agent's key
("agent::session"), but cancel_session() and cancel_message() looked the bare
session id up, so for any Agent other than the default one they found no queue
and left the queued messages running: #reset on a bound channel instance, or
recalling a queued Feishu message, reset nothing.
Both now resolve the key the same way produce() does, through the AgentBridge's
own scoped_session_key, and the two callers pass the Agent that accepted the
turn.
Owner
|
Merged, thanks @Lesereingrape! Routing both cancel paths through One follow-up on master (3e74cd0): the web console's session delete handler had the same gap. It called |
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 #3315
ChatChannel.produce()files a session's queue under the routed Agent's key (bridge/agent_bridge.py:1205-1207-- "keep legacy token keys for the default agent, namespace the rest"), whilecancel_session()andcancel_message()looked the queue up with the bare session id (channel/chat_channel.py:636,:666). For any Agent other than the default one -- a channel instance created with anagent_idin the console stampsbound_agent_idon every inbound message (app.py:193,agent/routing.py:57-78) -- the lookup missed, so#reset(plugins/godcmd/godcmd.py:340) left the queued messages in place to be processed after the memory was cleared, and recalling a queued Feishu message (channel/feishu/feishu_channel.py:697) still got answered. Thefutureshalf ofcancel_sessionmissed for the same reason, sinceconsume()records futures under the queue key (:614-617).What changed
channel/chat_channel.py-- both cancel paths now resolve the key the same way the enqueue path does:_queue_key(session_id, agent_id=None)goes throughAgentBridge.scoped_session_key, the helperbridge/agent_bridge.py:673-684already provides for exactly this ("cancel and steer lookups must be scoped"); if the bridge cannot be reached it falls back to the bare session id, the same wayproduce()falls back when routing fails, so a default-Agent install behaves byte-for-byte as before,cancel_session(session_id, agent_id=None)andcancel_message(session_id, message_id, agent_id=None)use it forself.sessionsandself.futures.plugins/godcmd/godcmd.py--#resetpassese_context["context"].get("agent_id"), which is the valueroute_context()wrote onto the context on the way into the queue.channel/feishu/feishu_channel.py--_message_sessionsrecords(session_id, agent_id)and is written afterproduce()has resolved the route, so a recall can rebuild the key; the two halves are passed tocancel_message. Readingcontext["agent_id"]beforeproduce()would store the pre-routing value (or nothing), and a bound Agent that has since been disabled falls back to the default route insideproduce()(agent/routing.py:71-77), so the value after the call is the only one that can match the key.How it was verified
04eb97cf: with the queue filed underteam-a::web:u1-- which is whatproduce()does, pinned by its own test case --cancel_session("web:u1")leftqsize() == 1, andcancel_message("web:u1", ...)reportedqueued=0while the message stayed in the queue. Running the two test files as submitted against that pristine checkout gives10 failed, 10 passed; on this branch the same two files give20 passed(addingtests/test_robustness_fixes.py, which already covers the default-Agent path, gives25 passed).pytest tests/ -q): pristine master32 failed, 2285 passed; this branch32 failed, 2294 passed. TheFAILEDlines are the same set in both runs (diffof the sorted lists is empty), so nothing regressed -- those are pre-existing environment-dependent failures on this Windows host, not caused by this diff. The nine extra passes are the new cases.ruff check channel/chat_channel.py channel/feishu/feishu_channel.py plugins/godcmd/godcmd.py tests/test_cancel_session_agent_scope.py tests/test_feishu_message_recall.py --select F --ignore F403,F405-- clean.