feat(gateway/dingtalk): env-based config and richer msgtype handling#8960
Closed
sputnicyoji wants to merge 1 commit into
Closed
feat(gateway/dingtalk): env-based config and richer msgtype handling#8960sputnicyoji wants to merge 1 commit into
sputnicyoji wants to merge 1 commit into
Conversation
Aligns the DingTalk adapter with the env-var bootstrap pattern other platforms use, and extends inbound handling beyond the `text` msgtype. Environment variables (gateway/config.py): - `DINGTALK_CLIENT_ID` / `DINGTALK_CLIENT_SECRET` enable the platform - `DINGTALK_ALLOWED_USERS` (comma-separated staff ids) populates the allow-list under `extra.allowed_users` - `DINGTALK_HOME_CHANNEL` / `DINGTALK_HOME_CHANNEL_NAME` set the home conversation - `get_connected_platforms` now recognizes DingTalk via `extra.client_id` Message-type dispatch (gateway/platforms/dingtalk.py): - DingTalk Stream delivers exactly three chatbot msgtypes: `text`, `picture`, `richText`. Dispatch each explicitly and render unknown types as a labelled placeholder rather than silently dropping. - Picture messages map to `MessageType.PHOTO` with `[图片]` placeholder (the download API requires an OpenAPI scope this adapter doesn't call). - `richText` renders each segment: plain text, `@user` mentions, and inline pictures as `[图片]`. - `_extract_text` now takes an explicit `msgtype` to keep callers honest; falls back to `message.message_type` when omitted. Tests updated to cover each dispatch path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sputnicyoji
pushed a commit
to sputnicyoji/hermes-agent
that referenced
this pull request
Apr 13, 2026
Previously the adapter replaced any `picture` or inline `richText` image with the literal string `[图片]`; vision tools therefore never saw the actual bytes. This patch exchanges each `downloadCode` for the temporary CDN URL via `/v1.0/robot/messageFiles/download`, fetches the bytes, and caches them locally so `MessageEvent.media_urls` points at a real file. Implementation notes: - Piggyback on the dingtalk-stream SDK: `register_callback_handler` wires `handler.dingtalk_client = stream_client`, which gives us the SDK's access-token helper and `get_image_download_url`. Keep the handler reference on the adapter (`self._handler`). - `get_image_download_url` is sync (requests-based) — offload via `asyncio.to_thread` to avoid blocking the event loop. - Failures at any stage (missing code, empty URL, HTTP error) are logged but degrade gracefully: the event still dispatches with the `[图片]` text placeholder so the agent knows something arrived. - `message.get_image_list()` handles both `picture` and `richText` shapes, so the same path supports inline images in rich messages. - On successful download the placeholder text is replaced with `[图片 × N]` as a short caption alongside the attached media list. Tests cover: missing handler, single-image success, empty downloadUrl, partial HTTP failure (continue on remaining codes), and full end-to-end picture dispatch through `_on_message`. Depends on NousResearch#8954 (SDK 0.24 async process) and NousResearch#8960 (msgtype dispatch). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 tasks
sputnicyoji
pushed a commit
to sputnicyoji/hermes-agent
that referenced
this pull request
Apr 13, 2026
Previously the adapter replaced any `picture` or inline `richText` image with the literal string `[图片]`; vision tools therefore never saw the actual bytes. This patch exchanges each `downloadCode` for the temporary CDN URL via `/v1.0/robot/messageFiles/download`, fetches the bytes, and caches them locally so `MessageEvent.media_urls` points at a real file. Implementation notes: - Piggyback on the dingtalk-stream SDK: `register_callback_handler` wires `handler.dingtalk_client = stream_client`, which gives us the SDK's access-token helper and `get_image_download_url`. Keep the handler reference on the adapter (`self._handler`). - `get_image_download_url` is sync (requests-based) — offload via `asyncio.to_thread` to avoid blocking the event loop. - Failures at any stage (missing code, empty URL, HTTP error) are logged but degrade gracefully: the event still dispatches with the `[图片]` text placeholder so the agent knows something arrived. - `message.get_image_list()` handles both `picture` and `richText` shapes, so the same path supports inline images in rich messages. - On successful download the placeholder text is replaced with `[图片 × N]` as a short caption alongside the attached media list. Tests cover: missing handler, single-image success, empty downloadUrl, partial HTTP failure (continue on remaining codes), and full end-to-end picture dispatch through `_on_message`. Depends on NousResearch#8954 (SDK 0.24 async process) and NousResearch#8960 (msgtype dispatch). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sputnicyoji
pushed a commit
to sputnicyoji/hermes-agent
that referenced
this pull request
Apr 15, 2026
Previously the adapter replaced any `picture` or inline `richText` image with the literal string `[图片]`; vision tools therefore never saw the actual bytes. This patch exchanges each `downloadCode` for the temporary CDN URL via `/v1.0/robot/messageFiles/download`, fetches the bytes, and caches them locally so `MessageEvent.media_urls` points at a real file. Implementation notes: - Piggyback on the dingtalk-stream SDK: `register_callback_handler` wires `handler.dingtalk_client = stream_client`, which gives us the SDK's access-token helper and `get_image_download_url`. Keep the handler reference on the adapter (`self._handler`). - `get_image_download_url` is sync (requests-based) — offload via `asyncio.to_thread` to avoid blocking the event loop. - Failures at any stage (missing code, empty URL, HTTP error) are logged but degrade gracefully: the event still dispatches with the `[图片]` text placeholder so the agent knows something arrived. - `message.get_image_list()` handles both `picture` and `richText` shapes, so the same path supports inline images in rich messages. - On successful download the placeholder text is replaced with `[图片 × N]` as a short caption alongside the attached media list. Tests cover: missing handler, single-image success, empty downloadUrl, partial HTTP failure (continue on remaining codes), and full end-to-end picture dispatch through `_on_message`. Depends on NousResearch#8954 (SDK 0.24 async process) and NousResearch#8960 (msgtype dispatch). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 tasks
Author
|
Closing — main already has the env-var config and msgtype handling from this PR (see |
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
Aligns the DingTalk adapter with the env-var bootstrap pattern other platforms (Telegram/Discord/WhatsApp/BlueBubbles) use, and extends inbound handling beyond the
textmsgtype.Environment variables (
gateway/config.py)DINGTALK_CLIENT_ID/DINGTALK_CLIENT_SECRETenable the platformDINGTALK_ALLOWED_USERS(comma-separated staff ids) populates the allow-list underextra.allowed_usersDINGTALK_HOME_CHANNEL/DINGTALK_HOME_CHANNEL_NAMEset the home conversationget_connected_platformsnow recognizes DingTalk viaextra.client_idMessage-type dispatch (
gateway/platforms/dingtalk.py)DingTalk Stream delivers exactly three chatbot msgtypes:
text,picture,richText. Previously anything other thantextwas silently dropped.picture→MessageType.PHOTOwith[图片]placeholder (the download API requires an OpenAPI scope this adapter doesn't call)richText→ render each segment: plain text,@usermentions, inline pictures as[图片][未支持的消息类型: <type>]rather than silent drop_extract_textnow takes an explicitmsgtypeto keep callers honest; falls back tomessage.message_typewhen omittedTest plan
Depends conceptually on #8954 (SDK 0.24 compat) for the
TextContentreading path in_read_plain_text, but the static methods are backwards-compatible with older SDKs viahasattr/isinstancefallbacks.