@zhin.js/adapter-dingtalk 1.0.80 → 1.1.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.
Files changed (65) hide show
  1. package/CHANGELOG.md +621 -0
  2. package/README.md +67 -333
  3. package/adapters/dingtalk.js +33 -0
  4. package/adapters/dingtalk.ts +38 -0
  5. package/agent/PERMITS.md +19 -0
  6. package/agent/tools/add_chat_members.ts +20 -0
  7. package/agent/tools/create_chat.ts +21 -0
  8. package/agent/tools/dept_info.ts +15 -0
  9. package/agent/tools/get_dept_users.ts +16 -0
  10. package/agent/tools/get_user.ts +15 -0
  11. package/agent/tools/list_departments.ts +16 -0
  12. package/agent/tools/send_work_notice.ts +18 -0
  13. package/agent/tools/update_chat.ts +25 -0
  14. package/commands/endpoint/add/[id].js +3 -0
  15. package/commands/endpoint/add/[id].ts +3 -0
  16. package/commands/endpoint/list.js +3 -0
  17. package/commands/endpoint/list.ts +3 -0
  18. package/commands/endpoint/remove/[id].js +3 -0
  19. package/commands/endpoint/remove/[id].ts +3 -0
  20. package/lib/client.d.ts +12 -0
  21. package/lib/client.js +2 -0
  22. package/lib/dingtalk-endpoint-commands.d.ts +1 -0
  23. package/lib/dingtalk-endpoint-commands.js +18 -0
  24. package/lib/dingtalk-runtime-state.d.ts +1 -0
  25. package/lib/dingtalk-runtime-state.js +6 -0
  26. package/lib/endpoint.d.ts +72 -0
  27. package/lib/endpoint.js +353 -0
  28. package/lib/index.d.ts +5 -15
  29. package/lib/index.js +5 -214
  30. package/lib/platform-permit.d.ts +14 -0
  31. package/lib/platform-permit.js +33 -0
  32. package/lib/protocol.d.ts +134 -0
  33. package/lib/protocol.js +265 -0
  34. package/lib/webhook.d.ts +13 -0
  35. package/lib/webhook.js +47 -0
  36. package/package.json +64 -18
  37. package/plugin.js +19 -0
  38. package/schema.json +92 -0
  39. package/src/client.ts +16 -0
  40. package/src/dingtalk-endpoint-commands.ts +19 -0
  41. package/src/dingtalk-runtime-state.ts +7 -0
  42. package/src/endpoint.ts +439 -0
  43. package/src/index.ts +44 -228
  44. package/src/platform-permit.ts +48 -0
  45. package/src/protocol.ts +385 -0
  46. package/src/webhook.ts +75 -0
  47. package/lib/adapter.d.ts +0 -16
  48. package/lib/adapter.d.ts.map +0 -1
  49. package/lib/adapter.js +0 -37
  50. package/lib/adapter.js.map +0 -1
  51. package/lib/bot.d.ts +0 -46
  52. package/lib/bot.d.ts.map +0 -1
  53. package/lib/bot.js +0 -539
  54. package/lib/bot.js.map +0 -1
  55. package/lib/index.d.ts.map +0 -1
  56. package/lib/index.js.map +0 -1
  57. package/lib/types.d.ts +0 -58
  58. package/lib/types.d.ts.map +0 -1
  59. package/lib/types.js +0 -5
  60. package/lib/types.js.map +0 -1
  61. package/plugin.yml +0 -3
  62. package/src/adapter.ts +0 -44
  63. package/src/bot.ts +0 -590
  64. package/src/types.ts +0 -56
  65. /package/{skills/dingtalk/SKILL.md → agent/skills/dingtalk.md} +0 -0
package/README.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # @zhin.js/adapter-dingtalk
2
2
 
3
- Zhin.js 钉钉适配器,支持企业内部机器人和钉钉开放平台机器人开发。
3
+ Zhin.js 钉钉适配器(Plugin Runtime),通过 Runtime Host HTTP Webhook 收发消息。
4
+
5
+ ## 功能
6
+
7
+ - Webhook 事件接收(`httpHostToken` POST + HMAC-SHA256 签名验证)
8
+ - Access Token 自动刷新
9
+ - Session Webhook 优先回复 / `/robot/send` 主动发送
10
+ - canonical `markdown` 段编码为钉钉原生 `msgtype: markdown`
11
+ - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
4
12
 
5
13
  ## 安装
6
14
 
@@ -8,357 +16,83 @@ Zhin.js 钉钉适配器,支持企业内部机器人和钉钉开放平台机器
8
16
  pnpm add @zhin.js/adapter-dingtalk
9
17
  ```
10
18
 
11
- ## 配置
12
-
13
- ### 基础配置
14
-
15
- ```typescript
16
- import { DingTalkBotConfig } from '@zhin.js/adapter-dingtalk';
17
-
18
- const config: DingTalkBotConfig = {
19
- context: 'dingtalk',
20
- name: 'my-dingtalk-bot',
21
- appKey: 'YOUR_APP_KEY', // 钉钉应用 AppKey
22
- appSecret: 'YOUR_APP_SECRET', // 钉钉应用 AppSecret
23
- webhookPath: '/dingtalk/webhook', // Webhook 路径
24
- robotCode: 'YOUR_ROBOT_CODE' // 机器人编码(可选)
25
- }
26
- ```
27
-
28
- ### 完整配置
29
-
30
- ```typescript
31
- const config: DingTalkBotConfig = {
32
- context: 'dingtalk',
33
- name: 'my-dingtalk-bot',
34
- appKey: 'YOUR_APP_KEY',
35
- appSecret: 'YOUR_APP_SECRET',
36
- webhookPath: '/dingtalk/webhook',
37
- robotCode: 'YOUR_ROBOT_CODE',
38
-
39
- // API 配置
40
- apiBaseUrl: 'https://oapi.dingtalk.com' // 自定义API地址(可选)
41
- }
42
- ```
43
-
44
- ### 配置参数说明
45
-
46
- - `appKey` (必需): 钉钉应用的 AppKey,在开发者后台获取
47
- - `appSecret` (必需): 钉钉应用的 AppSecret,在开发者后台获取
48
- - `webhookPath` (必需): Webhook 路径,如 `/dingtalk/webhook`
49
- - `robotCode` (可选): 机器人编码,用于发送消息时识别机器人身份
50
- - `apiBaseUrl` (可选): 自定义 API 基础地址,默认为 `https://oapi.dingtalk.com`
51
-
52
- ## 获取配置信息
53
-
54
- ### 创建钉钉企业内部应用
55
-
56
- 1. **访问钉钉开放平台**
57
- - 登录 [钉钉开放平台](https://open.dingtalk.com/)
58
- - 进入「应用开发」→「企业内部开发」
59
-
60
- 2. **创建应用**
61
- - 点击「创建应用」
62
- - 选择「企业内部开发」→「机器人」
63
- - 填写应用基本信息(应用名称、应用描述、应用图标等)
64
-
65
- 3. **获取应用凭证**
66
- - 在应用详情页面找到「开发管理」
67
- - 获取 **AppKey** 和 **AppSecret**
68
- - 记录这些信息用于配置
69
-
70
- ### 配置机器人
71
-
72
- 1. **配置机器人能力**
73
- - 在应用详情页面,进入「机器人配置」
74
- - 启用「消息接收」功能
75
- - 获取机器人的 **RobotCode**(机器人编码)
76
-
77
- 2. **配置消息接收地址**
78
- - 在「消息接收」设置中配置接收地址
79
- - 设置请求 URL:`https://yourdomain.com/dingtalk/webhook`
80
- - 钉钉会通过该地址推送消息事件
81
-
82
- 3. **配置权限**
83
- - 在「权限管理」中申请所需权限:
84
- - `通讯录只读权限` - 读取通讯录信息
85
- - `企业通讯录个人信息读权限` - 获取用户详细信息
86
- - `消息通知` - 发送工作通知
87
- - 其他业务需要的权限
88
-
89
- 4. **发布应用**
90
- - 完成配置后,发布应用
91
- - 在企业工作台添加应用
92
- - 员工可在钉钉中找到并使用该机器人
93
-
94
- ### 创建群机器人(Webhook 机器人)
95
-
96
- 如果只需要简单的群聊机器人功能:
97
-
98
- 1. **在群聊中添加机器人**
99
- - 进入钉钉群聊
100
- - 点击群设置 → 「智能群助手」
101
- - 选择「添加机器人」→「自定义机器人」
102
-
103
- 2. **配置 Webhook**
104
- - 输入机器人名称
105
- - 获取 Webhook 地址
106
- - 配置安全设置(加签或关键词)
107
-
108
- 3. **使用限制**
109
- - 群机器人只能在对应群聊中使用
110
- - 功能相对简单,适合轻量级场景
111
-
112
- ## 使用示例
113
-
114
- ### 配置文件(zhin.config.ts)
115
-
116
- ```typescript
117
- import { defineConfig } from 'zhin.js'
118
-
119
- export default defineConfig({
120
- bots: [
121
- {
122
- name: 'dingtalk-bot',
123
- context: 'dingtalk',
124
- appKey: 'dingxxxxxxxxxx',
125
- appSecret: 'your-app-secret',
126
- webhookPath: '/dingtalk/webhook',
127
- robotCode: 'dingxxxxxxxxxxxxxxxx'
128
- }
129
- ],
130
- plugins: [
131
- '@zhin.js/host-router',
132
- '@zhin.js/adapter-dingtalk',
133
- ],
134
- })
135
- ```
136
-
137
- ### 接收和发送消息
138
-
139
- ```typescript
140
- import { usePlugin, MessageCommand } from 'zhin.js'
141
-
142
- const { addCommand, logger } = usePlugin()
143
-
144
- // 定义命令
145
- addCommand(new MessageCommand('hello <name:text>')
146
- .action(async (message, result) => {
147
- logger.info(`收到来自 ${result.params.name} 的问候`)
148
- return `你好,${result.params.name}!欢迎使用钉钉机器人。`
149
- })
150
- )
151
-
152
- // 监听所有消息
153
- import { onMessage } from 'zhin.js'
154
-
155
- onMessage(async (message) => {
156
- logger.info(`收到消息:${message.$raw}`)
157
- logger.info(`发送者:${message.$sender.name}`)
158
- logger.info(`会话类型:${message.$channel.type}`)
159
- })
160
- ```
161
-
162
- ### 使用 @ 功能
163
-
164
- ```typescript
165
- addCommand(new MessageCommand('notify <...users:at>')
166
- .action(async (message, result) => {
167
- const users = result.params.users
168
- return [
169
- { type: 'text', data: { content: '通知以下用户:\n' } },
170
- ...users.map(user => ({
171
- type: 'at',
172
- data: { id: user.data.id, name: user.data.name }
173
- })),
174
- { type: 'text', data: { content: '\n请注意查看!' } }
175
- ]
176
- })
177
- )
178
- ```
179
-
180
- ### 发送富文本消息
181
-
182
- ```typescript
183
- addCommand(new MessageCommand('info')
184
- .action(async (message) => {
185
- return [
186
- {
187
- type: 'markdown',
188
- data: {
189
- title: '系统信息',
190
- content: `
191
- # 系统信息
192
-
193
- ## 基本信息
194
- - **服务器**: 运行正常
195
- - **版本**: v1.0.0
196
- - **状态**: ✅ 在线
197
-
198
- ## 功能列表
199
- 1. 消息接收与发送
200
- 2. 命令解析
201
- 3. @ 提醒功能
202
- `
203
- }
204
- }
205
- ]
206
- })
207
- )
208
- ```
209
-
210
- ## 消息类型支持
19
+ ## Plugin Runtime
211
20
 
212
- ### 接收消息类型
21
+ - `@zhin.js/adapter` — 约定式薄入口 `adapters/dingtalk.ts`(`defineAdapter`)
22
+ - 实现:`src/endpoint.ts`(生命周期/出站/OpenAPI)、`src/webhook.ts`(验签入站)、`src/protocol.ts`
23
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
24
+ - `@zhin.js/host-http` — `httpHostToken` 注册 Webhook 路由(**非** legacy host-router/Koa)
25
+ - `zhin.js` — `plugin.ts`(`definePlugin`)
26
+ - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
213
27
 
214
- - **文本消息** (`text`) - 普通文本和 @ 提醒
215
- - **图片消息** (`picture`) - 图片文件
216
- - ✅ **文件消息** (`file`) - 各类文件
217
- - ✅ **语音消息** (`audio`) - 音频文件
218
- - ✅ **视频消息** (`video`) - 视频文件
219
- - ✅ **富文本消息** (`richText`) - 富文本内容
220
- - ✅ **Markdown 消息** (`markdown`) - Markdown 格式
28
+ 入站:`gateway.receive({ conversation: ConversationRef, message: { conversation, id }, content: text, sender, metadata })`
29
+ 出站:`send({ conversation, payload })` sessionWebhook 或 `/robot/send`
221
30
 
222
- ### 发送消息类型
31
+ ## 前置条件
223
32
 
224
- - **文本消息** - 支持 @ 提醒
225
- - **图片消息** - 通过 URL 发送
226
- - **Markdown 消息** - 富文本展示
227
- - **链接消息** - 卡片式链接
228
- - ❌ **撤回消息** - 钉钉机器人不支持撤回
33
+ 1. [钉钉开放平台](https://open.dingtalk.com/) 创建企业内部应用 / 机器人
34
+ 2. 获取 **AppKey**、**AppSecret**(可选 RobotCode)
35
+ 3. 设置消息接收 URL `https://your-domain/dingtalk/webhook`
36
+ 4. Runtime Host(`http`)须已 listen,Webhook 才可达
229
37
 
230
- ## API 方法
38
+ 必填字段(`endpoints[i]`):`name`、`appKey`、`appSecret`、`webhookPath`、`robotCode`。
231
39
 
232
- ### 获取用户信息
40
+ ## 最小配置
233
41
 
234
- ```typescript
235
- const bot = app.adapters.get('dingtalk')?.bots.get('dingtalk-bot')
236
- if (bot) {
237
- const userInfo = await bot.getUserInfo('user-id')
238
- console.log(userInfo)
239
- }
42
+ ```yaml
43
+ # zhin.config.yml(Plugin Runtime)
44
+ plugins:
45
+ dingtalk:
46
+ apiBaseUrl: https://oapi.dingtalk.com # 可选,顶层共享
47
+ endpoints:
48
+ - name: my-dingtalk-bot
49
+ appKey: ${DINGTALK_APP_KEY}
50
+ appSecret: ${DINGTALK_APP_SECRET}
51
+ robotCode: ${DINGTALK_ROBOT_CODE}
52
+ webhookPath: /dingtalk/webhook # 可选,默认 /dingtalk/webhook
240
53
  ```
241
54
 
242
- ### 获取部门用户列表
55
+ 根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-dingtalk`(`instanceKey: dingtalk`)。
243
56
 
244
- ```typescript
245
- const users = await bot.getDepartmentUsers(1) // 部门 ID
246
- console.log(users)
247
- ```
248
-
249
- ### 发送工作通知
250
-
251
- ```typescript
252
- await bot.sendWorkNotice(
253
- ['user1', 'user2'], // 用户 ID 列表
254
- {
255
- msgtype: 'text',
256
- text: { content: '这是一条工作通知' }
257
- }
258
- )
259
- ```
260
-
261
- ## 安全说明
57
+ ## 环境变量
262
58
 
263
- ### 签名验证
59
+ | 变量 | 说明 |
60
+ |------|------|
61
+ | `DINGTALK_APP_KEY` | 应用 AppKey |
62
+ | `DINGTALK_APP_SECRET` | 应用 AppSecret |
63
+ | `DINGTALK_ROBOT_CODE` | RobotCode(主动发送 `/robot/send`) |
264
64
 
265
- 钉钉会在 Webhook 请求的 Header 中携带签名信息:
266
- - `timestamp`: 时间戳
267
- - `sign`: 签名值
65
+ ## 消息类型映射
268
66
 
269
- 适配器会自动验证签名,确保请求来自钉钉服务器。
67
+ | 钉钉类型 | 入站 content(文本摘要) | 出站 wire |
68
+ |----------|--------------------------|-----------|
69
+ | text | 原文 | text |
70
+ | picture | `[image]` | picture(需 `url`) |
71
+ | file | `[file: name]` | — |
72
+ | audio / video | `[audio]` / `[video]` | — |
73
+ | markdown | 原文或 `[markdown]` | markdown |
74
+ | link | — | link |
270
75
 
271
- ### Token 管理
76
+ ## Agent 工具
272
77
 
273
- 适配器会自动管理 access_token:
274
- - 首次连接时获取 token
275
- - Token 过期前 5 分钟自动刷新
276
- - 所有 API 请求自动携带有效 token
78
+ `agent/` 目录保留(get_user、部门、群聊、工作通知等)。工具声明 `adapter: 'dingtalk'` 后,通过惰性的 `context.$client` 自动取得当前操作的 `DingTalkClient`;无需把 Endpoint id 暴露给模型。
277
79
 
278
- ## 最佳实践
279
-
280
- ### 1. 配置环境变量
281
-
282
- 不要在代码中硬编码敏感信息:
283
-
284
- ```typescript
285
- export default defineConfig({
286
- bots: [{
287
- name: 'dingtalk-bot',
288
- context: 'dingtalk',
289
- appKey: process.env.DINGTALK_APP_KEY!,
290
- appSecret: process.env.DINGTALK_APP_SECRET!,
291
- webhookPath: '/dingtalk/webhook',
292
- robotCode: process.env.DINGTALK_ROBOT_CODE
293
- }]
294
- })
295
- ```
80
+ ## 平台权限(platform permit)
296
81
 
297
- ### 2. 错误处理
82
+ `plugin.ts` 在 generation setup 注册 `src/platform-permit.ts` checker,并在 dispose 注销;CapabilityIngress 与 ToolSystem 统一经 Core `canAccessTool()` 消费工具权限。
298
83
 
299
- 处理可能的错误情况:
84
+ ## 测试
300
85
 
301
- ```typescript
302
- onMessage(async (message) => {
303
- try {
304
- // 处理消息逻辑
305
- } catch (error) {
306
- logger.error('处理消息失败:', error)
307
- await message.$reply('抱歉,处理消息时出现错误')
308
- }
309
- })
310
- ```
311
-
312
- ### 3. 消息限流
313
-
314
- 注意钉钉的 API 调用频率限制,避免过于频繁的请求。
315
-
316
- ### 4. 日志记录
317
-
318
- 开启详细日志,便于排查问题:
319
-
320
- ```typescript
321
- export default defineConfig({
322
- log_level: 'debug', // 开发环境使用 debug
323
- // ... 其他配置
324
- })
86
+ ```bash
87
+ pnpm --filter @zhin.js/adapter-dingtalk build
88
+ pnpm --filter @zhin.js/adapter-dingtalk test
325
89
  ```
326
90
 
327
- ## 常见问题
328
-
329
- ### Q: Webhook 收不到消息?
330
-
331
- A: 检查以下几点:
332
- 1. Webhook URL 是否可以从公网访问
333
- 2. 钉钉后台的消息接收地址是否配置正确
334
- 3. 应用是否已经发布并添加到工作台
335
- 4. 检查服务器日志是否有错误信息
336
-
337
- ### Q: 发送消息失败?
338
-
339
- A: 可能的原因:
340
- 1. AppKey 或 AppSecret 配置错误
341
- 2. access_token 获取失败
342
- 3. 机器人编码(robotCode)配置错误
343
- 4. 网络问题或 API 限流
344
-
345
- ### Q: @ 功能不生效?
346
-
347
- A: 确保:
348
- 1. 使用正确的用户 ID 格式
349
- 2. @ 的用户在当前会话中
350
- 3. 消息格式正确包含 at 字段
351
-
352
- ## 相关链接
353
-
354
- - [钉钉开放平台](https://open.dingtalk.com/)
355
- - [钉钉机器人开发文档](https://open.dingtalk.com/document/robots/robot-overview)
356
- - [Zhin.js 官方文档](https://github.com/zhinjs/zhin)
357
-
358
- ## 许可证
359
-
360
- MIT License
361
-
362
- ## 贡献
91
+ ## 故障排查
363
92
 
364
- 欢迎提交 Issue Pull Request!
93
+ | 现象 | 排查 |
94
+ | --- | --- |
95
+ | 平台校验 URL 失败 | 确认公网 HTTPS 可达,HTTP Host 已监听,路径与 `webhookPath` 一致 |
96
+ | Webhook 返回 401/403 | 检查 `appSecret`、签名时间戳与服务器时钟 |
97
+ | 能收到但无法回复 | 检查 `robotCode`、应用权限与 session webhook 是否有效 |
98
+ | Endpoint 未出现 | 在日志查 Schema 或凭据错误,再到运行时能力核对 Endpoint |
@@ -0,0 +1,33 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ /**
3
+ * Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
4
+ */
5
+ import { defineAdapter } from 'zhin.js/adapter';
6
+ import { httpHostToken } from '@zhin.js/host-http';
7
+ import { DingTalkEndpoint } from "../lib/endpoint.js";
8
+ import { resolveDingTalkConfig, } from "../lib/protocol.js";
9
+ import { dingtalkRuntimeStateToken } from "../lib/dingtalk-runtime-state.js";
10
+ export { DingTalkEndpoint } from "../lib/endpoint.js";
11
+ export default defineAdapter({
12
+ capabilities: ['inbound', 'outbound'],
13
+ // 钉钉机器人媒体消息仅消费远程 URL;Markdown 走原生 msgtype;
14
+ // 无按钮交互面,交互段降级纯文本。
15
+ segments: {
16
+ outboundMedia: ['url'],
17
+ interactive: 'text',
18
+ markdown: 'native',
19
+ },
20
+ create(context) {
21
+ const config = resolveDingTalkConfig(context.config);
22
+ // 注册到插件运行时状态(dingtalk.endpoint list 的"运行中"数据源)
23
+ context.use(dingtalkRuntimeStateToken).endpoints.set(config.id, {
24
+ id: config.id,
25
+ mode: 'webhook',
26
+ });
27
+ return new DingTalkEndpoint({
28
+ id: context.id,
29
+ http: context.use(httpHostToken),
30
+ config,
31
+ });
32
+ },
33
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
3
+ */
4
+ import { defineAdapter } from 'zhin.js/adapter';
5
+ import { httpHostToken } from '@zhin.js/host-http';
6
+ import { DingTalkEndpoint } from '../src/endpoint.js';
7
+ import {
8
+ resolveDingTalkConfig,
9
+ type DingTalkAdapterConfig,
10
+ } from '../src/protocol.js';
11
+ import { dingtalkRuntimeStateToken } from '../src/dingtalk-runtime-state.js';
12
+
13
+ export { DingTalkEndpoint } from '../src/endpoint.js';
14
+ export type { DingTalkEndpointOptions, DingTalkFetch } from '../src/endpoint.js';
15
+
16
+ export default defineAdapter<DingTalkAdapterConfig>({
17
+ capabilities: ['inbound', 'outbound'],
18
+ // 钉钉机器人媒体消息仅消费远程 URL;Markdown 走原生 msgtype;
19
+ // 无按钮交互面,交互段降级纯文本。
20
+ segments: {
21
+ outboundMedia: ['url'],
22
+ interactive: 'text',
23
+ markdown: 'native',
24
+ },
25
+ create(context) {
26
+ const config = resolveDingTalkConfig(context.config);
27
+ // 注册到插件运行时状态(dingtalk.endpoint list 的"运行中"数据源)
28
+ context.use(dingtalkRuntimeStateToken).endpoints.set(config.id, {
29
+ id: config.id,
30
+ mode: 'webhook',
31
+ });
32
+ return new DingTalkEndpoint({
33
+ id: context.id,
34
+ http: context.use(httpHostToken),
35
+ config,
36
+ });
37
+ },
38
+ });
@@ -0,0 +1,19 @@
1
+ # 钉钉 DingTalk Platform Permits
2
+
3
+ ## 入站字段
4
+
5
+ | 字段 | 来源 |
6
+ |------|------|
7
+ | `$sender.role` | `isAdmin` → `admin`;`owner` 需业务侧创建群时指定 |
8
+ | `$sender.permissions` | `chat_owner` · `chat_admin` |
9
+
10
+ ## Permit 词汇表
11
+
12
+ | `platform(dingtalk,…)` | 含义 |
13
+ |------------------------|------|
14
+ | `chat_owner` | 群主(创建群等) |
15
+ | `chat_admin` | 群管理员 |
16
+
17
+ ## 工厂映射
18
+
19
+ `scene_admin` → `chat_admin` · `scene_owner` → `chat_owner`
@@ -0,0 +1,20 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+
5
+ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
6
+ description: '向钉钉群聊添加成员',
7
+ inputSchema: z.object({
8
+ chat_id: z.string().describe('群聊 ID'),
9
+ user_ids: z.string().describe('要添加的用户 ID 列表,逗号分隔'),
10
+ }),
11
+ adapter: 'dingtalk',
12
+ tags: ['dingtalk'],
13
+ permissions: [platformPermit('chat_admin')],
14
+ async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
15
+ const endpoint = context.$client;
16
+ const success = await endpoint.updateChat(chat_id, { add_useridlist: user_ids.split(',') });
17
+ return { success, message: success ? '成员添加成功' : '添加失败' };
18
+ },
19
+ });
20
+
@@ -0,0 +1,21 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ import { platformPermit } from '../../src/platform-permit.js';
4
+
5
+ export default defineAgentTool<{ name: string; owner: string; members: string }>({
6
+ description: '创建钉钉群聊',
7
+ inputSchema: z.object({
8
+ name: z.string().describe('群名'),
9
+ owner: z.string().describe('群主用户 ID'),
10
+ members: z.string().describe('成员用户 ID 列表,逗号分隔'),
11
+ }),
12
+ adapter: 'dingtalk',
13
+ tags: ['dingtalk'],
14
+ permissions: [platformPermit('chat_owner')],
15
+ async execute({ name, owner, members }: { name: string; owner: string; members: string }, context) {
16
+ const endpoint = context.$client;
17
+ const chatId = await endpoint.createChat(name, owner, members.split(','));
18
+ return { success: !!chatId, chat_id: chatId, message: chatId ? `群聊创建成功: ${chatId}` : '创建失败' };
19
+ },
20
+ });
21
+
@@ -0,0 +1,15 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ dept_id: string }>({
4
+ description: '获取钉钉部门详细信息',
5
+ inputSchema: z.object({
6
+ dept_id: z.string().describe('部门 ID'),
7
+ }),
8
+ adapter: 'dingtalk',
9
+ tags: ['dingtalk'],
10
+ async execute({ dept_id }: { dept_id: string }, context) {
11
+ const endpoint = context.$client;
12
+ return await endpoint.getDepartmentInfo(Number(dept_id));
13
+ },
14
+ });
15
+
@@ -0,0 +1,16 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ dept_id: string }>({
4
+ description: '获取钉钉部门用户列表',
5
+ inputSchema: z.object({
6
+ dept_id: z.string().describe('部门 ID'),
7
+ }),
8
+ adapter: 'dingtalk',
9
+ tags: ['dingtalk'],
10
+ async execute({ dept_id }: { dept_id: string }, context) {
11
+ const endpoint = context.$client;
12
+ const users = await endpoint.getDepartmentUsers(Number(dept_id));
13
+ return { users, count: users.length };
14
+ },
15
+ });
16
+
@@ -0,0 +1,15 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ user_id: string }>({
4
+ description: '获取钉钉用户信息',
5
+ inputSchema: z.object({
6
+ user_id: z.string().describe('用户 ID'),
7
+ }),
8
+ adapter: 'dingtalk',
9
+ tags: ['dingtalk'],
10
+ async execute({ user_id }: { user_id: string }, context) {
11
+ const endpoint = context.$client;
12
+ return await endpoint.getUserInfo(user_id);
13
+ },
14
+ });
15
+
@@ -0,0 +1,16 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ dept_id?: string }>({
4
+ description: '获取钉钉部门列表',
5
+ inputSchema: z.object({
6
+ dept_id: z.string().optional().describe('父部门 ID,默认 1(根部门)'),
7
+ }),
8
+ adapter: 'dingtalk',
9
+ tags: ['dingtalk'],
10
+ async execute({ dept_id }: { dept_id?: string }, context) {
11
+ const endpoint = context.$client;
12
+ const departments = await endpoint.getDepartmentList(Number(dept_id || '1'));
13
+ return { departments, count: departments.length };
14
+ },
15
+ });
16
+
@@ -0,0 +1,18 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ user_ids: string; content: string }>({
4
+ description: '向指定用户发送钉钉工作通知',
5
+ inputSchema: z.object({
6
+ user_ids: z.string().describe('用户 ID 列表,逗号分隔'),
7
+ content: z.string().describe('通知内容'),
8
+ }),
9
+ adapter: 'dingtalk',
10
+ tags: ['dingtalk'],
11
+ async execute({ user_ids, content }: { user_ids: string; content: string }, context) {
12
+ const endpoint = context.$client;
13
+ const msgContent = { msgtype: 'text', text: { content } };
14
+ const success = await endpoint.sendWorkNotice(user_ids.split(','), msgContent);
15
+ return { success, message: success ? '工作通知已发送' : '发送失败' };
16
+ },
17
+ });
18
+
@@ -0,0 +1,25 @@
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
+ import { z } from 'zod';
3
+ export default defineAgentTool<{ chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }>({
4
+ description: '更新钉钉群聊设置(改名、换群主、增减成员)',
5
+ inputSchema: z.object({
6
+ chat_id: z.string().describe('群聊 ID'),
7
+ name: z.string().optional().describe('新群名(可选)'),
8
+ owner: z.string().optional().describe('新群主 userId(可选)'),
9
+ add_members: z.string().optional().describe('要添加的成员 userId,逗号分隔(可选)'),
10
+ remove_members: z.string().optional().describe('要移除的成员 userId,逗号分隔(可选)'),
11
+ }),
12
+ adapter: 'dingtalk',
13
+ tags: ['dingtalk'],
14
+ async execute({ chat_id, name, owner, add_members, remove_members }: { chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }, context) {
15
+ const endpoint = context.$client;
16
+ const options: Record<string, unknown> = {};
17
+ if (name) options.name = name;
18
+ if (owner) options.owner = owner;
19
+ if (add_members) options.add_useridlist = add_members.split(',').map((s: string) => s.trim());
20
+ if (remove_members) options.del_useridlist = remove_members.split(',').map((s: string) => s.trim());
21
+ await endpoint.updateChat(chat_id, options);
22
+ return { success: true, message: '群聊设置已更新' };
23
+ },
24
+ });
25
+
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { dingtalkEndpointCommands } from "../../../lib/dingtalk-endpoint-commands.js";
3
+ export default dingtalkEndpointCommands.add;