fix(dingtalk): fix async compatibility with dingtalk-stream SDK v2+#9131
Closed
Jsoneft wants to merge 1 commit into
Closed
fix(dingtalk): fix async compatibility with dingtalk-stream SDK v2+#9131Jsoneft wants to merge 1 commit into
Jsoneft wants to merge 1 commit into
Conversation
The dingtalk-stream SDK migrated to a fully async architecture. This commit fixes three bugs that caused the DingTalk adapter to silently fail with newer SDK versions: 1. `_run_stream`: replace `asyncio.to_thread(client.start)` with `await client.start()`. The SDK's `start()` is now an async coroutine; wrapping it in `to_thread` created an unawaited coroutine object and never established the WebSocket connection. 2. `_IncomingHandler.process`: rewrite as `async def` and add the missing `ChatbotMessage.from_dict(callback_message.data)` conversion. The SDK now calls `await handler.process(callback_message)` where `callback_message` is a `CallbackMessage` container — the actual chatbot fields live in `.data` and must be parsed explicitly. The old sync implementation caused `object tuple can't be used in 'await' expression` errors and dropped all incoming messages. 3. `_DINGTALK_WEBHOOK_RE`: broaden the SSRF-guard regex from `api.dingtalk.com` to any `*.dingtalk.com` subdomain. DingTalk's `sessionWebhook` URLs use `oapi.dingtalk.com`, so the old pattern silently discarded every webhook, making replies impossible. Also adds an immediate "⏳ 思考中..." acknowledgement message sent to the user as soon as a message is received, before the agent processes it, to provide responsive feedback. Made-with: Cursor
Contributor
|
Closing as superseded by #11471 (#11471) which salvaged @kevinskysunny's minimal fix (#11257) and added a follow-up for the broken Thanks for the fix — a lot of contributors hit this SDK break at the same time. Your investigation helped confirm the root cause. |
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
The DingTalk adapter was written against an older synchronous version of the
dingtalk-streamSDK. The SDK has since migrated to a fully async architecture, breaking the adapter in three distinct ways that caused all incoming messages to be silently dropped and all replies to fail.Bug 1 —
_run_streamusedasyncio.to_thread()on an async coroutineDingTalkStreamClient.start()is now anasync def. Wrapping it inasyncio.to_thread()(which is meant for blocking sync functions) created a coroutine object that was passed as a callable but never awaited, so the WebSocket connection was never established.Bug 2 —
_IncomingHandler.processwas sync and missing message conversionThe SDK now dispatches via
await handler.raw_process(callback_message)→await handler.process(callback_message). Two problems:processwas a plaindef, causingobject tuple can't be used in 'await' expressionCallbackMessagecontainer; the actual chatbot fields live in.dataand must be converted viaChatbotMessage.from_dict(callback_message.data)before useBug 3 — SSRF-guard regex rejected valid
sessionWebhookURLsDingTalk's
sessionWebhookURLs use theoapi.dingtalk.comsubdomain, but the regex only whitelistedapi.dingtalk.com. Every incoming webhook was silently discarded, making replies impossible.Enhancement — immediate acknowledgement message
Sends a
⏳ 思考中...text message to the user as soon as a message arrives, before the agent begins processing. This provides responsive feedback during longer inference calls.Test plan
⏳ 思考中...appears immediatelycoroutine was never awaitedortuple can't be used in awaitwarnings in logssessionWebhookis stored and used correctly for repliesEnvironment
Tested with
dingtalk-stream0.x (async SDK), Python 3.12.Made with Cursor