@dingtalk-real-ai/dingtalk-connector 0.8.11 → 0.8.12

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 CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.8.12] - 2026-04-01
9
+
10
+ ### 修复 / Fixes
11
+ - 🐛 **修复 v0.8.11 安装后启动崩溃** ([#419](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/419)) - `mammoth` 和 `pdf-parse` 使用静态 import 但已从 dependencies 移除,导致模块加载阶段报错 `Cannot find module 'mammoth'`。改为动态 import + 优雅降级
12
+ **Fix startup crash after v0.8.11 installation** - Changed `mammoth` and `pdf-parse` from static import to dynamic import with graceful degradation
13
+
14
+ ### 改进 / Improvements
15
+ - ✅ **大幅精简依赖体积** - 移除 `pdf-parse`(~21MB)、`fluent-ffmpeg`(~12MB)、`@ffmpeg-installer/ffmpeg`(~70MB)、`@ffprobe-installer/ffprobe` 等非核心依赖,仅保留 `mammoth`(~2MB)在 `optionalDependencies`
16
+ **Significantly reduce dependency size** - Removed ~100MB of non-core optional dependencies, keeping only `mammoth` (~2MB)
17
+
18
+ ### 重构 / Refactoring
19
+ - ✅ **移除无效的代理禁用代码** - 经源码分析 `dingtalk-stream` SDK 的 WebSocket 连接使用 `ws` 库直接建立,不受 `axios.defaults.proxy` 影响。移除 `proxy-config.ts` 及相关代理配置
20
+ **Remove ineffective proxy bypass code** - Analysis showed `ws` library bypasses axios entirely; removed `proxy-config.ts` and all proxy configuration code
21
+
8
22
  ## [0.8.11] - 2026-04-01
9
23
 
10
24
  ### 新增 / Added
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "dingtalk-connector",
3
3
  "name": "DingTalk Channel",
4
- "version": "0.8.11",
4
+ "version": "0.8.12",
5
5
  "description": "DingTalk (钉钉) messaging channel via Stream mode with AI Card streaming",
6
6
  "author": "DingTalk Real Team",
7
7
  "main": "index.ts",
@@ -27,21 +27,44 @@
27
27
  },
28
28
  "clientId": {
29
29
  "anyOf": [
30
- { "type": "string" },
31
- { "type": "number" }
30
+ {
31
+ "type": "string"
32
+ },
33
+ {
34
+ "type": "number"
35
+ }
32
36
  ]
33
37
  },
34
38
  "clientSecret": {
35
39
  "anyOf": [
36
- { "type": "string" },
40
+ {
41
+ "type": "string"
42
+ },
37
43
  {
38
44
  "type": "object",
39
45
  "properties": {
40
- "source": { "type": "string", "enum": ["env", "file", "exec"] },
41
- "provider": { "type": "string", "minLength": 1 },
42
- "id": { "type": "string", "minLength": 1 }
46
+ "source": {
47
+ "type": "string",
48
+ "enum": [
49
+ "env",
50
+ "file",
51
+ "exec"
52
+ ]
53
+ },
54
+ "provider": {
55
+ "type": "string",
56
+ "minLength": 1
57
+ },
58
+ "id": {
59
+ "type": "string",
60
+ "minLength": 1
61
+ }
43
62
  },
44
- "required": ["source", "provider", "id"],
63
+ "required": [
64
+ "source",
65
+ "provider",
66
+ "id"
67
+ ],
45
68
  "additionalProperties": false
46
69
  }
47
70
  ]
@@ -55,23 +78,45 @@
55
78
  "dmPolicy": {
56
79
  "default": "open",
57
80
  "type": "string",
58
- "enum": ["open", "pairing", "allowlist"]
81
+ "enum": [
82
+ "open",
83
+ "pairing",
84
+ "allowlist"
85
+ ]
59
86
  },
60
87
  "allowFrom": {
61
88
  "type": "array",
62
89
  "items": {
63
- "anyOf": [{ "type": "string" }, { "type": "number" }]
90
+ "anyOf": [
91
+ {
92
+ "type": "string"
93
+ },
94
+ {
95
+ "type": "number"
96
+ }
97
+ ]
64
98
  }
65
99
  },
66
100
  "groupPolicy": {
67
101
  "default": "open",
68
102
  "type": "string",
69
- "enum": ["open", "allowlist", "disabled"]
103
+ "enum": [
104
+ "open",
105
+ "allowlist",
106
+ "disabled"
107
+ ]
70
108
  },
71
109
  "groupAllowFrom": {
72
110
  "type": "array",
73
111
  "items": {
74
- "anyOf": [{ "type": "string" }, { "type": "number" }]
112
+ "anyOf": [
113
+ {
114
+ "type": "string"
115
+ },
116
+ {
117
+ "type": "number"
118
+ }
119
+ ]
75
120
  }
76
121
  },
77
122
  "requireMention": {
@@ -83,26 +128,52 @@
83
128
  "additionalProperties": {
84
129
  "type": "object",
85
130
  "properties": {
86
- "requireMention": { "type": "boolean" },
131
+ "requireMention": {
132
+ "type": "boolean"
133
+ },
87
134
  "tools": {
88
135
  "type": "object",
89
136
  "properties": {
90
- "allow": { "type": "array", "items": { "type": "string" } },
91
- "deny": { "type": "array", "items": { "type": "string" } }
137
+ "allow": {
138
+ "type": "array",
139
+ "items": {
140
+ "type": "string"
141
+ }
142
+ },
143
+ "deny": {
144
+ "type": "array",
145
+ "items": {
146
+ "type": "string"
147
+ }
148
+ }
92
149
  },
93
150
  "additionalProperties": false
94
151
  },
95
- "enabled": { "type": "boolean" },
152
+ "enabled": {
153
+ "type": "boolean"
154
+ },
96
155
  "allowFrom": {
97
156
  "type": "array",
98
157
  "items": {
99
- "anyOf": [{ "type": "string" }, { "type": "number" }]
158
+ "anyOf": [
159
+ {
160
+ "type": "string"
161
+ },
162
+ {
163
+ "type": "number"
164
+ }
165
+ ]
100
166
  }
101
167
  },
102
- "systemPrompt": { "type": "string" },
168
+ "systemPrompt": {
169
+ "type": "string"
170
+ },
103
171
  "groupSessionScope": {
104
172
  "type": "string",
105
- "enum": ["group", "group_sender"]
173
+ "enum": [
174
+ "group",
175
+ "group_sender"
176
+ ]
106
177
  }
107
178
  },
108
179
  "additionalProperties": false
@@ -123,8 +194,12 @@
123
194
  "tools": {
124
195
  "type": "object",
125
196
  "properties": {
126
- "docs": { "type": "boolean" },
127
- "media": { "type": "boolean" }
197
+ "docs": {
198
+ "type": "boolean"
199
+ },
200
+ "media": {
201
+ "type": "boolean"
202
+ }
128
203
  },
129
204
  "additionalProperties": false
130
205
  },
@@ -145,7 +220,10 @@
145
220
  "groupSessionScope": {
146
221
  "default": "group",
147
222
  "type": "string",
148
- "enum": ["group", "group_sender"]
223
+ "enum": [
224
+ "group",
225
+ "group_sender"
226
+ ]
149
227
  },
150
228
  "asyncMode": {
151
229
  "type": "boolean"
@@ -164,82 +242,212 @@
164
242
  "additionalProperties": {
165
243
  "type": "object",
166
244
  "properties": {
167
- "enabled": { "type": "boolean" },
168
- "name": { "type": "string" },
245
+ "enabled": {
246
+ "type": "boolean"
247
+ },
248
+ "name": {
249
+ "type": "string"
250
+ },
169
251
  "clientId": {
170
- "anyOf": [{ "type": "string" }, { "type": "number" }]
252
+ "anyOf": [
253
+ {
254
+ "type": "string"
255
+ },
256
+ {
257
+ "type": "number"
258
+ }
259
+ ]
171
260
  },
172
261
  "clientSecret": {
173
262
  "anyOf": [
174
- { "type": "string" },
263
+ {
264
+ "type": "string"
265
+ },
175
266
  {
176
267
  "type": "object",
177
268
  "properties": {
178
- "source": { "type": "string", "enum": ["env", "file", "exec"] },
179
- "provider": { "type": "string", "minLength": 1 },
180
- "id": { "type": "string", "minLength": 1 }
269
+ "source": {
270
+ "type": "string",
271
+ "enum": [
272
+ "env",
273
+ "file",
274
+ "exec"
275
+ ]
276
+ },
277
+ "provider": {
278
+ "type": "string",
279
+ "minLength": 1
280
+ },
281
+ "id": {
282
+ "type": "string",
283
+ "minLength": 1
284
+ }
181
285
  },
182
- "required": ["source", "provider", "id"],
286
+ "required": [
287
+ "source",
288
+ "provider",
289
+ "id"
290
+ ],
183
291
  "additionalProperties": false
184
292
  }
185
293
  ]
186
294
  },
187
- "dmPolicy": { "type": "string", "enum": ["open", "pairing", "allowlist"] },
295
+ "dmPolicy": {
296
+ "type": "string",
297
+ "enum": [
298
+ "open",
299
+ "pairing",
300
+ "allowlist"
301
+ ]
302
+ },
188
303
  "allowFrom": {
189
304
  "type": "array",
190
- "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
305
+ "items": {
306
+ "anyOf": [
307
+ {
308
+ "type": "string"
309
+ },
310
+ {
311
+ "type": "number"
312
+ }
313
+ ]
314
+ }
315
+ },
316
+ "groupPolicy": {
317
+ "type": "string",
318
+ "enum": [
319
+ "open",
320
+ "allowlist",
321
+ "disabled"
322
+ ]
191
323
  },
192
- "groupPolicy": { "type": "string", "enum": ["open", "allowlist", "disabled"] },
193
324
  "groupAllowFrom": {
194
325
  "type": "array",
195
- "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
326
+ "items": {
327
+ "anyOf": [
328
+ {
329
+ "type": "string"
330
+ },
331
+ {
332
+ "type": "number"
333
+ }
334
+ ]
335
+ }
336
+ },
337
+ "requireMention": {
338
+ "type": "boolean"
196
339
  },
197
- "requireMention": { "type": "boolean" },
198
340
  "groups": {
199
341
  "type": "object",
200
342
  "additionalProperties": {
201
343
  "type": "object",
202
344
  "properties": {
203
- "requireMention": { "type": "boolean" },
345
+ "requireMention": {
346
+ "type": "boolean"
347
+ },
204
348
  "tools": {
205
349
  "type": "object",
206
350
  "properties": {
207
- "allow": { "type": "array", "items": { "type": "string" } },
208
- "deny": { "type": "array", "items": { "type": "string" } }
351
+ "allow": {
352
+ "type": "array",
353
+ "items": {
354
+ "type": "string"
355
+ }
356
+ },
357
+ "deny": {
358
+ "type": "array",
359
+ "items": {
360
+ "type": "string"
361
+ }
362
+ }
209
363
  },
210
364
  "additionalProperties": false
211
365
  },
212
- "enabled": { "type": "boolean" },
366
+ "enabled": {
367
+ "type": "boolean"
368
+ },
213
369
  "allowFrom": {
214
370
  "type": "array",
215
- "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
371
+ "items": {
372
+ "anyOf": [
373
+ {
374
+ "type": "string"
375
+ },
376
+ {
377
+ "type": "number"
378
+ }
379
+ ]
380
+ }
381
+ },
382
+ "systemPrompt": {
383
+ "type": "string"
216
384
  },
217
- "systemPrompt": { "type": "string" },
218
- "groupSessionScope": { "type": "string", "enum": ["group", "group_sender"] }
385
+ "groupSessionScope": {
386
+ "type": "string",
387
+ "enum": [
388
+ "group",
389
+ "group_sender"
390
+ ]
391
+ }
219
392
  },
220
393
  "additionalProperties": false
221
394
  }
222
395
  },
223
- "historyLimit": { "type": "integer", "minimum": 0 },
224
- "textChunkLimit": { "type": "integer", "exclusiveMinimum": 0 },
225
- "mediaMaxMb": { "type": "number", "exclusiveMinimum": 0 },
396
+ "historyLimit": {
397
+ "type": "integer",
398
+ "minimum": 0
399
+ },
400
+ "textChunkLimit": {
401
+ "type": "integer",
402
+ "exclusiveMinimum": 0
403
+ },
404
+ "mediaMaxMb": {
405
+ "type": "number",
406
+ "exclusiveMinimum": 0
407
+ },
226
408
  "tools": {
227
409
  "type": "object",
228
410
  "properties": {
229
- "docs": { "type": "boolean" },
230
- "media": { "type": "boolean" }
411
+ "docs": {
412
+ "type": "boolean"
413
+ },
414
+ "media": {
415
+ "type": "boolean"
416
+ }
231
417
  },
232
418
  "additionalProperties": false
233
419
  },
234
- "typingIndicator": { "type": "boolean" },
235
- "resolveSenderNames": { "type": "boolean" },
236
- "separateSessionByConversation": { "type": "boolean" },
237
- "sharedMemoryAcrossConversations": { "type": "boolean" },
238
- "groupSessionScope": { "type": "string", "enum": ["group", "group_sender"] },
239
- "asyncMode": { "type": "boolean" },
240
- "ackText": { "type": "string" },
241
- "endpoint": { "type": "string" },
242
- "debug": { "type": "boolean" }
420
+ "typingIndicator": {
421
+ "type": "boolean"
422
+ },
423
+ "resolveSenderNames": {
424
+ "type": "boolean"
425
+ },
426
+ "separateSessionByConversation": {
427
+ "type": "boolean"
428
+ },
429
+ "sharedMemoryAcrossConversations": {
430
+ "type": "boolean"
431
+ },
432
+ "groupSessionScope": {
433
+ "type": "string",
434
+ "enum": [
435
+ "group",
436
+ "group_sender"
437
+ ]
438
+ },
439
+ "asyncMode": {
440
+ "type": "boolean"
441
+ },
442
+ "ackText": {
443
+ "type": "string"
444
+ },
445
+ "endpoint": {
446
+ "type": "string"
447
+ },
448
+ "debug": {
449
+ "type": "boolean"
450
+ }
243
451
  },
244
452
  "additionalProperties": false
245
453
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dingtalk-real-ai/dingtalk-connector",
3
- "version": "0.8.11",
3
+ "version": "0.8.12",
4
4
  "description": "DingTalk (钉钉) channel connector — Stream mode with AI Card streaming",
5
5
  "main": "index.ts",
6
6
  "type": "module",
@@ -49,6 +49,9 @@
49
49
  "form-data": "^4.0.0",
50
50
  "zod": "^4.3.6"
51
51
  },
52
+ "optionalDependencies": {
53
+ "mammoth": "^1.8.0"
54
+ },
52
55
  "peerDependencies": {
53
56
  "openclaw": "^2026.3.23-2"
54
57
  },
@@ -74,4 +77,4 @@
74
77
  ],
75
78
  "installDependencies": true
76
79
  }
77
- }
80
+ }
@@ -130,31 +130,6 @@ export async function monitorSingleAccount(
130
130
  logger.info(`Initializing with clientId: ${clientIdStr.substring(0, 8)}...`);
131
131
  logger.info(`WebSocket keepAlive: false (using application-layer heartbeat)`);
132
132
 
133
- // 🔧 配置 dingtalk-stream SDK 的代理策略
134
- //
135
- // dingtalk-stream SDK 内部使用 axios 发起 HTTP 请求(获取 WebSocket endpoint)。
136
- // 策略与 src/utils/http-client.ts 保持一致:
137
- // - 默认禁用代理:避免阿里内网 PAC 文件将 *.dingtalk.com 路由到内网代理,
138
- // 导致外网环境连接超时。
139
- // - DINGTALK_FORCE_PROXY=true:保留系统代理,供需要通过代理访问外网的内网环境使用。
140
- //
141
- // 注意:这里修改的是 axios 全局默认值,会影响 dingtalk-stream SDK 内部的 axios 实例。
142
- // src/utils/http-client.ts 中的专用实例已在创建时单独配置,不受此处影响。
143
- try {
144
- const axios = (await import("axios")).default;
145
- if (axios.defaults) {
146
- const shouldDisableProxy = process.env.DINGTALK_FORCE_PROXY !== 'true';
147
- if (shouldDisableProxy) {
148
- axios.defaults.proxy = false;
149
- logger.debug(`已禁用 axios 全局代理(dingtalk-stream SDK),如需代理请设置 DINGTALK_FORCE_PROXY=true`);
150
- } else {
151
- logger.debug(`保留系统代理配置(DINGTALK_FORCE_PROXY=true),dingtalk-stream SDK 将通过代理连接`);
152
- }
153
- }
154
- } catch (err) {
155
- logger.warn(`无法配置 axios 代理设置: ${err}`);
156
- }
157
-
158
133
  // 动态导入 dingtalk-stream 模块(避免循环依赖和 ESM/CJS 兼容性问题)
159
134
  const dingtalkStreamModule = await import("dingtalk-stream");
160
135
  const DWClient = dingtalkStreamModule.DWClient;
@@ -62,8 +62,6 @@ import { createLoggerFromConfig } from '../utils/index.ts';
62
62
  import * as fs from 'fs';
63
63
  import * as path from 'path';
64
64
  import * as os from 'os';
65
- import mammoth from 'mammoth';
66
- import pdfParse from 'pdf-parse';
67
65
 
68
66
  // ============ 常量 ============
69
67
 
@@ -826,6 +824,15 @@ export async function downloadFileToLocal(
826
824
  async function parseDocxFile(filePath: string, log?: any): Promise<string | null> {
827
825
  try {
828
826
  log?.info?.(`开始解析 Word 文档: ${filePath}`);
827
+
828
+ let mammoth: any;
829
+ try {
830
+ mammoth = (await import('mammoth')).default;
831
+ } catch {
832
+ log?.warn?.('mammoth 库未安装,无法解析 .docx 文件。请运行: npm install mammoth');
833
+ return null;
834
+ }
835
+
829
836
  const buffer = fs.readFileSync(filePath);
830
837
  const result = await mammoth.extractRawText({ buffer });
831
838
  const text = result.value.trim();
@@ -849,6 +856,15 @@ async function parseDocxFile(filePath: string, log?: any): Promise<string | null
849
856
  async function parsePdfFile(filePath: string, log?: any): Promise<string | null> {
850
857
  try {
851
858
  log?.info?.(`开始解析 PDF 文档: ${filePath}`);
859
+
860
+ let pdfParse: any;
861
+ try {
862
+ pdfParse = (await import('pdf-parse')).default;
863
+ } catch {
864
+ log?.warn?.('pdf-parse 库未安装,无法解析 .pdf 文件。请运行: npm install pdf-parse');
865
+ return null;
866
+ }
867
+
852
868
  const buffer = fs.readFileSync(filePath);
853
869
  const data = await pdfParse(buffer);
854
870
  const text = data.text.trim();
@@ -1,15 +1,7 @@
1
1
  /**
2
2
  * HTTP 客户端配置模块
3
3
  *
4
- * 提供统一的 axios 实例,禁用代理以避免系统 PAC 文件影响
5
- *
6
- * 问题背景:
7
- * - 阿里巴巴内网 PAC 文件会将 *.dingtalk.com 路由到内网代理(如 192.168.1.176:443)
8
- * - 当不在内网环境时,会导致连接超时
9
- *
10
- * 解决方案:
11
- * - 创建专用的 axios 实例,禁用代理
12
- * - 仅影响钉钉插件,不影响 OpenClaw Gateway 和其他插件
4
+ * 提供统一的 axios 实例,用于钉钉 API 请求。
13
5
  *
14
6
  * 使用方式:
15
7
  * ```typescript
@@ -20,41 +12,26 @@
20
12
  */
21
13
 
22
14
  import axios, { type AxiosInstance } from 'axios';
23
- import { getProxyConfig } from './proxy-config.ts';
24
15
 
25
- /**
26
- * 钉钉专用 HTTP 客户端
27
- *
28
- * 特性:
29
- * - 禁用代理(避免 PAC 文件影响)
30
- * - 30 秒超时
31
- * - 仅影响钉钉插件的请求
32
- */
16
+ /** 钉钉专用 HTTP 客户端(30 秒超时) */
33
17
  export const dingtalkHttp: AxiosInstance = axios.create({
34
- proxy: getProxyConfig(),
35
18
  timeout: 30000,
36
19
  headers: {
37
20
  'Content-Type': 'application/json',
38
21
  },
39
22
  });
40
23
 
41
- /**
42
- * 钉钉 OAPI 专用 HTTP 客户端(用于媒体上传等)
43
- */
24
+ /** 钉钉 OAPI 专用 HTTP 客户端(60 秒超时,用于媒体上传等) */
44
25
  export const dingtalkOapiHttp: AxiosInstance = axios.create({
45
- proxy: getProxyConfig(),
46
- timeout: 60000, // 媒体上传可能需要更长时间
26
+ timeout: 60000,
47
27
  headers: {
48
28
  'Content-Type': 'application/json',
49
29
  },
50
30
  });
51
31
 
52
- /**
53
- * 用于文件上传的 HTTP 客户端(支持 multipart/form-data)
54
- */
32
+ /** 文件上传专用 HTTP 客户端(120 秒超时,无 body 大小限制) */
55
33
  export const dingtalkUploadHttp: AxiosInstance = axios.create({
56
- proxy: getProxyConfig(),
57
- timeout: 120000, // 文件上传需要更长时间
34
+ timeout: 120000,
58
35
  maxContentLength: Infinity,
59
36
  maxBodyLength: Infinity,
60
37
  });
@@ -1,35 +0,0 @@
1
- /**
2
- * 代理配置模块
3
- *
4
- * 从环境变量中读取代理配置,与 HTTP 客户端实例分离,
5
- * 避免安全扫描器误报"环境变量访问 + 网络请求"组合。
6
- *
7
- * 策略:
8
- * 1. 如果设置了 DINGTALK_FORCE_PROXY=true,使用环境变量中的代理
9
- * 2. 否则禁用代理(避免被系统 PAC 影响)
10
- */
11
-
12
- import type { CreateAxiosDefaults } from 'axios';
13
-
14
- /**
15
- * 获取代理配置
16
- *
17
- * 默认禁用代理,避免阿里内网 PAC 文件将 *.dingtalk.com 路由到内网代理。
18
- * 可通过 DINGTALK_FORCE_PROXY=true 环境变量强制启用代理。
19
- */
20
- export function getProxyConfig(): CreateAxiosDefaults['proxy'] {
21
- if (process.env.DINGTALK_FORCE_PROXY === 'true') {
22
- const proxyUrl =
23
- process.env.https_proxy ||
24
- process.env.HTTPS_PROXY ||
25
- process.env.http_proxy ||
26
- process.env.HTTP_PROXY;
27
-
28
- if (proxyUrl) {
29
- return proxyUrl as any;
30
- }
31
- }
32
-
33
- // 默认禁用代理
34
- return false;
35
- }