Skip to content

fix(discord): add typing_loop_max_lifetime deadline guard for orphaned typing loops - #90179

Open
JinUltimate1995 wants to merge 3 commits into
NousResearch:mainfrom
JinUltimate1995:fix/discord-typing-loop-max-lifetime-90151
Open

fix(discord): add typing_loop_max_lifetime deadline guard for orphaned typing loops#90179
JinUltimate1995 wants to merge 3 commits into
NousResearch:mainfrom
JinUltimate1995:fix/discord-typing-loop-max-lifetime-90151

Conversation

@JinUltimate1995

Copy link
Copy Markdown

Summary

Issue #90151: the persistent typing loop in DiscordAdapter.send_typing had no natural exit condition other than stop_typing() or a non-429 error. If stop_typing never reached the adapter (e.g. a crashed run, or a thread-vs-parent-channel key mismatch), the loop ran forever and Discord kept showing the "…is typing" badge until the gateway restarted.

Adds a configurable max-lifetime deadline (discord.typing_loop_max_seconds, default 600s, 0 disables). The loop now exits cleanly when the deadline elapses, bounding the post-typing sleep so it wakes up in time to honor the guard.

Changes

  • hermes_cli/config_defaults.py — adds the new typing_loop_max_seconds key (default 600).
  • plugins/platforms/discord/adapter.py:
    • Adds _load_typing_loop_max_seconds() config loader.
    • Initializes self._typing_loop_max_seconds in __init__.
    • Adds a deadline guard at the top of _typing_loop and bounds the post-typing sleep by the deadline.
  • tests/gateway/test_discord_typing_max_lifetime.py — new test file:
    • test_loop_expires_after_max_lifetime — verifies the loop exits once the deadline elapses.
    • test_stop_typing_still_works_with_deadline — verifies stop_typing still cancels cleanly.
    • test_zero_max_seconds_disables_deadline — verifies setting 0 disables the guard.

Related

Closes #90151.

Complements #85425 (cleanup race) and #85435 (reap bounding) — those address related races, but the core max-lifetime problem remained unaddressed.

Test Results

  • New tests: 3/3 pass.
  • Existing test_discord_send.py: 11/11 pass.
  • All tests/gateway/test_discord_*.py: 262/262 pass.
  • Config tests: 78/78 pass.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

JinUltimate and others added 3 commits August 19, 2026 03:50
…ronment

For stdio catalog entries using auth.type: api_key, the credentials
declared in auth.env were saved to .env by _prompt_env_vars() but never
wired into the generated mcp_servers.<name> configuration. Without an
env-backed reference, _build_safe_env() excluded them and the stdio child
started without its API key, causing silent authentication failures.

Now _build_server_config translates each auth.env variable into a safe
${VAR} reference for stdio transports, mirroring how HTTP api_key
manifests get a Bearer header template.

Fixes NousResearch#89316.
…atching (ignoring metadata)

The prefix-matching logic used full dict equality (==), which fails when
the agent modifies messages during the conversation loop — timestamps are
added, content may be truncated, and fields like finish_reason/reasoning
are stamped on. This caused _turn_transcript_messages to return ALL
messages instead of only the current turn, bloating the run.completed
SSE event's messages field.

Fix: compare role + content (with prefix tolerance for truncated
strings), ignoring metadata fields. Fixes NousResearch#89891.
…d typing loops

Issue NousResearch#90151: the persistent typing loop in DiscordAdapter.send_typing had
no natural exit condition other than stop_typing() or a non-429 error.
If stop_typing never reached the adapter (crashed run, thread-vs-parent
key mismatch), the loop ran forever until gateway restart.

Adds a configurable max-lifetime deadline
(discord.typing_loop_max_seconds, default 600s, 0 disables).
The loop now exits cleanly when the deadline elapses, bounding the
post-typing sleep so it wakes up in time to honor the guard.
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins tool/mcp MCP client and OAuth platform/discord Discord bot adapter area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 19, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #90087 for the Responses turn-boundary and MCP auth.env repairs. This PR additionally contains Discord typing-loop work, which should be submitted as a focused follow-up rather than bundled with those already-open fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/discord Discord bot adapter sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages tool/mcp MCP client and OAuth type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord typing indicator loops can orphan and run indefinitely (no max lifetime)

2 participants