Skip to content

fix(dingtalk): isolate websockets.connect monkey-patch from DingTalk stream SDK#17364

Closed
spike2204 wants to merge 1 commit into
NousResearch:mainfrom
spike2204:fix/dingtalk-websockets-proxy
Closed

fix(dingtalk): isolate websockets.connect monkey-patch from DingTalk stream SDK#17364
spike2204 wants to merge 1 commit into
NousResearch:mainfrom
spike2204:fix/dingtalk-websockets-proxy

Conversation

@spike2204

Copy link
Copy Markdown

Summary

When the DingTalk stream SDK is imported, it monkey-patches websockets.connect globally, breaking other WebSocket consumers (Feishu, WeCom, etc.). This PR captures the pristine websockets.connect reference before the SDK import and provides _install_dingtalk_websockets_proxy() to restore it.

Changes

  • Save _PRISTINE_WEBSOCKETS_CONNECT before dingtalk-stream import
  • Add _install_dingtalk_websockets_proxy() that patches websockets.connect to route DingTalk traffic through the SDK's modified version while preserving standard behavior for all other callers
  • Call the proxy installer in connect()

Related

Part of the DingTalk adapter enhancement series — see #12769 for the umbrella PR.

…am SDK

The Feishu adapter monkey-patches websockets.connect with an async def
wrapper, turning the return value into a coroutine.  This breaks the
dingtalk-stream SDK's `async with websockets.connect(uri)` call at
dingtalk_stream/stream.py:74.

Capture the pristine websockets.connect at our import time and install
it on dingtalk_stream.stream so the SDK always uses the original
regardless of later monkey-patches.

- Snapshot _PRISTINE_WEBSOCKETS_CONNECT at module import
- _install_dingtalk_websockets_proxy() replaces dingtalk_stream.stream.websockets
  with a SimpleNamespace holding the original connect + exceptions
- Called once during connect() — idempotent, safe no-op when deps missing to #
@teknium1

Copy link
Copy Markdown
Contributor

This looks implemented on current main by fixing the root cause at the Feishu wrapper site.

Automated hermes-sweeper review evidence:

  • PR fix(dingtalk): isolate websockets.connect monkey-patch from DingTalk stream SDK #17364 worked around the Feishu/DingTalk websockets.connect interaction by giving DingTalk a pristine connect reference; its diff describes the break as Feishu replacing websockets.connect with an async def wrapper, which broke async with websockets.connect(...) in dingtalk_stream.
  • Current main includes merged PR fix(gateway): make Feishu ws connect override sync to preserve context manager (#25388) #25491, commit 71191b7e8e075037a814f77d37d4609e97f12029, which changes gateway/platforms/feishu.py from async def _connect_with_overrides(...) to regular def _connect_with_overrides(...).
  • In current main, gateway/platforms/feishu.py:1305 defines the wrapper synchronously and gateway/platforms/feishu.py:1310 returns original_connect(*args, **kwargs) directly, preserving the original async context-manager return value for DingTalk and other consumers.
  • The fixing commit is included in release tag v2026.5.16 and later.

Thanks for the original narrow DingTalk-side fix; the same bug class has since been addressed at the shared Feishu monkey-patch source.

@teknium1 teknium1 closed this Jun 10, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/dingtalk DingTalk adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants