fix(slack): progress/status card lifecycle — edit in place, always clear, survive transients - #70189
Merged
Conversation
Contributor
૮ >ﻌ< ა ci reviewran on be14828 ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job1 visual diff. inline evidence upload failed. Failed to upload diff-665a0833239e-onboarding-overlay-diff.png with gh image (exit code 1): Error uploading /home/runner/work/_temp/e2e-evidence/diff-665a0833239e-onboarding-overlay-diff.png: step 0 (get upload token): uploadToken not found on repo page — do you have write access to NousResearch/hermes-agent? (or, if NousResearch enforces SAML SSO, authorize at https://github.com/orgs/NousResearch/sso) |
Progress/status callbacks (context-pressure, compression retries,
model fallback) route through _send_or_update_status_coro, which
edits the previous bubble for the same status_key when the adapter
implements send_or_update_status — but only Telegram did. On Slack
every status event posted a fresh thread message, so a compression
retry loop spammed a dozen out-of-order bubbles into the thread
('Context too large 1/3... 2/3... 3/3', fallback switches, etc.).
Implement send_or_update_status on the Slack adapter following the
Telegram pattern (#30045): first call posts and caches the message ts
per (channel, thread, status_key); subsequent calls edit that message
via chat.update. Edit failure drops the cached ts and falls back to a
fresh send. Cache is FIFO-bounded.
When reply_in_thread=false, top-level channel events carry their own
message ts as metadata.thread_id for session keying. Calling
assistant.threads.setStatus on that ts activated a Slack assistant
thread ('is thinking...') before the actual response was sent, and the
flat reply then never cleared it.
send_typing now routes through the same _resolve_thread_ts synthetic-
thread guard as message sending, and the gateway threads message_id
through progress/status metadata so the adapter can distinguish real
threads from synthetic top-level session keys.
Reapplied from #18859-sibling PR #17184 by @dorukardahan (both commits:
fix + progress-metadata test) onto current main via 3-way apply — the
original patched gateway/platforms/slack.py, moved to
plugins/platforms/slack/adapter.py in the plugin migration.
The Slack adapter honours platforms.slack.extra.reply_in_thread=false
in _resolve_thread_ts, but the Gateway's progress-message path forced
event_message_id as the thread_id for Slack regardless. The first
progress message ('terminal: …', 'Processing…') created a thread that
all subsequent edits and the final answer inherited, defeating the
user's reply_in_thread=false setting.
Check the live Slack adapter's reply_in_thread flag before applying the
event_message_id fallback, and treat a synthetic source.thread_id (==
the event's own message ts, used only for session keying) as 'no
thread' so progress messages stay at the channel/DM top level.
Folds both #18859 commits (reply_in_thread gate + synthetic thread_id
drop) into main's extracted _resolve_progress_thread_id helper — the
original patched the pre-refactor inline block; the gate now composes
as a keyword argument so Mattermost/other platforms keep the default
fallback behavior.
Widening for #24117 ('is thinking...' stuck after the response was sent): the stuck-thinking class is a missing-cleanup-on-error-path bug. send()'s status clear was gated on thread_ts already being resolved and on reaching the normal post-message path, which left the Slack Assistant status visible when a turn ended through any sibling exit: - exception BEFORE _resolve_thread_ts (slash-context handling, formatting, DM resolution) — the 'if thread_ts: stop_typing' clear never ran - empty/whitespace-only final response (no_text guard early-return) - ephemeral slash replies (Slack only auto-clears assistant status on real thread replies; ephemerals never count) Add _clear_thread_status_quietly() — a best-effort stop_typing wrapper that never masks the caller's SendResult — and wire it at every send() exit plus the finalize paths of edit_message. stop_typing already handles the untracked-thread fallback (clearing an unset status is a no-op on Slack's side), so this is pure coverage widening. Also add the #18859 unit tests for _resolve_progress_thread_id's new reply_in_thread gate (synthetic-thread drop, real-thread keep, event-id fallback suppression, default unchanged). A/B: 3 of the 4 new status-clear tests fail with the adapter widening reverted and pass with it applied; the fourth pins the existing cleanup-must-not-mask-result contract.
- rt.cms012@gmail.com -> trac3r00 (#68378; commit authored as 'Minseo-Choi' — trac3r00's display name, same account) - 15167896+2001Y@users.noreply.github.com -> 2001Y (#64267) - hello@jeromeiveson.com -> Trantor-develops (#57196) - boumagent@gmail.com -> patp (#18859) - dorukardahan@hotmail.com -> dorukardahan (#17184) was already mapped.
… tests CI shards run without the slack extras; the two #64267 tests import the real SDK (SlackApiError, the lazy-rebind path) and errored with ModuleNotFoundError. Skip on bare environments — classification coverage for stdlib exception types (OSError/TimeoutError/cert errors) still runs everywhere.
teknium1
force-pushed
the
slack/c6-progress-cards
branch
from
July 23, 2026 16:49
b05d6b4 to
be14828
Compare
This was referenced Jul 23, 2026
19 tasks
1 task
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.
Summary
Slack progress/status messages no longer hang, duplicate, or outlive the reply: status bubbles edit in place, finalization always clears status (including error paths), transient network failures don't kill progress edits, and stale progress messages are cleaned up.
Fixes #36780, #24117.
Changes
SlackAdapter.send_or_update_status— status bubbles edit in place instead of posting new messages; gateway dispatches via the existinggetattrhook, zero gateway changes (fix(slack): edit status bubbles in place instead of posting new ones #68378).edit_message(timeouts/connection drops → retryable; TLS errors stay permanent) + overflow-path transient-skip (fix(slack): preserve progress edits on network failures #64267).reply_in_thread=falserespected for progress (fix(gateway): respect reply_in_thread=false for Slack progress messages #18859), no assistant status on synthetic top-level threads (fix(slack): avoid assistant status on synthetic top-level threads #17184).Credits
Salvaged with authorship preserved: #68378 (@trac3r00), #64267 (@2001Y), #57196 (@Trantor-develops), #18859, #17184.
Flag: #68552 (default tool progress off) NOT included — behavior-default change needing explicit maintainer sign-off; recommend separate decision.
Validation
tests/gateway/ -q -k slackInfographic