feat(gateway): auto-delete Discord tool progress bubbles - #26055
Closed
nazirulhafiy wants to merge 13 commits into
Closed
nazirulhafiy wants to merge 13 commits into
nazirulhafiy wants to merge 13 commits into
Conversation
Contributor
20 tasks
Adds delete_message() to the Discord adapter and wires it into both __reset__ handlers in the progress message loop, plus the final edit drain path. When a content bubble lands after a tool batch, the progress bubble (🔧, 📖, 💻) is now deleted instead of left orphaned in the channel, reducing chat clutter. - gateway/platforms/discord.py: new delete_message() method - gateway/run.py: delete in normal __reset__, CancelledError drain, and final-edit path — with capability gate via 'type(adapter).delete_message is not BasePlatformAdapter.delete_message'
…o-delete - Final-drain path (3rd location) now logs delete attempts and errors, matching the __reset__ handlers — so lingering bubbles are diagnosable. - Adds config key `display.auto_delete_tool_progress` (default: true). Set to `false` in config.yaml to disable progress bubble auto-deletion. - All three delete locations respect the toggle.
…eanup Bug: The __reset__ delete handler gated deletion on can_edit, which flips to False on any edit failure (e.g. Discord 429 rate limit on rapid tool calls). Once can_edit went False, every subsequent progress bubble became permanent. Fix: - Add can_delete flag alongside can_edit - Use can_delete in the __reset__ delete gate instead of can_edit - Track can_delete = False only when delete_message() actually fails, not when edit fails - Apply same failure tracking to CancelledError drain and final drain delete paths This ensures Discord rate-limiting an edit mid-session no longer disables progress bubble deletion.
…o-delete Adds 8 tests covering: - Capability check: overridden vs base adapter delete_message detection - Adapter behavior: success, failure, and multiple sequential calls - Config resolution: auto_delete_tool_progress default, explicit off, and per-platform overrides via display_config Pragmatic approach: tests verify the component pieces directly (capability checks, adapter contract, config resolver) rather than requiring a full _run_agent integration test, since the delete code path requires an active Discord adapter + live agent loop that doesn't map cleanly to the mock-based test harness. Part of PR #18306.
…nterrupt Bug: When the agent finishes normally (not interrupted/cancelled), _run_still_current() returned False and send_progress_messages() exited via early return at the top of the main loop body. This bypassed the CancelledError handler where the delete calls live, so tool progress bubbles (e.g. ⏰ cronjob) lingered permanently in Discord. Fix: Added delete logic at the early-return site (normal completion) matching the existing pattern in the CancelledError drain handler. All three exit paths now clean up: normal completion, __reset__ drain, and final-drain. Part of PR #18306.
- Add delete to first _run_still_current() check (race: run completes before __reset__ signal arrives). Tagged (run-completed). - Move __reset__ delete outside can_edit gate (Discord supports delete even when edit fails). Fixes nested-gate bug May 2026.
- Add pending_progress_cleanup.json queue at ~/.hermes/gateway/ - Record (platform, chat_id, message_id) on bubble creation - Clear record on successful delete (4 existing paths + startup drain) - Retry failed deletes up to 5 attempts - GatewayRunner.start() drains stale records after adapter connect - Add TestPersistedProgressCleanup (3 tests: round-trip, startup success, startup failure retries) Extends PR #18306 (auto-delete tool progress bubbles).
…w() with timezone-aware alternative; B2: unify auto_delete_tool_progress config source via resolve_display_setting
austinpickett
requested changes
May 19, 2026
austinpickett
left a comment
Collaborator
There was a problem hiding this comment.
Please use .github/PULL_REQUEST_TEMPLATE.md and fix merge conflicts
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
This PR makes Hermes clean up Discord tool progress bubbles after they are no longer useful.
Hermes can show little “I’m working on it” messages while tools run:
Those bubbles are helpful while Hermes is working.
But once the final answer is delivered, they should not hang around forever like abandoned scaffolding.
This PR makes them disappear automatically after successful runs, while still preserving useful breadcrumbs when something fails.
Problem
Hermes already had progress bubbles, and Discord already had the ability to delete messages.
The missing piece was the cleanup path.
In practice, this could happen:
For users, this makes Discord channels feel noisy and stale.
For maintainers, the confusing part was that the config setting looked correct:
…but the gateway was not always tracking enough cleanup state to actually delete the bubbles later.
Solution
This PR wires progress cleanup to the setting users expect:
When enabled:
delete_message()capabilityauto_delete_tool_progress: falsepreserves the old behaviorIn plain English:
Technical details
This PR updates the gateway progress lifecycle so that:
display.auto_delete_tool_progressenables cleanup tracking directlyKey behavior change:
now means both:
Previously, those two parts could drift apart.
User-facing behavior
Successful run
Gateway restart with pending bubbles
Failed run
Files changed
gateway/platforms/discord.pygateway/run.pytests/gateway/test_progress_auto_delete.pytests/gateway/test_run_cleanup_progress.pyTesting
Ran targeted gateway tests:
Result:
Also manually verified locally:
Breaking changes
None.
The feature is controlled by:
display.auto_delete_tool_progressDefault behavior is auto-delete enabled.
Users who prefer the old “leave progress bubbles visible” behavior can set:
Reviewer note
This PR overlaps with earlier progress cleanup work, but the current branch fixes the practical config-path gap:
So the goal is not just “Discord can delete messages.”
The goal is: