mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-26 21:26:39 +00:00
* fix(channels): run Discord connection-repository work on the Gateway loop discord.py delivers messages on a private loop in the client thread, and the Discord adapter awaited the channel-connection repository there even though its SQLAlchemy engine and pool belong to the Gateway loop. On PostgreSQL the first Discord message after the Gateway used the pool failed with "got Future attached to a different loop" and was dropped; on SQLite a pool-exhausting burst failed with "Queue is bound to a different event loop" and left the pool's wait queue bound to the Discord loop, so the Gateway's own queries then failed the same way. Resolve the identity together with the intake commit, and run /connect binding, on the Gateway loop through _submit_threadsafe_coroutine, as Telegram, Feishu and DingTalk already do. Bind replies return through _run_on_discord_loop, and start()/stop() now open and drain the cross-thread submissions. * docs(changelog): reference #6214 for the Discord connection-loop fix * fix(channels): correct the unscheduled Discord bind comment and pin it When _submit_threadsafe_coroutine refuses the bind, base.py closes the coroutine, so consume_oauth_state never runs and the one-time code stays valid; only the Discord message is swallowed. Say that instead of claiming the code is consumed, and pin both halves with a test: the attempt is handled (never a chat turn) and the code still binds later. * fix(channels): undo Discord typing when the Gateway hand-off fails Since identity resolution moved to the Gateway loop, both inbound paths started typing and the ack reaction as soon as the hand-off was scheduled. A lookup that then raised (database outage, pool-checkout timeout) dropped the message but left an endless typing loop and a success reaction behind. The hand-off now returns its completion future (new Channel._submit_threadsafe_coroutine_future, which the bool helper wraps) and the Discord side waits on it through asyncio.shield. Typing still registers before the hand-off settles, so a fast reply's _stop_typing cannot run first; the ack reaction waits for the commit. On failure, or when stop() drains the hand-off, the indicator this message started is stopped (never one another in-flight message owns) and no ack is added. * fix(channels): keep shared Discord typing alive for dependent messages Two messages to the same target share one typing task: the first starts it, a later one reuses it. If the creator's hand-off failed after a follower had committed, or while the follower was still pending, the creator stopped the indicator the follower relied on, and nothing restored it while the follower's request ran. Count the hand-offs that depend on each typing task. A pending or committed hand-off holds the task (a commit keeps its hold until a reply stops the indicator), a failed one releases its hold, and the indicator is stopped only when the failed message started it and no hold remains. The count is dropped when the task ends or the channel cancels typing. --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>