@dingtalk-real-ai/dingtalk-connector 0.8.10 → 0.8.11-beta.0

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "dingtalk-connector",
3
3
  "name": "DingTalk Channel",
4
- "version": "0.8.10",
4
+ "version": "0.8.11-beta.0",
5
5
  "description": "DingTalk (钉钉) messaging channel via Stream mode with AI Card streaming",
6
6
  "author": "DingTalk Real Team",
7
7
  "main": "index.ts",
@@ -10,7 +10,281 @@
10
10
  ],
11
11
  "configSchema": {
12
12
  "type": "object",
13
- "additionalProperties": false,
14
- "properties": {}
13
+ "additionalProperties": true
14
+ },
15
+ "channelConfigs": {
16
+ "dingtalk-connector": {
17
+ "label": "DingTalk",
18
+ "description": "钉钉企业内部机器人,使用 Stream 模式,无需公网 IP,支持 AI Card 流式响应。",
19
+ "schema": {
20
+ "type": "object",
21
+ "properties": {
22
+ "enabled": {
23
+ "type": "boolean"
24
+ },
25
+ "defaultAccount": {
26
+ "type": "string"
27
+ },
28
+ "clientId": {
29
+ "anyOf": [
30
+ { "type": "string" },
31
+ { "type": "number" }
32
+ ]
33
+ },
34
+ "clientSecret": {
35
+ "anyOf": [
36
+ { "type": "string" },
37
+ {
38
+ "type": "object",
39
+ "properties": {
40
+ "source": { "type": "string", "enum": ["env", "file", "exec"] },
41
+ "provider": { "type": "string", "minLength": 1 },
42
+ "id": { "type": "string", "minLength": 1 }
43
+ },
44
+ "required": ["source", "provider", "id"],
45
+ "additionalProperties": false
46
+ }
47
+ ]
48
+ },
49
+ "enableMediaUpload": {
50
+ "type": "boolean"
51
+ },
52
+ "systemPrompt": {
53
+ "type": "string"
54
+ },
55
+ "dmPolicy": {
56
+ "default": "open",
57
+ "type": "string",
58
+ "enum": ["open", "pairing", "allowlist"]
59
+ },
60
+ "allowFrom": {
61
+ "type": "array",
62
+ "items": {
63
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
64
+ }
65
+ },
66
+ "groupPolicy": {
67
+ "default": "open",
68
+ "type": "string",
69
+ "enum": ["open", "allowlist", "disabled"]
70
+ },
71
+ "groupAllowFrom": {
72
+ "type": "array",
73
+ "items": {
74
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
75
+ }
76
+ },
77
+ "requireMention": {
78
+ "default": true,
79
+ "type": "boolean"
80
+ },
81
+ "groups": {
82
+ "type": "object",
83
+ "additionalProperties": {
84
+ "type": "object",
85
+ "properties": {
86
+ "requireMention": { "type": "boolean" },
87
+ "tools": {
88
+ "type": "object",
89
+ "properties": {
90
+ "allow": { "type": "array", "items": { "type": "string" } },
91
+ "deny": { "type": "array", "items": { "type": "string" } }
92
+ },
93
+ "additionalProperties": false
94
+ },
95
+ "enabled": { "type": "boolean" },
96
+ "allowFrom": {
97
+ "type": "array",
98
+ "items": {
99
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
100
+ }
101
+ },
102
+ "systemPrompt": { "type": "string" },
103
+ "groupSessionScope": {
104
+ "type": "string",
105
+ "enum": ["group", "group_sender"]
106
+ }
107
+ },
108
+ "additionalProperties": false
109
+ }
110
+ },
111
+ "historyLimit": {
112
+ "type": "integer",
113
+ "minimum": 0
114
+ },
115
+ "textChunkLimit": {
116
+ "type": "integer",
117
+ "exclusiveMinimum": 0
118
+ },
119
+ "mediaMaxMb": {
120
+ "type": "number",
121
+ "exclusiveMinimum": 0
122
+ },
123
+ "tools": {
124
+ "type": "object",
125
+ "properties": {
126
+ "docs": { "type": "boolean" },
127
+ "media": { "type": "boolean" }
128
+ },
129
+ "additionalProperties": false
130
+ },
131
+ "typingIndicator": {
132
+ "type": "boolean"
133
+ },
134
+ "resolveSenderNames": {
135
+ "type": "boolean"
136
+ },
137
+ "separateSessionByConversation": {
138
+ "default": true,
139
+ "type": "boolean"
140
+ },
141
+ "sharedMemoryAcrossConversations": {
142
+ "default": false,
143
+ "type": "boolean"
144
+ },
145
+ "groupSessionScope": {
146
+ "default": "group",
147
+ "type": "string",
148
+ "enum": ["group", "group_sender"]
149
+ },
150
+ "asyncMode": {
151
+ "type": "boolean"
152
+ },
153
+ "ackText": {
154
+ "type": "string"
155
+ },
156
+ "endpoint": {
157
+ "type": "string"
158
+ },
159
+ "debug": {
160
+ "type": "boolean"
161
+ },
162
+ "accounts": {
163
+ "type": "object",
164
+ "additionalProperties": {
165
+ "type": "object",
166
+ "properties": {
167
+ "enabled": { "type": "boolean" },
168
+ "name": { "type": "string" },
169
+ "clientId": {
170
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
171
+ },
172
+ "clientSecret": {
173
+ "anyOf": [
174
+ { "type": "string" },
175
+ {
176
+ "type": "object",
177
+ "properties": {
178
+ "source": { "type": "string", "enum": ["env", "file", "exec"] },
179
+ "provider": { "type": "string", "minLength": 1 },
180
+ "id": { "type": "string", "minLength": 1 }
181
+ },
182
+ "required": ["source", "provider", "id"],
183
+ "additionalProperties": false
184
+ }
185
+ ]
186
+ },
187
+ "dmPolicy": { "type": "string", "enum": ["open", "pairing", "allowlist"] },
188
+ "allowFrom": {
189
+ "type": "array",
190
+ "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
191
+ },
192
+ "groupPolicy": { "type": "string", "enum": ["open", "allowlist", "disabled"] },
193
+ "groupAllowFrom": {
194
+ "type": "array",
195
+ "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
196
+ },
197
+ "requireMention": { "type": "boolean" },
198
+ "groups": {
199
+ "type": "object",
200
+ "additionalProperties": {
201
+ "type": "object",
202
+ "properties": {
203
+ "requireMention": { "type": "boolean" },
204
+ "tools": {
205
+ "type": "object",
206
+ "properties": {
207
+ "allow": { "type": "array", "items": { "type": "string" } },
208
+ "deny": { "type": "array", "items": { "type": "string" } }
209
+ },
210
+ "additionalProperties": false
211
+ },
212
+ "enabled": { "type": "boolean" },
213
+ "allowFrom": {
214
+ "type": "array",
215
+ "items": { "anyOf": [{ "type": "string" }, { "type": "number" }] }
216
+ },
217
+ "systemPrompt": { "type": "string" },
218
+ "groupSessionScope": { "type": "string", "enum": ["group", "group_sender"] }
219
+ },
220
+ "additionalProperties": false
221
+ }
222
+ },
223
+ "historyLimit": { "type": "integer", "minimum": 0 },
224
+ "textChunkLimit": { "type": "integer", "exclusiveMinimum": 0 },
225
+ "mediaMaxMb": { "type": "number", "exclusiveMinimum": 0 },
226
+ "tools": {
227
+ "type": "object",
228
+ "properties": {
229
+ "docs": { "type": "boolean" },
230
+ "media": { "type": "boolean" }
231
+ },
232
+ "additionalProperties": false
233
+ },
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" }
243
+ },
244
+ "additionalProperties": false
245
+ }
246
+ }
247
+ },
248
+ "additionalProperties": false
249
+ },
250
+ "uiHints": {
251
+ "channels.dingtalk-connector.clientId": {
252
+ "label": "Client ID (AppKey)",
253
+ "help": "钉钉应用的 AppKey / Client ID",
254
+ "sensitive": true
255
+ },
256
+ "channels.dingtalk-connector.clientSecret": {
257
+ "label": "Client Secret (AppSecret)",
258
+ "help": "钉钉应用的 AppSecret / Client Secret",
259
+ "sensitive": true
260
+ },
261
+ "channels.dingtalk-connector.dmPolicy": {
262
+ "label": "DM Policy",
263
+ "help": "单聊策略:open(开放)、pairing(配对)、allowlist(白名单)"
264
+ },
265
+ "channels.dingtalk-connector.groupPolicy": {
266
+ "label": "Group Policy",
267
+ "help": "群聊策略:open(开放)、allowlist(白名单)、disabled(禁用)"
268
+ },
269
+ "channels.dingtalk-connector.requireMention": {
270
+ "label": "Require @Mention",
271
+ "help": "群聊中是否需要 @机器人 才响应"
272
+ },
273
+ "channels.dingtalk-connector.debug": {
274
+ "label": "Debug Mode",
275
+ "help": "启用调试日志",
276
+ "advanced": true
277
+ },
278
+ "channels.dingtalk-connector.endpoint": {
279
+ "label": "Gateway Endpoint",
280
+ "help": "自定义 DWClient 网关地址(高级)",
281
+ "advanced": true
282
+ },
283
+ "channels.dingtalk-connector.accounts": {
284
+ "label": "Accounts",
285
+ "help": "多账号配置,每个 key 是账号 ID"
286
+ }
287
+ }
288
+ }
15
289
  }
16
290
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dingtalk-real-ai/dingtalk-connector",
3
- "version": "0.8.10",
3
+ "version": "0.8.11-beta.0",
4
4
  "description": "DingTalk (钉钉) channel connector — Stream mode with AI Card streaming",
5
5
  "main": "index.ts",
6
6
  "type": "module",
@@ -51,7 +51,7 @@
51
51
  "mammoth": "^1.8.0",
52
52
  "pako": "^2.1.0",
53
53
  "pdf-parse": "^1.1.1",
54
- "zod": "^3.22.0"
54
+ "zod": "^4.3.6"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "openclaw": "^2026.3.23-2"
package/src/channel.ts CHANGED
@@ -2,12 +2,16 @@ import type {
2
2
  ChannelPlugin,
3
3
  ClawdbotConfig,
4
4
  } from "openclaw/plugin-sdk";
5
+ import {
6
+ buildChannelConfigSchema,
7
+ } from "openclaw/plugin-sdk/core";
5
8
  import {
6
9
  createDefaultChannelRuntimeState,
7
10
  DEFAULT_ACCOUNT_ID,
8
11
  resolveAllowlistProviderRuntimeGroupPolicy,
9
12
  resolveDefaultGroupPolicy,
10
13
  } from "./sdk/helpers.ts";
14
+ import { DingtalkConfigBaseSchema } from "./config/schema.ts";
11
15
  import { createLogger } from "./utils/logger.ts";
12
16
  import {
13
17
  resolveDingtalkAccount,
@@ -76,103 +80,7 @@ export const dingtalkPlugin: ChannelPlugin<ResolvedDingtalkAccount> = {
76
80
  stripPatterns: () => ['@[^\\s]+'], // Strip @mentions
77
81
  },
78
82
  reload: { configPrefixes: ["channels.dingtalk-connector"] },
79
- configSchema: {
80
- schema: {
81
- type: "object",
82
- additionalProperties: false,
83
- properties: {
84
- enabled: { type: "boolean" },
85
- defaultAccount: { type: "string" },
86
- clientId: { type: "string" },
87
- clientSecret: { type: "string" },
88
- enableMediaUpload: { type: "boolean" },
89
- systemPrompt: { type: "string" },
90
- dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
91
- allowFrom: { type: "array", items: { type: "string" } },
92
- groupPolicy: { type: "string", enum: ["open", "allowlist", "disabled"] },
93
- groupAllowFrom: { type: "array", items: { type: "string" } },
94
- requireMention: { type: "boolean" },
95
- groupSessionScope: { type: "string", enum: ["group", "group_sender"] },
96
- separateSessionByConversation: { type: "boolean" },
97
- sharedMemoryAcrossConversations: { type: "boolean" },
98
- historyLimit: { type: "integer", minimum: 0 },
99
- textChunkLimit: { type: "integer", minimum: 1 },
100
- mediaMaxMb: { type: "number", minimum: 0 },
101
- typingIndicator: { type: "boolean" },
102
- resolveSenderNames: { type: "boolean" },
103
- asyncMode: { type: "boolean" },
104
- ackText: { type: "string" },
105
- endpoint: { type: "string" },
106
- debug: { type: "boolean" },
107
- tools: {
108
- type: "object",
109
- additionalProperties: false,
110
- properties: {
111
- docs: { type: "boolean" },
112
- media: { type: "boolean" },
113
- },
114
- },
115
- groups: {
116
- type: "object",
117
- additionalProperties: {
118
- type: "object",
119
- properties: {
120
- requireMention: { type: "boolean" },
121
- tools: {
122
- type: "object",
123
- properties: {
124
- allow: { type: "array", items: { type: "string" } },
125
- deny: { type: "array", items: { type: "string" } },
126
- },
127
- },
128
- enabled: { type: "boolean" },
129
- allowFrom: { type: "array", items: { type: "string" } },
130
- systemPrompt: { type: "string" },
131
- groupSessionScope: { type: "string", enum: ["group", "group_sender"] },
132
- },
133
- },
134
- },
135
- accounts: {
136
- type: "object",
137
- additionalProperties: {
138
- type: "object",
139
- properties: {
140
- enabled: { type: "boolean" },
141
- name: { type: "string" },
142
- clientId: { type: "string" },
143
- clientSecret: { type: "string" },
144
- enableMediaUpload: { type: "boolean" },
145
- systemPrompt: { type: "string" },
146
- dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
147
- allowFrom: { type: "array", items: { type: "string" } },
148
- groupPolicy: { type: "string", enum: ["open", "allowlist", "disabled"] },
149
- groupAllowFrom: { type: "array", items: { type: "string" } },
150
- requireMention: { type: "boolean" },
151
- groupSessionScope: { type: "string", enum: ["group", "group_sender"] },
152
- separateSessionByConversation: { type: "boolean" },
153
- sharedMemoryAcrossConversations: { type: "boolean" },
154
- historyLimit: { type: "integer", minimum: 0 },
155
- textChunkLimit: { type: "integer", minimum: 1 },
156
- mediaMaxMb: { type: "number", minimum: 0 },
157
- typingIndicator: { type: "boolean" },
158
- asyncMode: { type: "boolean" },
159
- ackText: { type: "string" },
160
- endpoint: { type: "string" },
161
- debug: { type: "boolean" },
162
- tools: {
163
- type: "object",
164
- additionalProperties: false,
165
- properties: {
166
- docs: { type: "boolean" },
167
- media: { type: "boolean" },
168
- },
169
- },
170
- },
171
- },
172
- },
173
- },
174
- },
175
- },
83
+ configSchema: buildChannelConfigSchema(DingtalkConfigBaseSchema),
176
84
  config: {
177
85
  listAccountIds: (cfg) => listDingtalkAccountIds(cfg),
178
86
  resolveAccount: (cfg, accountId) => resolveDingtalkAccount({ cfg, accountId }),
@@ -19,32 +19,8 @@
19
19
  * ```
20
20
  */
21
21
 
22
- import axios, { type AxiosInstance, type CreateAxiosDefaults } from 'axios';
23
-
24
- /**
25
- * 获取代理配置
26
- *
27
- * 策略:
28
- * 1. 如果设置了 DINGTALK_FORCE_PROXY=true,使用环境变量中的代理
29
- * 2. 否则禁用代理(避免被系统 PAC 影响)
30
- */
31
- function getProxyConfig(): CreateAxiosDefaults['proxy'] {
32
- // 如果强制启用代理
33
- if (process.env.DINGTALK_FORCE_PROXY === 'true') {
34
- const proxyUrl =
35
- process.env.https_proxy ||
36
- process.env.HTTPS_PROXY ||
37
- process.env.http_proxy ||
38
- process.env.HTTP_PROXY;
39
-
40
- if (proxyUrl) {
41
- return proxyUrl as any;
42
- }
43
- }
44
-
45
- // 默认禁用代理
46
- return false;
47
- }
22
+ import axios, { type AxiosInstance } from 'axios';
23
+ import { getProxyConfig } from './proxy-config.ts';
48
24
 
49
25
  /**
50
26
  * 钉钉专用 HTTP 客户端
@@ -0,0 +1,35 @@
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
+ }