feat(discord): final response inline, tool progress in thread - #68409
feat(discord): final response inline, tool progress in thread#68409HangGlidersRule wants to merge 2 commits into
Conversation
When auto-thread fires, the Discord adapter was rewriting source.chat_id to the auto-created thread ID, causing both tool progress AND the final text response to go into the thread. Fix: keep source.chat_id as the parent channel when auto-thread creates a thread. source.thread_id already points to the thread, so tool-progress messages route there via _resolve_progress_thread_id. The final text response now lands inline in the parent channel. This mirrors Slack's behaviour: tool progress in a thread, final response flat in the channel. Tests cover: - Auto-thread: chat_id is parent channel, not thread - No auto-thread: chat_id is message channel (unchanged) - Progress thread routing: thread_id used when auto-thread on - Progress thread routing: None when auto-thread off - Existing reply_mode and thread_persistence tests pass (no regression)
Free-response channels were excluded from auto-threading by the skip_thread check (is_free_channel was OR'd into skip_thread). This meant tool progress appeared inline in free-response channels instead of in a thread. Fix: remove is_free_channel from skip_thread so free-response channels also get auto-threaded. Channels explicitly listed in DISCORD_NO_THREAD_CHANNELS still skip auto-threading. Tests cover: - Free-response channel not skipped from auto-thread - Explicit no-thread channel still skipped - Free channel also in no_thread list still skipped - Existing reply_mode/thread_persistence/mattermost tests pass
teknium1
left a comment
There was a problem hiding this comment.
Thanks for isolating the current auto-thread routing behavior. The premise is present on current main: plugins/platforms/discord/adapter.py:7577-7606 assigns the created thread as chat_id and retains it as thread_id.
Problems
- Changing only
chat_idcannot make final text inline.gateway/platforms/base.py:5778builds final metadata fromsource.thread_id, andgateway/platforms/base.py:5918-5923sends with it. Discord then givesmetadata.thread_idprecedence overchat_id(plugins/platforms/discord/adapter.py:2910-2928). The final response would still target the thread. - The
skip_threadchange reverses an intentional contract: free-response channels are documented as inline lightweight chat (website/docs/user-guide/messaging/discord.md:19) and covered bytests/gateway/test_discord_free_response.py:658-685; commitd557544560b0492be67b320f06033e9362c2cf09added that behavior. gateway/session.py:1114-1133keys sessions using bothchat_idandthread_id, so this source-shape change needs compatibility coverage for existing auto-thread sessions.
Suggested changes
- Preserve the free-response skip.
- Separate final-delivery metadata from progress metadata, including streaming, and add an end-to-end routing test rather than assignment-only tests.
Automated hermes-sweeper review.
| no_thread_channels_raw = os.getenv("DISCORD_NO_THREAD_CHANNELS", "") | ||
| no_thread_channels = {ch.strip() for ch in no_thread_channels_raw.split(",") if ch.strip()} | ||
| skip_thread = bool(channel_keys & no_thread_channels) or is_free_channel | ||
| skip_thread = bool(channel_keys & no_thread_channels) |
There was a problem hiding this comment.
This reverses the documented free-response contract. website/docs/user-guide/messaging/discord.md:19 and tests/gateway/test_discord_free_response.py:658-685 require these channels to remain inline so every unmentioned message does not create a new thread; retain or is_free_channel here.
| @@ -7265,7 +7275,7 @@ async def _handle_message( | |||
| # Build source | |||
There was a problem hiding this comment.
Changing chat_id alone does not redirect the final response inline: BasePlatformAdapter builds final metadata from source.thread_id and sends with it (gateway/platforms/base.py:5778-5923), while Discord gives that metadata precedence over chat_id (adapter.py:2910-2928). This needs a separate final-delivery metadata path.
Problem
When
DISCORD_AUTO_THREADis enabled, the Discord adapter rewritessource.chat_idto the auto-created thread ID (line 7245:effective_channel = auto_threaded_channel or message.channel). This causes both tool-progress messages and the final text response to go into the thread.The desired behaviour (matching Slack) is: tool progress goes into a thread, the final text response goes inline in the channel. The channel stays clean; tool noise is isolated.
Fix
When auto-thread creates a thread, keep
source.chat_idas the parent channel ID so the final response is delivered inline.source.thread_idalready points to the auto-created thread, so tool-progress messages route there via the existing_resolve_progress_thread_id()mechanism.One-line logic change in
plugins/platforms/discord/adapter.py:No changes to
gateway/run.py— progress routing already works correctly whensource.thread_idis set.Changes
plugins/platforms/discord/adapter.py: keepchat_idas parent channel when auto-threadedtests/gateway/test_discord_autothread_chatid.py: 4 new testsTest Plan
test_discord_autothread_chatid.py— 4/4 passedtest_discord_reply_mode.py— 29/29 passed (no regression)test_discord_thread_persistence.py— 12/12 passed (no regression)