@dingtalk-real-ai/dingtalk-connector 0.8.9 → 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.
- package/CHANGELOG.md +13 -0
- package/openclaw.plugin.json +277 -3
- package/package.json +3 -3
- package/src/channel.ts +5 -97
- package/src/core/connection.ts +1 -1
- package/src/gateway-methods.ts +28 -68
- package/src/utils/http-client.ts +2 -26
- package/src/utils/proxy-config.ts +35 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ 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.10] - 2026-03-31
|
|
9
|
+
|
|
10
|
+
### 修复 / Fixes
|
|
11
|
+
- 🐛 **Gateway Methods 配置访问失败** ([#397](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/397)) - 修复 SDK 升级后 `context.deps.config` 为 `undefined`,所有 Gateway RPC 方法调用失败。改用 SDK 的 `loadConfig()` 函数获取配置
|
|
12
|
+
**Gateway Methods config access failure** - Fixed `context.deps.config` being `undefined` after SDK upgrade, now uses `loadConfig()` from `openclaw/plugin-sdk/config-runtime`
|
|
13
|
+
|
|
14
|
+
- 🐛 **锁定 axios 版本避免兼容性问题** ([#396](https://github.com/DingTalk-Real-AI/dingtalk-openclaw-connector/issues/396)) - 将 `axios` 从 `^1.6.0` 锁定为 `1.6.0`,避免自动升级引入不兼容变更
|
|
15
|
+
**Pin axios version** - Pinned `axios` from `^1.6.0` to `1.6.0` to prevent incompatible upgrades
|
|
16
|
+
|
|
17
|
+
### 改进 / Improvements
|
|
18
|
+
- ✅ **connection.ts 动态 import 优化** - 将 `createLoggerFromConfig` 改为动态 import,避免潜在循环依赖
|
|
19
|
+
**connection.ts dynamic import** - Changed `createLoggerFromConfig` to dynamic import to avoid potential circular dependencies
|
|
20
|
+
|
|
8
21
|
## [0.8.9] - 2026-03-31
|
|
9
22
|
|
|
10
23
|
### 新增 / Added
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dingtalk-connector",
|
|
3
3
|
"name": "DingTalk Channel",
|
|
4
|
-
"version": "0.8.
|
|
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":
|
|
14
|
-
|
|
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.
|
|
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",
|
|
@@ -44,14 +44,14 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"axios": "
|
|
47
|
+
"axios": "1.6.0",
|
|
48
48
|
"dingtalk-stream": "2.1.4",
|
|
49
49
|
"fluent-ffmpeg": "^2.1.3",
|
|
50
50
|
"form-data": "^4.0.0",
|
|
51
51
|
"mammoth": "^1.8.0",
|
|
52
52
|
"pako": "^2.1.0",
|
|
53
53
|
"pdf-parse": "^1.1.1",
|
|
54
|
-
"zod": "^3.
|
|
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 }),
|
package/src/core/connection.ts
CHANGED
|
@@ -18,7 +18,6 @@ import type { ResolvedDingtalkAccount } from "../types/index.ts";
|
|
|
18
18
|
import {
|
|
19
19
|
checkAndMarkDingtalkMessage,
|
|
20
20
|
} from "../utils/utils-legacy.ts";
|
|
21
|
-
import { createLoggerFromConfig } from "../utils/logger.ts";
|
|
22
21
|
|
|
23
22
|
// ============ 类型定义 ============
|
|
24
23
|
|
|
@@ -78,6 +77,7 @@ export async function monitorSingleAccount(
|
|
|
78
77
|
const log = runtime?.log;
|
|
79
78
|
|
|
80
79
|
// 创建 debug logger(仅在 debug 模式下输出 info/debug 日志)
|
|
80
|
+
const { createLoggerFromConfig } = await import('../utils/logger');
|
|
81
81
|
const logger = createLoggerFromConfig(account.config, `DingTalk:${accountId}`);
|
|
82
82
|
|
|
83
83
|
// 验证凭据是否存在
|
package/src/gateway-methods.ts
CHANGED
|
@@ -31,11 +31,11 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
33
|
api.registerGatewayMethod('dingtalk-connector.sendToUser', async ({ context, params, respond }) => {
|
|
34
|
-
const
|
|
34
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
35
|
+
const cfg = loadConfig();
|
|
35
36
|
try {
|
|
36
37
|
const { userId, userIds, content, msgType, title, useAICard, fallbackToNormal, accountId } = params || {};
|
|
37
38
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
38
|
-
|
|
39
39
|
if (!account.config?.clientId) {
|
|
40
40
|
return respond(false, { error: 'DingTalk not configured' });
|
|
41
41
|
}
|
|
@@ -82,11 +82,11 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
82
82
|
* ```
|
|
83
83
|
*/
|
|
84
84
|
api.registerGatewayMethod('dingtalk-connector.sendToGroup', async ({ context, params, respond }) => {
|
|
85
|
-
const
|
|
85
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
86
|
+
const cfg = loadConfig();
|
|
86
87
|
try {
|
|
87
88
|
const { openConversationId, content, msgType, title, useAICard, fallbackToNormal, accountId } = params || {};
|
|
88
89
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
89
|
-
|
|
90
90
|
if (!account.config?.clientId) {
|
|
91
91
|
return respond(false, { error: 'DingTalk not configured' });
|
|
92
92
|
}
|
|
@@ -110,35 +110,18 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
110
110
|
respond(result.ok, result);
|
|
111
111
|
} catch (err: any) {
|
|
112
112
|
log?.error?.(`[Gateway][sendToGroup] 错误: ${err.message}`);
|
|
113
|
+
console.error(err);
|
|
113
114
|
respond(false, { error: err.message });
|
|
114
115
|
}
|
|
115
116
|
});
|
|
116
117
|
|
|
117
|
-
/**
|
|
118
|
-
* 智能发送消息(自动识别目标类型)
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* ```typescript
|
|
122
|
-
* // 发送给用户
|
|
123
|
-
* await gateway.call('dingtalk-connector.send', {
|
|
124
|
-
* target: 'user:user123',
|
|
125
|
-
* content: '你好!'
|
|
126
|
-
* });
|
|
127
|
-
*
|
|
128
|
-
* // 发送到群
|
|
129
|
-
* await gateway.call('dingtalk-connector.send', {
|
|
130
|
-
* target: 'group:cid123',
|
|
131
|
-
* content: '大家好!'
|
|
132
|
-
* });
|
|
133
|
-
* ```
|
|
134
|
-
*/
|
|
135
118
|
api.registerGatewayMethod('dingtalk-connector.send', async ({ context, params, respond }) => {
|
|
136
|
-
const
|
|
119
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
120
|
+
const cfg = loadConfig();
|
|
137
121
|
try {
|
|
138
122
|
const { target, content, message, msgType, title, useAICard, fallbackToNormal, accountId } = params || {};
|
|
139
123
|
const actualContent = content || message;
|
|
140
124
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
141
|
-
|
|
142
125
|
log?.info?.(`[Gateway][send] 收到请求: target=${target}, contentLen=${actualContent?.length}`);
|
|
143
126
|
|
|
144
127
|
if (!account.config?.clientId) {
|
|
@@ -182,20 +165,9 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
182
165
|
|
|
183
166
|
// ============ 文档操作类 ============
|
|
184
167
|
|
|
185
|
-
/**
|
|
186
|
-
* 读取钉钉文档
|
|
187
|
-
*
|
|
188
|
-
* @example
|
|
189
|
-
* ```typescript
|
|
190
|
-
* const result = await gateway.call('dingtalk-connector.docs.read', {
|
|
191
|
-
* docId: 'doc123',
|
|
192
|
-
* operatorId: 'user_union_id'
|
|
193
|
-
* });
|
|
194
|
-
* console.log(result.content);
|
|
195
|
-
* ```
|
|
196
|
-
*/
|
|
197
168
|
api.registerGatewayMethod('dingtalk-connector.docs.read', async ({ context, params, respond }) => {
|
|
198
|
-
const
|
|
169
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
170
|
+
const cfg = loadConfig();
|
|
199
171
|
try {
|
|
200
172
|
const { docId, operatorId: rawOperatorId, accountId } = params || {};
|
|
201
173
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
@@ -247,7 +219,8 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
247
219
|
* ```
|
|
248
220
|
*/
|
|
249
221
|
api.registerGatewayMethod('dingtalk-connector.docs.create', async ({ context, params, respond }) => {
|
|
250
|
-
const
|
|
222
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
223
|
+
const cfg = loadConfig();
|
|
251
224
|
try {
|
|
252
225
|
const { spaceId, title, content, accountId } = params || {};
|
|
253
226
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
@@ -286,7 +259,8 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
286
259
|
* ```
|
|
287
260
|
*/
|
|
288
261
|
api.registerGatewayMethod('dingtalk-connector.docs.append', async ({ context, params, respond }) => {
|
|
289
|
-
const
|
|
262
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
263
|
+
const cfg = loadConfig();
|
|
290
264
|
try {
|
|
291
265
|
const { docId, content, accountId } = params || {};
|
|
292
266
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
@@ -322,7 +296,8 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
322
296
|
* ```
|
|
323
297
|
*/
|
|
324
298
|
api.registerGatewayMethod('dingtalk-connector.docs.search', async ({ context, params, respond }) => {
|
|
325
|
-
const
|
|
299
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
300
|
+
const cfg = loadConfig();
|
|
326
301
|
try {
|
|
327
302
|
const { keyword, spaceId, accountId } = params || {};
|
|
328
303
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
@@ -358,7 +333,8 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
358
333
|
* ```
|
|
359
334
|
*/
|
|
360
335
|
api.registerGatewayMethod('dingtalk-connector.docs.list', async ({ context, params, respond }) => {
|
|
361
|
-
const
|
|
336
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
337
|
+
const cfg = loadConfig();
|
|
362
338
|
try {
|
|
363
339
|
const { spaceId, parentId, accountId } = params || {};
|
|
364
340
|
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
@@ -383,26 +359,20 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
383
359
|
|
|
384
360
|
// ============ 状态检查类 ============
|
|
385
361
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
* @example
|
|
390
|
-
* ```typescript
|
|
391
|
-
* const result = await gateway.call('dingtalk-connector.status');
|
|
392
|
-
* console.log('配置状态:', result);
|
|
393
|
-
* ```
|
|
394
|
-
*/
|
|
395
|
-
api.registerGatewayMethod('dingtalk-connector.status', async ({ context, respond }) => {
|
|
396
|
-
const cfg = context.deps.getConfig();
|
|
362
|
+
api.registerGatewayMethod('dingtalk-connector.status', async ({ context, params, respond }) => {
|
|
363
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
364
|
+
const cfg = loadConfig();
|
|
397
365
|
try {
|
|
398
|
-
const
|
|
399
|
-
const
|
|
366
|
+
const accountId = (params as any)?.accountId as string | undefined;
|
|
367
|
+
const account = resolveDingtalkAccount({ cfg, accountId });
|
|
368
|
+
const hasClientId = !!account.config?.clientId;
|
|
369
|
+
const hasClientSecret = !!account.config?.clientSecret;
|
|
400
370
|
|
|
401
371
|
respond(true, {
|
|
402
|
-
configured,
|
|
372
|
+
configured: hasClientId && hasClientSecret,
|
|
403
373
|
enabled: account.enabled,
|
|
404
374
|
accountId: account.accountId,
|
|
405
|
-
clientId: account.config
|
|
375
|
+
clientId: hasClientId ? String(account.config!.clientId).substring(0, 8) + '...' : undefined,
|
|
406
376
|
});
|
|
407
377
|
} catch (err: any) {
|
|
408
378
|
log?.error?.(`[Gateway][status] 错误: ${err.message}`);
|
|
@@ -410,19 +380,9 @@ export function registerGatewayMethods(api: OpenClawPluginApi) {
|
|
|
410
380
|
}
|
|
411
381
|
});
|
|
412
382
|
|
|
413
|
-
/**
|
|
414
|
-
* 探测钉钉连接
|
|
415
|
-
*
|
|
416
|
-
* @example
|
|
417
|
-
* ```typescript
|
|
418
|
-
* const result = await gateway.call('dingtalk-connector.probe');
|
|
419
|
-
* if (result.ok) {
|
|
420
|
-
* console.log('连接正常');
|
|
421
|
-
* }
|
|
422
|
-
* ```
|
|
423
|
-
*/
|
|
424
383
|
api.registerGatewayMethod('dingtalk-connector.probe', async ({ context, respond }) => {
|
|
425
|
-
const
|
|
384
|
+
const { loadConfig } = await import('openclaw/plugin-sdk/config-runtime');
|
|
385
|
+
const cfg = loadConfig();
|
|
426
386
|
try {
|
|
427
387
|
const account = resolveDingtalkAccount({ cfg });
|
|
428
388
|
|
package/src/utils/http-client.ts
CHANGED
|
@@ -19,32 +19,8 @@
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import axios, { type AxiosInstance
|
|
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
|
+
}
|