fix(dingtalk): get_connected_platforms + fire-and-forget processing + null-toolsets guard#11605
Merged
Conversation
gateway cant add DingTalk platform without key and secret
…allback Fixes #11463: DingTalk channel receives messages but fails to reply with 'No session_webhook available'. Two changes: 1. **Fire-and-forget message processing**: process() now dispatches _on_message as a background task via asyncio.create_task instead of awaiting it. This ensures the SDK ACK is returned immediately, preventing heartbeat timeouts and disconnections when message processing takes longer than the SDK's ACK deadline. 2. **session_webhook extraction fallback**: If ChatbotMessage.from_dict() fails to map the sessionWebhook field (possible across SDK versions), the handler now falls back to extracting it directly from the raw callback data dict using both 'sessionWebhook' and 'session_webhook' key variants. Added 3 tests covering webhook extraction, fallback behavior, and fire-and-forget ACK timing.
Follow-ups to the salvaged commits in this PR:
* gateway/config.py — strip trailing whitespace from youngDoo's diff
(line 315 had ~140 trailing spaces).
* hermes_cli/tools_config.py — replace `config.get("platform_toolsets", {})`
with `config.get("platform_toolsets") or {}`. Handles the case where the
YAML key is present but explicitly null (parses as None, previously
crashed with AttributeError on the next line's .get(platform)).
Cherry-picked from yyq4193's #9003 with attribution.
* tests/gateway/test_config.py — 4 new tests for TestGetConnectedPlatforms
covering DingTalk via extras, via env vars, disabled, and missing creds.
* tests/hermes_cli/test_tools_config.py — regression test for the null
platform_toolsets edge case.
* scripts/release.py — add kagura-agent, youngDoo, yyq4193 to AUTHOR_MAP.
Co-authored-by: yyq4193 <39405770+yyq4193@users.noreply.github.com>
This was referenced Apr 17, 2026
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
Three DingTalk follow-up fixes in one PR — all from external contributors, all cherry-picked with authorship preserved:
gateway cant add DingTalk platform #11500 @youngDoo —
GatewayConfig.get_connected_platforms()was missing a DingTalk branch entirely. A DingTalk-configured gateway (via YAMLextra:or env vars) never appeared in the connected-platforms list, so status displays and iteration callers silently omitted it.fix(dingtalk): fire-and-forget message processing & session_webhook fallback #11518 @kagura-agent —
_IncomingHandler.process()currently awaits_on_messagedirectly, which blocks the SDK's recv loop for the full duration of agent processing. For a chat agent responding in 10-30s, this breaks the SDK's heartbeat deadline and causes WebSocket disconnects. Fix: dispatch viaasyncio.create_task()so ACK returns immediately. Also adds a defensivesession_webhookfallback (raw dict lookup for bothsessionWebhookandsession_webhookkeys) in case a future SDK revision changes the field name. Resolves issue [Bug]: dingtalk channle callback error #11463 (@sgjeff's "No session_webhook available" report).fix(dingtalk): fix multiple bugs in DingTalk platform adapter #9003 @yyq4193 (one-liner cherry-picked with
Co-authored-bytrailer) —hermes_cli/tools_config.pywas callingconfig.get("platform_toolsets", {}), which returnsNonewhen the YAML key is explicitly null (common withplatform_toolsets:and no value below). The next line's.get(platform)then crashed with AttributeError. Changed toconfig.get(...) or {}.The rest of #9003 is redundant with #11471 that landed earlier today (webhook regex, async
start(), asyncprocess(),CallbackMessage → ChatbotMessage) and includes one security regression (https?://allowing plain HTTP on the webhook allowlist) that I deliberately did not carry over. The tools_config.py one-liner is the only net-new legitimate change from #9003 and I'm landing it here with credit.Commits (all authorship preserved)
Merge with
--rebaseto preserve per-commit authorship.What I cleaned up
tests/gateway/test_dingtalk.py— kagura-agent's branch predated the group-gating test classes we merged earlier today via feat(dingtalk): add require_mention + allowed_users gating (parity with Slack/Telegram/Discord) #11564, and both sides appended new test classes at EOF. Kept both.What I deliberately dropped from #9003
r'^https?://(api|oapi)\.dingtalk\.com/'— this would re-allow plain HTTP on the webhook URL allowlist. Current main enforces^https://only and this is the right security posture. Rejected as a regression.async start(),async process(),CallbackMessage → ChatbotMessage, webhook regexoapiaccept) — already on main.logger.debug → logger.infofor inbound messages — debatable noise; every received message would land inagent.logat INFO. Not carrying over.Tests
tests/gateway/test_dingtalk.py— 50 passed (includes kagura-agent's 3 newTestIncomingHandlerProcesstests + our earlier regression tests)tests/gateway/test_config.py— 28 passed (includes 4 newTestGetConnectedPlatforms::test_dingtalk_*tests I added)tests/hermes_cli/test_tools_config.py— 31 passed (includestest_get_platform_tools_handles_null_platform_toolsetsregression test)Closes
Closes #11500, #11518, #9003 on merge. Should also resolve #11463 (pending @sgjeff pulling latest main).