@dingtalk-real-ai/dingtalk-connector 0.8.12 → 0.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.en.md +31 -6
- package/README.md +31 -6
- package/docs/RELEASE_NOTES_V0.7.10.md +40 -0
- package/docs/RELEASE_NOTES_V0.7.2.md +143 -0
- package/docs/RELEASE_NOTES_V0.7.3.md +149 -0
- package/docs/RELEASE_NOTES_V0.7.4.md +206 -0
- package/docs/RELEASE_NOTES_V0.7.5.md +267 -0
- package/docs/RELEASE_NOTES_V0.7.6.md +219 -0
- package/docs/RELEASE_NOTES_V0.7.7.md +122 -0
- package/docs/RELEASE_NOTES_V0.7.8.md +101 -0
- package/docs/RELEASE_NOTES_V0.7.9.md +65 -0
- package/docs/RELEASE_NOTES_V0.8.0.md +53 -0
- package/docs/RELEASE_NOTES_V0.8.1.md +47 -0
- package/docs/RELEASE_NOTES_V0.8.10.md +49 -0
- package/docs/RELEASE_NOTES_V0.8.11.md +51 -0
- package/docs/RELEASE_NOTES_V0.8.12.md +63 -0
- package/docs/RELEASE_NOTES_V0.8.13-beta.0.md +69 -0
- package/docs/RELEASE_NOTES_V0.8.13.md +62 -0
- package/docs/RELEASE_NOTES_V0.8.2.md +55 -0
- package/docs/RELEASE_NOTES_V0.8.3.md +63 -0
- package/docs/RELEASE_NOTES_V0.8.4.md +45 -0
- package/docs/RELEASE_NOTES_V0.8.7.md +49 -0
- package/docs/RELEASE_NOTES_V0.8.8.md +63 -0
- package/docs/RELEASE_NOTES_V0.8.9.md +81 -0
- package/docs/RELEASE_NOTES_v0.7.0.md +142 -0
- package/docs/RELEASE_NOTES_v0.7.1.md +74 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +13 -2
- package/src/channel.ts +18 -6
- package/src/config/schema.ts +2 -2
- package/src/core/connection.ts +9 -6
- package/src/core/message-handler.ts +30 -10
- package/src/reply-dispatcher.ts +4 -3
- package/src/services/media/file.ts +7 -2
- package/src/services/media.ts +19 -12
- package/src/services/messaging/card.ts +1 -2
- package/src/services/messaging.ts +29 -16
- package/src/utils/http-client.ts +2 -1
- package/docs/images/dingtalk.svg +0 -1
- package/docs/images/image-1.png +0 -0
- package/docs/images/image-2.png +0 -0
- package/docs/images/image-3.png +0 -0
- package/docs/images/image-4.png +0 -0
- package/docs/images/image-5.png +0 -0
- package/docs/images/image-6.png +0 -0
- package/docs/images/image-7.png +0 -0
- package/install-beta.sh +0 -438
- package/install-npm.sh +0 -167
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Release Notes - v0.8.9
|
|
2
|
+
|
|
3
|
+
## 🎉 新版本亮点 / Highlights
|
|
4
|
+
|
|
5
|
+
本次更新带来**引用消息完整解析**、**macOS LaunchAgent 兼容性修复**和**多项稳定性改进**。消息处理层新增对引用消息(reply)的递归解析,支持提取引用中的文本、媒体附件和链接;修复了 macOS LaunchAgent 环境下因无效文件描述符导致 WebSocket 连接失败的问题;同时修复了 AI Card 流式关闭的竞争条件、FormData CJS 互操作问题,并锁定 axios 版本以提升依赖稳定性。
|
|
6
|
+
|
|
7
|
+
This release introduces **quoted message parsing**, **macOS LaunchAgent compatibility**, and **multiple stability improvements**. The message handler now recursively parses quoted (reply) messages, extracting text, media attachments, and URLs. A fix for invalid file descriptors (EBADF) on macOS LaunchAgent environments prevents WebSocket connection failures. Additionally, the AI Card streaming close race condition is fixed, FormData CJS interop issues are resolved, and axios is pinned to v1.6.0 for dependency stability.
|
|
8
|
+
|
|
9
|
+
## ✨ 功能与体验改进 / Features & Improvements
|
|
10
|
+
|
|
11
|
+
- **引用消息完整解析 / Quoted message full parsing**
|
|
12
|
+
新增 `extractQuotedMsgText` 递归解析引用消息(最多 3 层嵌套),支持 text、richText、picture、video、audio、file、markdown、interactiveCard 等消息类型。引用消息中的媒体附件(图片/视频/音频/文件)会被自动提取并传递给下游处理。引用了含链接的文本消息时,链接会被提取用于 URL 路由(如 alidocs 文档链接)。
|
|
13
|
+
Added `extractQuotedMsgText` for recursive quoted message parsing (up to 3 levels), supporting text, richText, picture, video, audio, file, markdown, and interactiveCard message types. Media attachments in quoted messages are automatically extracted and passed downstream. URLs from quoted text messages are extracted for URL routing (e.g., alidocs document links).
|
|
14
|
+
|
|
15
|
+
- **新增配置项 / New configuration options**
|
|
16
|
+
`configSchema` 新增 `asyncMode`、`ackText`、`endpoint`、`debug` 四个配置字段,为异步消息处理和自定义端点提供灵活配置能力。
|
|
17
|
+
Added `asyncMode`, `ackText`, `endpoint`, `debug` to `configSchema`, enabling flexible configuration for async message processing and custom endpoints.
|
|
18
|
+
|
|
19
|
+
- **普通消息本地图片后处理 / Local image post-processing for normal messages**
|
|
20
|
+
`sendNormalToUser` 和 `sendNormalToGroup` 新增本地图片上传后处理,发送普通消息时自动将 Markdown 中的本地图片路径上传到钉钉并替换为 media_id,与 AI Card 消息行为保持一致。
|
|
21
|
+
Added local image upload post-processing to `sendNormalToUser` and `sendNormalToGroup`, automatically uploading local image paths in Markdown to DingTalk and replacing them with media_id, consistent with AI Card message behavior.
|
|
22
|
+
|
|
23
|
+
## 🐛 修复 / Fixes
|
|
24
|
+
|
|
25
|
+
- **macOS LaunchAgent 环境 WebSocket 连接失败 / WebSocket connection failure on macOS LaunchAgent**
|
|
26
|
+
修复 macOS LaunchAgent/daemon 环境下,进程启动时 stdin/stdout/stderr(fd 0/1/2)无效(EBADF),导致 Node.js 创建 TCP 连接时出现 EBADF 错误。启动前检测并将无效 fd 重定向到 `/dev/null`。
|
|
27
|
+
Fixed EBADF errors when creating TCP connections on macOS LaunchAgent/daemon environments where stdin/stdout/stderr (fd 0/1/2) are invalid at process startup. Invalid file descriptors are now detected and redirected to `/dev/null`.
|
|
28
|
+
|
|
29
|
+
- **AI Card 流式关闭竞争条件 / AI Card streaming close race condition**
|
|
30
|
+
修复 `closeStreaming` 可能被 `onIdle` 和 `onError` 同时触发时的竞争条件。现在在函数开头立即捕获并清空 `currentCardTarget`(snapshot 模式),防止并发调用导致 `finishAICard` 收到 null 参数而崩溃。
|
|
31
|
+
Fixed a race condition where `closeStreaming` could be triggered simultaneously by `onIdle` and `onError`. Now captures and clears `currentCardTarget` at function entry (snapshot pattern), preventing concurrent calls from passing null to `finishAICard`.
|
|
32
|
+
|
|
33
|
+
- **FormData CJS 互操作问题 / FormData CJS interop issue**
|
|
34
|
+
将 `form-data` 从动态 `import()` 改为静态 `import`,修复 jiti/ESM 环境下动态导入 CJS 模块时 `.default` 偶发为 `undefined` 导致 `Cannot read properties of undefined (reading 'registry')` 错误的问题。
|
|
35
|
+
Changed `form-data` from dynamic `import()` to static `import`, fixing intermittent `Cannot read properties of undefined (reading 'registry')` errors caused by `.default` being `undefined` when dynamically importing CJS modules in jiti/ESM environments.
|
|
36
|
+
|
|
37
|
+
- **纯文本图片路径误转换 / Bare image path false conversion**
|
|
38
|
+
禁用纯文本中本地图片路径的自动转换为图片语法的行为。此前纯文本中出现的本地路径(如 `/path/to/image.png`)会被自动包裹为 ``,影响用户只想展示路径文本的场景。
|
|
39
|
+
Disabled automatic conversion of bare local image paths in plain text to image syntax. Previously, local paths like `/path/to/image.png` in plain text were automatically wrapped as ``, which was undesirable when users intended to display the path as text.
|
|
40
|
+
|
|
41
|
+
## 🔧 内部改进 / Internal Improvements
|
|
42
|
+
|
|
43
|
+
- **Zod Schema 拆分兼容 Web UI / Zod Schema split for Web UI compatibility**
|
|
44
|
+
将 `DingtalkConfigSchema` 拆分为 `DingtalkConfigBaseSchema`(纯 ZodObject)和带 `superRefine` 的完整 Schema,解决 `superRefine` 将 Schema 转为 `ZodEffects` 后无法用于 `buildChannelConfigSchema` 生成 JSON Schema 的问题。
|
|
45
|
+
Split `DingtalkConfigSchema` into `DingtalkConfigBaseSchema` (pure ZodObject) and the full schema with `superRefine`, fixing incompatibility with `buildChannelConfigSchema` JSON Schema generation.
|
|
46
|
+
|
|
47
|
+
- **configSchema 类型简化 / configSchema type simplification**
|
|
48
|
+
将 `clientId`、`clientSecret`、`allowFrom`、`groupAllowFrom` 等字段的 JSON Schema 从 `oneOf` 联合类型简化为单一 `string` 类型,移除不再需要的 `secretInputJsonSchema`,降低配置复杂度。
|
|
49
|
+
Simplified JSON Schema for `clientId`, `clientSecret`, `allowFrom`, `groupAllowFrom` from `oneOf` union types to single `string` type, removing the no-longer-needed `secretInputJsonSchema`.
|
|
50
|
+
|
|
51
|
+
- **reply-dispatcher logger 统一 / reply-dispatcher logger unification**
|
|
52
|
+
将 `reply-dispatcher.ts` 中手动构建的 log 对象替换为 `createLoggerFromConfig`,与项目其他模块的日志规范保持一致。
|
|
53
|
+
Replaced manually constructed log object in `reply-dispatcher.ts` with `createLoggerFromConfig`, aligning with the project's logging conventions.
|
|
54
|
+
|
|
55
|
+
- **锁定 axios 版本 / Pin axios version**
|
|
56
|
+
将 `axios` 依赖从 `^1.6.0` 锁定为 `1.6.0`,避免自动升级引入不兼容变更。
|
|
57
|
+
Pinned `axios` dependency from `^1.6.0` to `1.6.0` to prevent automatic upgrades from introducing incompatible changes.
|
|
58
|
+
|
|
59
|
+
## 📥 安装升级 / Installation & Upgrade
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# 通过 npm 安装最新版本 / Install latest version via npm
|
|
63
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector
|
|
64
|
+
|
|
65
|
+
# 或升级现有版本 / Or upgrade existing version
|
|
66
|
+
openclaw plugins update dingtalk-connector
|
|
67
|
+
|
|
68
|
+
# 通过 Git 安装 / Install via Git
|
|
69
|
+
openclaw plugins install https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector.git
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 🔗 相关链接 / Related Links
|
|
73
|
+
|
|
74
|
+
- [完整变更日志 / Full Changelog](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/CHANGELOG.md)
|
|
75
|
+
- [使用文档 / Documentation](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/README.md)
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
**发布日期 / Release Date**:2026-03-31
|
|
80
|
+
**版本号 / Version**:v0.8.9
|
|
81
|
+
**兼容性 / Compatibility**:OpenClaw Gateway 0.4.0+
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Release Notes - v0.7.0
|
|
2
|
+
|
|
3
|
+
## 🎉 新版本亮点 / Highlights
|
|
4
|
+
|
|
5
|
+
本次更新带来了丰富的富媒体和文档处理能力,让 AI 助手能够更好地理解和处理各种类型的内容。新增了图片识别、文件解析、钉钉文档操作和多 Agent 路由等核心功能。
|
|
6
|
+
|
|
7
|
+
This update brings rich media and document processing capabilities, enabling AI assistants to better understand and process various types of content. New core features include image recognition, file parsing, DingTalk document operations, and multi-Agent routing.
|
|
8
|
+
|
|
9
|
+
## ✨ 新增功能 / Added Features
|
|
10
|
+
|
|
11
|
+
### 富媒体接收支持 / Rich Media Reception Support
|
|
12
|
+
- ✅ **JPEG 图片消息** - 支持接收钉钉中直接发送的 JPEG 图片,自动下载到 `~/.openclaw/workspace/media/inbound/` 目录
|
|
13
|
+
**JPEG Image Messages** - Support receiving JPEG images sent directly in DingTalk, automatically downloaded to `~/.openclaw/workspace/media/inbound/` directory
|
|
14
|
+
- ✅ **PNG 图片(富文本)** - 支持接收富文本消息中包含的 PNG 图片,自动提取 URL 和 downloadCode 并下载
|
|
15
|
+
**PNG Images (Rich Text)** - Support receiving PNG images contained in rich text messages, automatically extract URL and downloadCode and download
|
|
16
|
+
- ✅ **视觉模型集成** - 下载的图片自动传递给视觉模型,AI 可以识别和分析图片内容
|
|
17
|
+
**Vision Model Integration** - Downloaded images are automatically passed to vision models, AI can recognize and analyze image content
|
|
18
|
+
- ✅ **媒体文件管理** - 统一的文件命名格式 `openclaw-media-{timestamp}.{ext}`,便于管理和追踪
|
|
19
|
+
**Media File Management** - Unified file naming format `openclaw-media-{timestamp}.{ext}` for easy management and tracking
|
|
20
|
+
|
|
21
|
+
### 文件附件提取 / File Attachment Extraction
|
|
22
|
+
- ✅ **Word 文档解析** - 支持解析 `.docx` 文件,通过 `mammoth` 库提取文本内容并注入到 AI 上下文
|
|
23
|
+
**Word Document Parsing** - Support parsing `.docx` files, extract text content via `mammoth` library and inject into AI context
|
|
24
|
+
- ✅ **PDF 文档解析** - 支持解析 `.pdf` 文件,通过 `pdf-parse` 库提取文本内容并注入到 AI 上下文
|
|
25
|
+
**PDF Document Parsing** - Support parsing `.pdf` files, extract text content via `pdf-parse` library and inject into AI context
|
|
26
|
+
- ✅ **纯文本文件** - 支持读取 `.txt`、`.md`、`.json` 等纯文本文件,内容直接注入到消息中
|
|
27
|
+
**Plain Text Files** - Support reading plain text files (`.txt`, `.md`, `.json`, etc.), content directly injected into messages
|
|
28
|
+
- ✅ **二进制文件处理** - 支持处理 `.xlsx`、`.pptx`、`.zip` 等二进制文件,文件保存到磁盘并在消息中报告路径
|
|
29
|
+
**Binary File Processing** - Support processing binary files (`.xlsx`, `.pptx`, `.zip`, etc.), files saved to disk and paths reported in messages
|
|
30
|
+
|
|
31
|
+
### 钉钉文档 API / DingTalk Document API
|
|
32
|
+
- ✅ **创建文档** - `docs.create()` - 在指定空间中创建新的钉钉文档
|
|
33
|
+
**Create Document** - `docs.create()` - Create new DingTalk documents in specified spaces
|
|
34
|
+
- ✅ **追加内容** - `docs.append()` - 在现有文档上追加 Markdown 内容
|
|
35
|
+
**Append Content** - `docs.append()` - Append Markdown content to existing documents
|
|
36
|
+
- ✅ **搜索文档** - `docs.search()` - 根据关键词搜索钉钉文档
|
|
37
|
+
**Search Documents** - `docs.search()` - Search DingTalk documents by keywords
|
|
38
|
+
- ✅ **列举文档** - `docs.list()` - 列举指定空间下的所有文档
|
|
39
|
+
**List Documents** - `docs.list()` - List all documents under specified spaces
|
|
40
|
+
- ⚠️ **读取文档** - `docs.read()` - 当前不可用(见已知问题)
|
|
41
|
+
**Read Document** - `docs.read()` - Currently unavailable (see Known Issues)
|
|
42
|
+
|
|
43
|
+
### 多 Agent 路由支持 / Multi-Agent Routing Support
|
|
44
|
+
- ✅ **多 Agent 会话隔离** - 支持一个连接器实例同时连接多个 Agent
|
|
45
|
+
**Multi-Agent Session Isolation** - Support one connector instance connecting to multiple Agents simultaneously
|
|
46
|
+
- ✅ **多机器人绑定** - 支持多个钉钉机器人分别绑定到不同的 Agent,实现角色分工和专业化服务
|
|
47
|
+
**Multi-Bot Binding** - Support multiple DingTalk bots binding to different Agents, enabling role division and specialized services
|
|
48
|
+
- ✅ **独立会话空间** - 每个 Agent 拥有独立的会话上下文,互不干扰
|
|
49
|
+
**Independent Session Space** - Each Agent has an independent session context without interference
|
|
50
|
+
- ✅ **灵活配置** - 通过 `accounts` 和 `bindings` 配置多个机器人,提供详细的配置示例和说明
|
|
51
|
+
**Flexible Configuration** - Configure multiple bots via `accounts` and `bindings`, with detailed configuration examples and instructions
|
|
52
|
+
- ✅ **向后兼容** - 单 Agent 场景下功能完全兼容,无需额外配置
|
|
53
|
+
**Backward Compatible** - Fully compatible with single Agent scenarios, no additional configuration required
|
|
54
|
+
|
|
55
|
+
## 🐛 修复 / Fixes
|
|
56
|
+
|
|
57
|
+
- **语音消息播放异常修复** - 修复机器人发送语音消息播放异常问题,音频进度和播放功能现已正常工作
|
|
58
|
+
**Voice Message Playback Fix** - Fixed bot voice message playback issues, audio progress and playback functionality now work correctly
|
|
59
|
+
|
|
60
|
+
## 🔧 改进 / Improvements
|
|
61
|
+
|
|
62
|
+
- **媒体文件处理优化** - 优化了媒体文件下载和存储机制,提升处理效率
|
|
63
|
+
**Media File Processing Optimization** - Optimized media file download and storage mechanism, improved processing efficiency
|
|
64
|
+
- **文件附件流程改进** - 改进了文件附件处理流程,支持更多文件类型,错误处理更完善
|
|
65
|
+
**File Attachment Process Improvement** - Improved file attachment processing flow, supporting more file types with better error handling
|
|
66
|
+
- **Markdown 表格转换** - 自动将 Markdown 表格转换为钉钉支持的文本格式,提升消息可读性
|
|
67
|
+
**Markdown Table Conversion** - Automatically convert Markdown tables to DingTalk-supported text format for better message readability
|
|
68
|
+
- **日志增强** - 增强了错误处理和日志输出,便于问题排查和调试
|
|
69
|
+
**Log Enhancement** - Enhanced error handling and log output for easier troubleshooting and debugging
|
|
70
|
+
|
|
71
|
+
## 📦 依赖更新 / Dependency Updates
|
|
72
|
+
|
|
73
|
+
- 新增 `mammoth@^1.8.0` - Word 文档(.docx)解析库
|
|
74
|
+
Added `mammoth@^1.8.0` - Word document (.docx) parsing library
|
|
75
|
+
- 新增 `pdf-parse@^1.1.1` - PDF 文档解析库
|
|
76
|
+
Added `pdf-parse@^1.1.1` - PDF document parsing library
|
|
77
|
+
|
|
78
|
+
## ⚠️ 已知问题 / Known Issues
|
|
79
|
+
|
|
80
|
+
### 1. 钉钉文档读取功能不可用 / DingTalk Document Reading Unavailable
|
|
81
|
+
|
|
82
|
+
**问题描述 / Issue Description**:`docs.read()` API 当前无法正常工作
|
|
83
|
+
`docs.read()` API is currently not working properly
|
|
84
|
+
|
|
85
|
+
**原因 / Cause**:MCP(Model Context Protocol)中未提供读取文档的 tool,虽然代码层面实现正常,但缺少底层支持
|
|
86
|
+
MCP (Model Context Protocol) does not provide the tool for reading documents. While the implementation is correct at the code level, underlying support is missing
|
|
87
|
+
|
|
88
|
+
**影响范围 / Impact**:仅影响文档读取功能,其他文档操作(创建、追加、搜索、列举)均正常
|
|
89
|
+
Only affects document reading functionality, other document operations (create, append, search, list) work normally
|
|
90
|
+
|
|
91
|
+
**解决方案 / Solution**:等待 MCP 提供相应的 tool 支持,或使用其他文档操作 API 作为替代方案
|
|
92
|
+
Wait for MCP to provide corresponding tool support, or use other document operation APIs as alternatives
|
|
93
|
+
|
|
94
|
+
**状态 / Status**:已记录,等待上游支持
|
|
95
|
+
Recorded, waiting for upstream support
|
|
96
|
+
|
|
97
|
+
## 📚 文档更新 / Documentation Updates
|
|
98
|
+
|
|
99
|
+
- ✅ 更新 README.md,添加新功能使用说明
|
|
100
|
+
Updated README.md, added usage instructions for new features
|
|
101
|
+
- ✅ 新增"富媒体接收"章节,说明图片消息处理方式
|
|
102
|
+
Added "Rich Media Reception" section, explaining image message processing
|
|
103
|
+
- ✅ 新增"文件附件提取"章节,列出支持的文件类型和处理方式
|
|
104
|
+
Added "File Attachment Extraction" section, listing supported file types and processing methods
|
|
105
|
+
- ✅ 新增"钉钉文档 API"章节,提供 API 使用示例
|
|
106
|
+
Added "DingTalk Document API" section, providing API usage examples
|
|
107
|
+
- ✅ 新增"多 Agent 路由支持"章节,说明多 Agent 会话隔离功能
|
|
108
|
+
Added "Multi-Agent Routing Support" section, explaining multi-Agent session isolation functionality
|
|
109
|
+
- ✅ 新增"多 Agent 配置"章节,提供详细的配置示例和说明(`accounts` 和 `bindings` 配置)
|
|
110
|
+
Added "Multi-Agent Configuration" section with detailed configuration examples and instructions (`accounts` and `bindings` configuration)
|
|
111
|
+
- ✅ 补充常见问题解答,包括新功能的故障排查
|
|
112
|
+
Added FAQ section, including troubleshooting for new features
|
|
113
|
+
|
|
114
|
+
## 🔗 相关链接 / Related Links
|
|
115
|
+
|
|
116
|
+
- [完整变更日志 / Full Changelog](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/CHANGELOG.md)
|
|
117
|
+
- [使用文档 / Documentation](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/README.md)
|
|
118
|
+
- [问题反馈 / Issue Feedback](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues)
|
|
119
|
+
|
|
120
|
+
## 📥 安装升级 / Installation & Upgrade
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# 通过 npm 安装最新版本 / Install latest version via npm
|
|
124
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector
|
|
125
|
+
|
|
126
|
+
# 或升级现有版本 / Or upgrade existing version
|
|
127
|
+
openclaw plugins update dingtalk-connector
|
|
128
|
+
|
|
129
|
+
# 通过 Git 安装 / Install via Git
|
|
130
|
+
openclaw plugins install https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector.git
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## 🙏 致谢 / Acknowledgments
|
|
134
|
+
|
|
135
|
+
感谢所有贡献者和用户的支持与反馈!
|
|
136
|
+
Thanks to all contributors and users for their support and feedback!
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
**发布日期 / Release Date**:2026-03-05
|
|
141
|
+
**版本号 / Version**:v0.7.0
|
|
142
|
+
**兼容性 / Compatibility**:OpenClaw Gateway 0.4.0+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Release Notes - v0.7.1
|
|
2
|
+
|
|
3
|
+
## 🐛 修复版本 / Bug Fix Release
|
|
4
|
+
|
|
5
|
+
本次更新修复了 stream 模式下的关键问题,确保 Agent 路由功能正常工作。
|
|
6
|
+
|
|
7
|
+
This update fixes critical issues in stream mode to ensure Agent routing functionality works correctly.
|
|
8
|
+
|
|
9
|
+
## 🐛 修复 / Fixes
|
|
10
|
+
|
|
11
|
+
### 1. Stream 模式 Session 路由失败问题 / Stream Mode Session Routing Failure
|
|
12
|
+
|
|
13
|
+
**问题描述 / Issue Description**:stream 模式下 model 参数错误导致 session 路由失败
|
|
14
|
+
Incorrect model parameter in stream mode caused session routing failures
|
|
15
|
+
|
|
16
|
+
**修复内容 / Fix**:
|
|
17
|
+
- 将 Gateway 请求中的 `model` 参数从 `'default'` 更正为 `'main'`
|
|
18
|
+
Corrected `model` parameter in Gateway requests from `'default'` to `'main'`
|
|
19
|
+
- 确保正确的 Agent 路由和会话管理
|
|
20
|
+
Ensures proper Agent routing and session management
|
|
21
|
+
|
|
22
|
+
**影响范围 / Impact**:影响所有使用 stream 模式的用户,修复后 Agent 路由将正常工作
|
|
23
|
+
Affects all users using stream mode. After the fix, Agent routing will work correctly.
|
|
24
|
+
|
|
25
|
+
### 2. 多 Agent 路由问题修复 / Multi-Agent Routing Fix
|
|
26
|
+
|
|
27
|
+
**问题描述 / Issue Description**:多个钉钉机器人绑定到不同 Agent 时路由异常
|
|
28
|
+
Multiple DingTalk bots binding to different Agents failed to route correctly
|
|
29
|
+
|
|
30
|
+
**修复内容 / Fix**:
|
|
31
|
+
- 修复多 Agent 路由机制,确保多个钉钉机器人可以正确绑定到不同的 Agent
|
|
32
|
+
Fixed multi-Agent routing mechanism, ensuring multiple DingTalk bots can correctly bind to different Agents
|
|
33
|
+
- 改进会话隔离和路由逻辑
|
|
34
|
+
Improved session isolation and routing logic
|
|
35
|
+
|
|
36
|
+
**影响范围 / Impact**:影响使用多 Agent 配置的用户,修复后多机器人多 Agent 场景将正常工作
|
|
37
|
+
Affects users with multi-Agent configurations. After the fix, multi-bot multi-Agent scenarios will work correctly.
|
|
38
|
+
|
|
39
|
+
## 🔧 改进 / Improvements
|
|
40
|
+
|
|
41
|
+
- **异步模式优化** - 优化异步模式处理流程,改进错误处理和日志输出
|
|
42
|
+
**Async Mode Optimization** - Optimized async mode processing flow, improved error handling and log output
|
|
43
|
+
- **DM Policy 增强** - 增强 DM Policy 检查机制,支持白名单配置
|
|
44
|
+
**DM Policy Enhancement** - Enhanced DM Policy check mechanism, supporting allowlist configuration
|
|
45
|
+
|
|
46
|
+
## 📥 安装升级 / Installation & Upgrade
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# 通过 npm 安装最新版本 / Install latest version via npm
|
|
50
|
+
openclaw plugins install @dingtalk-real-ai/dingtalk-connector
|
|
51
|
+
|
|
52
|
+
# 或升级现有版本 / Or upgrade existing version
|
|
53
|
+
openclaw plugins update dingtalk-connector
|
|
54
|
+
|
|
55
|
+
# 通过 Git 安装 / Install via Git
|
|
56
|
+
openclaw plugins install https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector.git
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 🔗 相关链接 / Related Links
|
|
60
|
+
|
|
61
|
+
- [完整变更日志 / Full Changelog](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/CHANGELOG.md)
|
|
62
|
+
- [使用文档 / Documentation](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/blob/main/README.md)
|
|
63
|
+
- [问题反馈 / Issue Feedback](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues)
|
|
64
|
+
|
|
65
|
+
## 🙏 致谢 / Acknowledgments
|
|
66
|
+
|
|
67
|
+
感谢所有贡献者和用户的支持与反馈!
|
|
68
|
+
Thanks to all contributors and users for their support and feedback!
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
**发布日期 / Release Date**:2026-03-05
|
|
73
|
+
**版本号 / Version**:v0.7.1
|
|
74
|
+
**兼容性 / Compatibility**:OpenClaw Gateway 0.4.0+
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dingtalk-real-ai/dingtalk-connector",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.13",
|
|
4
4
|
"description": "DingTalk (钉钉) channel connector — Stream mode with AI Card streaming",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -40,11 +40,22 @@
|
|
|
40
40
|
},
|
|
41
41
|
"homepage": "https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector#readme",
|
|
42
42
|
"bugs": "https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues",
|
|
43
|
+
"files": [
|
|
44
|
+
"index.ts",
|
|
45
|
+
"src/",
|
|
46
|
+
"docs/*.md",
|
|
47
|
+
"openclaw.plugin.json",
|
|
48
|
+
"tsconfig.json",
|
|
49
|
+
"LICENSE",
|
|
50
|
+
"README.md",
|
|
51
|
+
"README.en.md",
|
|
52
|
+
"CHANGELOG.md"
|
|
53
|
+
],
|
|
43
54
|
"publishConfig": {
|
|
44
55
|
"access": "public"
|
|
45
56
|
},
|
|
46
57
|
"dependencies": {
|
|
47
|
-
"axios": "1.
|
|
58
|
+
"axios": "1.14.0",
|
|
48
59
|
"dingtalk-stream": "2.1.4",
|
|
49
60
|
"form-data": "^4.0.0",
|
|
50
61
|
"zod": "^4.3.6"
|
package/src/channel.ts
CHANGED
|
@@ -162,10 +162,10 @@ export const dingtalkPlugin: ChannelPlugin<ResolvedDingtalkAccount> = {
|
|
|
162
162
|
name: account.name,
|
|
163
163
|
clientId: account.clientId,
|
|
164
164
|
}),
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
165
|
+
// 返回空列表,禁止框架层对发送者做全局过滤。
|
|
166
|
+
// 连接器内部(message-handler.ts)已按 dmPolicy/groupPolicy 各自独立检查,
|
|
167
|
+
// allowFrom 仅用于私聊,groupAllowFrom 仅用于群聊,不应被框架层全局应用。
|
|
168
|
+
resolveAllowFrom: () => [],
|
|
169
169
|
formatAllowFrom: ({ allowFrom }) =>
|
|
170
170
|
allowFrom
|
|
171
171
|
.map((entry) => String(entry).trim())
|
|
@@ -289,8 +289,14 @@ export const dingtalkPlugin: ChannelPlugin<ResolvedDingtalkAccount> = {
|
|
|
289
289
|
textChunkLimit: 2000,
|
|
290
290
|
sendText: async ({ cfg, to, text, accountId, replyToId, threadId }) => {
|
|
291
291
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
292
|
+
// 使用已解析的凭据覆盖原始 config,防止 clientId/clientSecret 为 SecretInput 对象或 undefined
|
|
293
|
+
const resolvedConfig: DingtalkConfig = {
|
|
294
|
+
...account.config,
|
|
295
|
+
...(account.clientId != null ? { clientId: account.clientId } : {}),
|
|
296
|
+
...(account.clientSecret != null ? { clientSecret: account.clientSecret } : {}),
|
|
297
|
+
};
|
|
292
298
|
const result = await sendTextToDingTalk({
|
|
293
|
-
config:
|
|
299
|
+
config: resolvedConfig,
|
|
294
300
|
target: to,
|
|
295
301
|
text,
|
|
296
302
|
replyToId,
|
|
@@ -303,6 +309,12 @@ export const dingtalkPlugin: ChannelPlugin<ResolvedDingtalkAccount> = {
|
|
|
303
309
|
},
|
|
304
310
|
sendMedia: async ({ cfg, to, text, mediaUrl, accountId, mediaLocalRoots, replyToId, threadId }) => {
|
|
305
311
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
312
|
+
// 使用已解析的凭据覆盖原始 config,防止 clientId/clientSecret 为 SecretInput 对象或 undefined
|
|
313
|
+
const resolvedConfig: DingtalkConfig = {
|
|
314
|
+
...account.config,
|
|
315
|
+
...(account.clientId != null ? { clientId: account.clientId } : {}),
|
|
316
|
+
...(account.clientSecret != null ? { clientSecret: account.clientSecret } : {}),
|
|
317
|
+
};
|
|
306
318
|
const logger = createLogger(account.config?.debug ?? false, 'DingTalk:SendMedia');
|
|
307
319
|
|
|
308
320
|
logger.info('开始处理,参数:', JSON.stringify({
|
|
@@ -326,7 +338,7 @@ export const dingtalkPlugin: ChannelPlugin<ResolvedDingtalkAccount> = {
|
|
|
326
338
|
}
|
|
327
339
|
|
|
328
340
|
const result = await sendMediaToDingTalk({
|
|
329
|
-
config:
|
|
341
|
+
config: resolvedConfig,
|
|
330
342
|
target: to,
|
|
331
343
|
text,
|
|
332
344
|
mediaUrl,
|
package/src/config/schema.ts
CHANGED
|
@@ -66,6 +66,8 @@ const DingtalkSharedConfigShape = {
|
|
|
66
66
|
ackText: z.string().optional(),
|
|
67
67
|
endpoint: z.string().optional(), // DWClient gateway endpoint
|
|
68
68
|
debug: z.boolean().optional(), // DWClient debug mode
|
|
69
|
+
enableMediaUpload: z.boolean().optional(),
|
|
70
|
+
systemPrompt: z.string().optional(),
|
|
69
71
|
};
|
|
70
72
|
|
|
71
73
|
/**
|
|
@@ -93,8 +95,6 @@ export const DingtalkConfigBaseSchema = z
|
|
|
93
95
|
// Top-level credentials (backward compatible for single-account mode)
|
|
94
96
|
clientId: z.union([z.string(), z.number()]).optional(),
|
|
95
97
|
clientSecret: buildSecretInputSchema().optional(),
|
|
96
|
-
enableMediaUpload: z.boolean().optional(),
|
|
97
|
-
systemPrompt: z.string().optional(),
|
|
98
98
|
...DingtalkSharedConfigShape,
|
|
99
99
|
dmPolicy: DmPolicySchema.optional().default("open"),
|
|
100
100
|
groupPolicy: GroupPolicySchema.optional().default("open"),
|
package/src/core/connection.ts
CHANGED
|
@@ -664,7 +664,7 @@ export async function monitorSingleAccount(
|
|
|
664
664
|
|
|
665
665
|
// 处理 400 错误(请求参数错误)
|
|
666
666
|
if (error.response?.status === 400 || error.message?.includes("status code 400") || error.message?.includes("400")) {
|
|
667
|
-
|
|
667
|
+
reject(new Error(
|
|
668
668
|
`[DingTalk][${accountId}] Bad Request (400):\n` +
|
|
669
669
|
` - clientId or clientSecret format is invalid\n` +
|
|
670
670
|
` - clientId: ${clientIdStr} (type: ${typeof account.clientId}, length: ${clientIdStr.length})\n` +
|
|
@@ -676,24 +676,27 @@ export async function monitorSingleAccount(
|
|
|
676
676
|
` 4. Check if clientId starts with 'ding' prefix\n` +
|
|
677
677
|
` - Error details: ${error.message}\n` +
|
|
678
678
|
` - Response data: ${JSON.stringify(error.response?.data || {})}`,
|
|
679
|
-
);
|
|
679
|
+
));
|
|
680
|
+
return;
|
|
680
681
|
}
|
|
681
682
|
|
|
682
683
|
// 处理 401 认证错误
|
|
683
684
|
if (error.response?.status === 401 || error.message?.includes("401")) {
|
|
684
|
-
|
|
685
|
+
reject(new Error(
|
|
685
686
|
`[DingTalk][${accountId}] Authentication failed (401 Unauthorized):\n` +
|
|
686
687
|
` - Your clientId or clientSecret is invalid, expired, or revoked\n` +
|
|
687
688
|
` - clientId: ${clientIdStr.substring(0, 8)}...\n` +
|
|
688
689
|
` - Please verify your credentials at DingTalk Developer Console\n` +
|
|
689
690
|
` - Error details: ${error.message}`,
|
|
690
|
-
);
|
|
691
|
+
));
|
|
692
|
+
return;
|
|
691
693
|
}
|
|
692
694
|
|
|
693
695
|
// 处理其他连接错误
|
|
694
|
-
|
|
696
|
+
reject(new Error(
|
|
695
697
|
`[DingTalk][${accountId}] Failed to connect to DingTalk Stream: ${error.message}`,
|
|
696
|
-
);
|
|
698
|
+
));
|
|
699
|
+
return;
|
|
697
700
|
}
|
|
698
701
|
|
|
699
702
|
// Handle disconnection(已被自定义 close 监听器替代)
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
processLocalImages,
|
|
50
50
|
processVideoMarkers,
|
|
51
51
|
processAudioMarkers,
|
|
52
|
-
|
|
52
|
+
uploadAndReplaceFileMarkers
|
|
53
53
|
} from "../services/media/index.ts";
|
|
54
54
|
import { sendProactive, type AICardTarget } from "../services/messaging/index.ts";
|
|
55
55
|
import { createAICardForTarget, streamAICard, type AICardInstance } from "../services/messaging/card.ts";
|
|
@@ -701,7 +701,7 @@ export async function downloadMediaByCode(
|
|
|
701
701
|
|
|
702
702
|
const resp = await dingtalkHttp.post(
|
|
703
703
|
`${DINGTALK_API}/v1.0/robot/messageFiles/download`,
|
|
704
|
-
{ downloadCode, robotCode: config.clientId },
|
|
704
|
+
{ downloadCode, robotCode: String(config.clientId) },
|
|
705
705
|
{
|
|
706
706
|
headers: { 'x-acs-dingtalk-access-token': token, 'Content-Type': 'application/json' },
|
|
707
707
|
timeout: 30_000,
|
|
@@ -733,7 +733,7 @@ export async function getFileDownloadUrl(
|
|
|
733
733
|
|
|
734
734
|
const resp = await dingtalkHttp.post(
|
|
735
735
|
`${DINGTALK_API}/v1.0/robot/messageFiles/download`,
|
|
736
|
-
{ downloadCode, robotCode: config.clientId },
|
|
736
|
+
{ downloadCode, robotCode: String(config.clientId) },
|
|
737
737
|
{
|
|
738
738
|
headers: { 'x-acs-dingtalk-access-token': token, 'Content-Type': 'application/json' },
|
|
739
739
|
timeout: 30_000,
|
|
@@ -857,20 +857,40 @@ async function parsePdfFile(filePath: string, log?: any): Promise<string | null>
|
|
|
857
857
|
try {
|
|
858
858
|
log?.info?.(`开始解析 PDF 文档: ${filePath}`);
|
|
859
859
|
|
|
860
|
-
let
|
|
860
|
+
let pdfParseV1: any;
|
|
861
|
+
let pdfParseV2: any;
|
|
861
862
|
try {
|
|
862
|
-
|
|
863
|
+
const mod = await import('pdf-parse');
|
|
864
|
+
if (mod.PDFParse) {
|
|
865
|
+
pdfParseV2 = mod.PDFParse; // v2.x API
|
|
866
|
+
} else if (mod.default) {
|
|
867
|
+
pdfParseV1 = mod.default; // v1.x API
|
|
868
|
+
} else {
|
|
869
|
+
throw new Error('pdf-parse module format not recognized');
|
|
870
|
+
}
|
|
863
871
|
} catch {
|
|
864
872
|
log?.warn?.('pdf-parse 库未安装,无法解析 .pdf 文件。请运行: npm install pdf-parse');
|
|
865
873
|
return null;
|
|
866
874
|
}
|
|
867
875
|
|
|
868
876
|
const buffer = fs.readFileSync(filePath);
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
877
|
+
let text: string;
|
|
878
|
+
let numPages: number | undefined;
|
|
879
|
+
|
|
880
|
+
if (pdfParseV2) {
|
|
881
|
+
const parser = new pdfParseV2({ data: buffer });
|
|
882
|
+
const result = await parser.getText();
|
|
883
|
+
text = (result.text ?? '').trim();
|
|
884
|
+
numPages = result.total;
|
|
885
|
+
parser.destroy?.();
|
|
886
|
+
} else {
|
|
887
|
+
const data = await pdfParseV1(buffer);
|
|
888
|
+
text = (data.text ?? '').trim();
|
|
889
|
+
numPages = data.numpages;
|
|
890
|
+
}
|
|
891
|
+
|
|
872
892
|
if (text) {
|
|
873
|
-
log?.info?.(`PDF 文档解析成功: ${filePath}, 文本长度=${text.length}, 页数=${
|
|
893
|
+
log?.info?.(`PDF 文档解析成功: ${filePath}, 文本长度=${text.length}, 页数=${numPages}`);
|
|
874
894
|
return text;
|
|
875
895
|
} else {
|
|
876
896
|
log?.warn?.(`PDF 文档解析结果为空: ${filePath}`);
|
|
@@ -1493,7 +1513,7 @@ export async function handleDingTalkMessageInternal(params: HandleMessageParams)
|
|
|
1493
1513
|
true, // ✅ 使用主动 API 模式
|
|
1494
1514
|
mediaTarget
|
|
1495
1515
|
);
|
|
1496
|
-
finalText = await
|
|
1516
|
+
finalText = await uploadAndReplaceFileMarkers(
|
|
1497
1517
|
finalText,
|
|
1498
1518
|
'',
|
|
1499
1519
|
config,
|
package/src/reply-dispatcher.ts
CHANGED
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
processLocalImages,
|
|
44
44
|
processVideoMarkers,
|
|
45
45
|
processAudioMarkers,
|
|
46
|
-
|
|
46
|
+
uploadAndReplaceFileMarkers,
|
|
47
47
|
} from "./services/media/index.ts";
|
|
48
48
|
|
|
49
49
|
|
|
@@ -314,7 +314,7 @@ export function createDingtalkReplyDispatcher(params: CreateDingtalkReplyDispatc
|
|
|
314
314
|
true, // ✅ 使用主动 API 模式
|
|
315
315
|
target
|
|
316
316
|
);
|
|
317
|
-
finalText = await
|
|
317
|
+
finalText = await uploadAndReplaceFileMarkers(
|
|
318
318
|
finalText,
|
|
319
319
|
'',
|
|
320
320
|
account.config as DingtalkConfig,
|
|
@@ -607,7 +607,8 @@ export function createDingtalkReplyDispatcher(params: CreateDingtalkReplyDispatc
|
|
|
607
607
|
// 安全检查:确保 code 存在且为字符串
|
|
608
608
|
const errorCode = err.response?.data?.code;
|
|
609
609
|
if (err.response?.status === 403 && typeof errorCode === 'string' && errorCode.includes('QpsLimit')) {
|
|
610
|
-
// QPS
|
|
610
|
+
// QPS 限流,跳过本次更新;同步更新节流时间,防止立即重试再次触发限流
|
|
611
|
+
lastUpdateTime = now;
|
|
611
612
|
log.warn(`[DingTalk][AICard] QPS 限流,跳过本次更新`);
|
|
612
613
|
} else {
|
|
613
614
|
log.error(`[DingTalk][onPartialReply] ❌ AI Card 更新失败:${err.message}`);
|
|
@@ -29,9 +29,14 @@ export async function parseDocumentFile(filePath: string, log?: any): Promise<st
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
-
*
|
|
32
|
+
* 提取文件标记,上传文件到钉钉,并用文本替换标记。
|
|
33
|
+
*
|
|
34
|
+
* 注意:此函数只做「上传 + 文本替换」,不会发送独立的文件消息。
|
|
35
|
+
* 如果需要上传后再发送独立文件消息,请使用 media.ts 中的 processFileMarkers。
|
|
36
|
+
*
|
|
37
|
+
* 调用方:reply-dispatcher.ts、message-handler.ts(通过 media/index.ts 导入)
|
|
33
38
|
*/
|
|
34
|
-
export async function
|
|
39
|
+
export async function uploadAndReplaceFileMarkers(
|
|
35
40
|
content: string,
|
|
36
41
|
sessionWebhook: string,
|
|
37
42
|
config: DingtalkConfig,
|