Conversation
Add a full inbound rich-media pipeline for the DingTalk adapter: download images/files from DingTalk CDN, parse document contents (docx/pdf/xlsx/txt), persist to a local inbox directory with automatic 24h purge, and inject parsed text into the agent context. - File parsers: _parse_text_file, _parse_docx_file, _parse_pdf_file, _parse_excel_file with graceful fallbacks when deps missing - _inbound_media_dir() + _cleanup_inbound_media() — 24h auto-purge - _download_file_to_inbox() — authenticated download via DingTalk /v1.0/robot/messageFiles/download with 20MB guard - _download_images_to_local() — batch download for multi-modal input - _extract_and_parse_file_attachments() — walk raw extensions payload - Integrate media pipeline into _on_message() - Add python-docx, pdfplumber, openpyxl to dingtalk optional deps Ported from dingtalk-openclaw-connector core/message-handler.ts:700-956. to #
|
Hi @alt-glitch, appreciate the thorough cross-referencing! 🙏 You're right that this overlaps with #14335 and #9451. Here's the full picture: We're the DingTalk (钉钉) Open Platform team at Alibaba — @PeterGuy326 and @spike2204 are colleagues. This PR is a clean, self-contained re-submission of the media pipeline from the stacked #14335, rebased against How this relates to #9451: Our implementation is a superset that covers the same ground as #9451 but adds:
This is ported from our production dingtalk-openclaw-connector ( Happy to help consolidate with #9451 if the maintainers prefer — we can close whichever PR is superseded. 🚀 |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for tackling an unhandled DingTalk media path. The underlying gap remains on current main: plugins/platforms/dingtalk/adapter.py:659-670 only proceeds with _extract_media() output, and _extract_media() currently handles image and rich-text download codes (:765-824), not raw file/audio/video extension payloads.
Problems
gateway/platforms/dingtalk.py:1732is the final successful-download statement in_extract_and_parse_file_attachments; it falls through without returning the(parts, attachments)tuple unpacked at:932.- The PR calls
_resolve_single_download_urlat:441and:596, but the full PR diff contains no definition. :369-372buffersresponse.contentwithout enforcing the declared_DINGTALK_MEDIA_MAX_SIZE; current shared bounded download logic is ingateway/platforms/base.py:641-669.- Current main moved this adapter to
plugins/platforms/dingtalk/adapter.pyin5600105478ffde29d7566b45421b100eaa29c4ef; the changed files include no tests.
Suggested changes
- Salvage the raw-extension extraction into the plugin adapter, use the shared media cache/bounded reader, complete the return and resolver paths, and add fixtures in
tests/gateway/test_dingtalk.py.
Automated hermes-sweeper review.
| slug = re.sub(r'[^\w]', '', msg_id)[:16] if msg_id else uuid.uuid4().hex[:12] | ||
| out_path = os.path.join(_inbound_media_dir(), f"{slug}_{base}{ext}") | ||
| async with httpx.AsyncClient(timeout=timeout, follow_redirects=True) as client: | ||
| resp = await client.get(url) |
There was a problem hiding this comment.
This buffers the whole response before writing it, while _DINGTALK_MEDIA_MAX_SIZE is never enforced in this diff. Please use a bounded streaming read (the current shared implementation is gateway/platforms/base.py:_read_httpx_body_with_limit) before caching untrusted attachment data.
| continue | ||
|
|
||
| mime = _mime_for_file(fname) | ||
| attachments.append((local_path, mime)) |
There was a problem hiding this comment.
After a successful attachment download this function falls through and returns None; _on_message unpacks its result as (file_parts, file_attachments). Finish the success path, including parsing/context construction, and explicitly return (parts, attachments).
Summary
Add a full inbound rich-media pipeline for the DingTalk adapter: download images/files from DingTalk CDN, parse document contents (docx/pdf/xlsx/txt), persist to a local inbox directory with automatic 24h purge, and inject parsed text into the agent context.
Changes
_parse_text_file,_parse_docx_file,_parse_pdf_file,_parse_excel_filewith graceful fallbacks when optional deps are missing_inbound_media_dir()+_cleanup_inbound_media()— 24h auto-purge_download_file_to_inbox()— authenticated download with 20MB guard_download_images_to_local()— batch download for multi-modal input (DingTalk signed OSS URLs are not universally accessible)_extract_and_parse_file_attachments()— walk raw extensions payload for file/audio/video/richText_on_message()pyproject.tomlPorted from dingtalk-openclaw-connector
core/message-handler.ts:700-956.Related
Part of the DingTalk adapter enhancement series — see #12769 for the umbrella PR.