@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.
- package/CHANGELOG.md +621 -0
- package/README.md +67 -333
- package/adapters/dingtalk.js +33 -0
- package/adapters/dingtalk.ts +38 -0
- package/agent/PERMITS.md +19 -0
- package/agent/tools/add_chat_members.ts +20 -0
- package/agent/tools/create_chat.ts +21 -0
- package/agent/tools/dept_info.ts +15 -0
- package/agent/tools/get_dept_users.ts +16 -0
- package/agent/tools/get_user.ts +15 -0
- package/agent/tools/list_departments.ts +16 -0
- package/agent/tools/send_work_notice.ts +18 -0
- package/agent/tools/update_chat.ts +25 -0
- package/commands/endpoint/add/[id].js +3 -0
- package/commands/endpoint/add/[id].ts +3 -0
- package/commands/endpoint/list.js +3 -0
- package/commands/endpoint/list.ts +3 -0
- package/commands/endpoint/remove/[id].js +3 -0
- package/commands/endpoint/remove/[id].ts +3 -0
- package/lib/client.d.ts +12 -0
- package/lib/client.js +2 -0
- package/lib/dingtalk-endpoint-commands.d.ts +1 -0
- package/lib/dingtalk-endpoint-commands.js +18 -0
- package/lib/dingtalk-runtime-state.d.ts +1 -0
- package/lib/dingtalk-runtime-state.js +6 -0
- package/lib/endpoint.d.ts +72 -0
- package/lib/endpoint.js +353 -0
- package/lib/index.d.ts +5 -15
- package/lib/index.js +5 -214
- package/lib/platform-permit.d.ts +14 -0
- package/lib/platform-permit.js +33 -0
- package/lib/protocol.d.ts +134 -0
- package/lib/protocol.js +265 -0
- package/lib/webhook.d.ts +13 -0
- package/lib/webhook.js +47 -0
- package/package.json +64 -18
- package/plugin.js +19 -0
- package/schema.json +92 -0
- package/src/client.ts +16 -0
- package/src/dingtalk-endpoint-commands.ts +19 -0
- package/src/dingtalk-runtime-state.ts +7 -0
- package/src/endpoint.ts +439 -0
- package/src/index.ts +44 -228
- package/src/platform-permit.ts +48 -0
- package/src/protocol.ts +385 -0
- package/src/webhook.ts +75 -0
- package/lib/adapter.d.ts +0 -16
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -37
- package/lib/adapter.js.map +0 -1
- package/lib/bot.d.ts +0 -46
- package/lib/bot.d.ts.map +0 -1
- package/lib/bot.js +0 -539
- package/lib/bot.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/types.d.ts +0 -58
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -5
- package/lib/types.js.map +0 -1
- package/plugin.yml +0 -3
- package/src/adapter.ts +0 -44
- package/src/bot.ts +0 -590
- package/src/types.ts +0 -56
- /package/{skills/dingtalk/SKILL.md → agent/skills/dingtalk.md} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,228 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const disposers: (() => void)[] = groupTools.map(t => toolService.addTool(t, plugin.name));
|
|
46
|
-
|
|
47
|
-
disposers.push(toolService.addTool({
|
|
48
|
-
name: 'dingtalk_get_user',
|
|
49
|
-
description: '获取钉钉用户信息',
|
|
50
|
-
parameters: {
|
|
51
|
-
type: 'object',
|
|
52
|
-
properties: {
|
|
53
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
54
|
-
user_id: { type: 'string', description: '用户 ID' },
|
|
55
|
-
},
|
|
56
|
-
required: ['bot', 'user_id'],
|
|
57
|
-
},
|
|
58
|
-
platforms: ['dingtalk'],
|
|
59
|
-
tags: ['dingtalk'],
|
|
60
|
-
execute: async (args: Record<string, any>) => {
|
|
61
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
62
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
63
|
-
return await bot.getUserInfo(args.user_id);
|
|
64
|
-
},
|
|
65
|
-
}, plugin.name));
|
|
66
|
-
|
|
67
|
-
disposers.push(toolService.addTool({
|
|
68
|
-
name: 'dingtalk_get_dept_users',
|
|
69
|
-
description: '获取钉钉部门用户列表',
|
|
70
|
-
parameters: {
|
|
71
|
-
type: 'object',
|
|
72
|
-
properties: {
|
|
73
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
74
|
-
dept_id: { type: 'string', description: '部门 ID' },
|
|
75
|
-
},
|
|
76
|
-
required: ['bot', 'dept_id'],
|
|
77
|
-
},
|
|
78
|
-
platforms: ['dingtalk'],
|
|
79
|
-
tags: ['dingtalk'],
|
|
80
|
-
execute: async (args: Record<string, any>) => {
|
|
81
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
82
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
83
|
-
const users = await bot.getDepartmentUsers(args.dept_id);
|
|
84
|
-
return { users, count: users.length };
|
|
85
|
-
},
|
|
86
|
-
}, plugin.name));
|
|
87
|
-
|
|
88
|
-
disposers.push(toolService.addTool({
|
|
89
|
-
name: 'dingtalk_list_departments',
|
|
90
|
-
description: '获取钉钉部门列表',
|
|
91
|
-
parameters: {
|
|
92
|
-
type: 'object',
|
|
93
|
-
properties: {
|
|
94
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
95
|
-
dept_id: { type: 'string', description: '父部门 ID,默认 1(根部门)' },
|
|
96
|
-
},
|
|
97
|
-
required: ['bot'],
|
|
98
|
-
},
|
|
99
|
-
platforms: ['dingtalk'],
|
|
100
|
-
tags: ['dingtalk'],
|
|
101
|
-
execute: async (args: Record<string, any>) => {
|
|
102
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
103
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
104
|
-
const departments = await bot.getDepartmentList(args.dept_id || '1');
|
|
105
|
-
return { departments, count: departments.length };
|
|
106
|
-
},
|
|
107
|
-
}, plugin.name));
|
|
108
|
-
|
|
109
|
-
disposers.push(toolService.addTool({
|
|
110
|
-
name: 'dingtalk_send_work_notice',
|
|
111
|
-
description: '向指定用户发送钉钉工作通知',
|
|
112
|
-
parameters: {
|
|
113
|
-
type: 'object',
|
|
114
|
-
properties: {
|
|
115
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
116
|
-
user_ids: { type: 'string', description: '用户 ID 列表,逗号分隔' },
|
|
117
|
-
content: { type: 'string', description: '通知内容' },
|
|
118
|
-
},
|
|
119
|
-
required: ['bot', 'user_ids', 'content'],
|
|
120
|
-
},
|
|
121
|
-
platforms: ['dingtalk'],
|
|
122
|
-
tags: ['dingtalk'],
|
|
123
|
-
execute: async (args: Record<string, any>) => {
|
|
124
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
125
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
126
|
-
const msgContent = { msgtype: 'text', text: { content: args.content } };
|
|
127
|
-
const success = await bot.sendWorkNotice(args.user_ids.split(','), msgContent);
|
|
128
|
-
return { success, message: success ? '工作通知已发送' : '发送失败' };
|
|
129
|
-
},
|
|
130
|
-
}, plugin.name));
|
|
131
|
-
|
|
132
|
-
disposers.push(toolService.addTool({
|
|
133
|
-
name: 'dingtalk_create_chat',
|
|
134
|
-
description: '创建钉钉群聊',
|
|
135
|
-
parameters: {
|
|
136
|
-
type: 'object',
|
|
137
|
-
properties: {
|
|
138
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
139
|
-
name: { type: 'string', description: '群名' },
|
|
140
|
-
owner: { type: 'string', description: '群主用户 ID' },
|
|
141
|
-
members: { type: 'string', description: '成员用户 ID 列表,逗号分隔' },
|
|
142
|
-
},
|
|
143
|
-
required: ['bot', 'name', 'owner', 'members'],
|
|
144
|
-
},
|
|
145
|
-
platforms: ['dingtalk'],
|
|
146
|
-
tags: ['dingtalk'],
|
|
147
|
-
execute: async (args: Record<string, any>) => {
|
|
148
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
149
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
150
|
-
const chatId = await bot.createChat(args.name, args.owner, args.members.split(','));
|
|
151
|
-
return { success: !!chatId, chat_id: chatId, message: chatId ? `群聊创建成功: ${chatId}` : '创建失败' };
|
|
152
|
-
},
|
|
153
|
-
}, plugin.name));
|
|
154
|
-
|
|
155
|
-
disposers.push(toolService.addTool({
|
|
156
|
-
name: 'dingtalk_add_chat_members',
|
|
157
|
-
description: '向钉钉群聊添加成员',
|
|
158
|
-
parameters: {
|
|
159
|
-
type: 'object',
|
|
160
|
-
properties: {
|
|
161
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
162
|
-
chat_id: { type: 'string', description: '群聊 ID' },
|
|
163
|
-
user_ids: { type: 'string', description: '要添加的用户 ID 列表,逗号分隔' },
|
|
164
|
-
},
|
|
165
|
-
required: ['bot', 'chat_id', 'user_ids'],
|
|
166
|
-
},
|
|
167
|
-
platforms: ['dingtalk'],
|
|
168
|
-
tags: ['dingtalk'],
|
|
169
|
-
execute: async (args: Record<string, any>) => {
|
|
170
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
171
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
172
|
-
const success = await bot.updateChat(args.chat_id, { add_useridlist: args.user_ids.split(',') });
|
|
173
|
-
return { success, message: success ? '成员添加成功' : '添加失败' };
|
|
174
|
-
},
|
|
175
|
-
}, plugin.name));
|
|
176
|
-
|
|
177
|
-
disposers.push(toolService.addTool({
|
|
178
|
-
name: 'dingtalk_dept_info',
|
|
179
|
-
description: '获取钉钉部门详细信息',
|
|
180
|
-
parameters: {
|
|
181
|
-
type: 'object',
|
|
182
|
-
properties: {
|
|
183
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
184
|
-
dept_id: { type: 'string', description: '部门 ID' },
|
|
185
|
-
},
|
|
186
|
-
required: ['bot', 'dept_id'],
|
|
187
|
-
},
|
|
188
|
-
platforms: ['dingtalk'],
|
|
189
|
-
tags: ['dingtalk'],
|
|
190
|
-
execute: async (args: Record<string, any>) => {
|
|
191
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
192
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
193
|
-
return await bot.getDepartmentInfo(Number(args.dept_id));
|
|
194
|
-
},
|
|
195
|
-
}, plugin.name));
|
|
196
|
-
|
|
197
|
-
disposers.push(toolService.addTool({
|
|
198
|
-
name: 'dingtalk_update_chat',
|
|
199
|
-
description: '更新钉钉群聊设置(改名、换群主、增减成员)',
|
|
200
|
-
parameters: {
|
|
201
|
-
type: 'object',
|
|
202
|
-
properties: {
|
|
203
|
-
bot: { type: 'string', description: 'Bot 名称' },
|
|
204
|
-
chat_id: { type: 'string', description: '群聊 ID' },
|
|
205
|
-
name: { type: 'string', description: '新群名(可选)' },
|
|
206
|
-
owner: { type: 'string', description: '新群主 userId(可选)' },
|
|
207
|
-
add_members: { type: 'string', description: '要添加的成员 userId,逗号分隔(可选)' },
|
|
208
|
-
remove_members: { type: 'string', description: '要移除的成员 userId,逗号分隔(可选)' },
|
|
209
|
-
},
|
|
210
|
-
required: ['bot', 'chat_id'],
|
|
211
|
-
},
|
|
212
|
-
platforms: ['dingtalk'],
|
|
213
|
-
tags: ['dingtalk'],
|
|
214
|
-
execute: async (args: Record<string, any>) => {
|
|
215
|
-
const bot = dingtalk.bots.get(args.bot);
|
|
216
|
-
if (!bot) throw new Error(`Bot ${args.bot} 不存在`);
|
|
217
|
-
const options: any = {};
|
|
218
|
-
if (args.name) options.name = args.name;
|
|
219
|
-
if (args.owner) options.owner = args.owner;
|
|
220
|
-
if (args.add_members) options.add_useridlist = args.add_members.split(',').map((s: string) => s.trim());
|
|
221
|
-
if (args.remove_members) options.del_useridlist = args.remove_members.split(',').map((s: string) => s.trim());
|
|
222
|
-
await bot.updateChat(args.chat_id, options);
|
|
223
|
-
return { success: true, message: '群聊设置已更新' };
|
|
224
|
-
},
|
|
225
|
-
}, plugin.name));
|
|
226
|
-
|
|
227
|
-
return () => disposers.forEach(d => d());
|
|
228
|
-
});
|
|
1
|
+
export {
|
|
2
|
+
dingtalkInboundConversation,
|
|
3
|
+
formatInboundContent,
|
|
4
|
+
formatOutboundBody,
|
|
5
|
+
generateMessageId,
|
|
6
|
+
headerValue,
|
|
7
|
+
normalizeWebhookPath,
|
|
8
|
+
readTextBody,
|
|
9
|
+
resolveChatType,
|
|
10
|
+
resolveDingTalkConfig,
|
|
11
|
+
resolveSender,
|
|
12
|
+
verifySignature,
|
|
13
|
+
type AccessToken,
|
|
14
|
+
type DingTalkAdapterConfig,
|
|
15
|
+
type DingTalkApiResponse,
|
|
16
|
+
type DingTalkEvent,
|
|
17
|
+
type DingTalkMessage,
|
|
18
|
+
type DingTalkSendBody,
|
|
19
|
+
type DingTalkWireSegment,
|
|
20
|
+
type ResolvedDingTalkConfig,
|
|
21
|
+
} from './protocol.js';
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
DingTalkClient,
|
|
25
|
+
DingTalkEndpoint,
|
|
26
|
+
type DingTalkClientApi,
|
|
27
|
+
type DingTalkEndpointOptions,
|
|
28
|
+
type DingTalkFetch,
|
|
29
|
+
} from './endpoint.js';
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
registerDingTalkWebhookRoutes,
|
|
33
|
+
handleDingTalkWebhookRequest,
|
|
34
|
+
type DingTalkWebhookHandler,
|
|
35
|
+
} from './webhook.js';
|
|
36
|
+
|
|
37
|
+
export { dingtalkClient, type DingtalkClientEventMap } from './client.js';
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
checkDingtalkPlatformPermit,
|
|
41
|
+
dingtalkGroupPermitResolver,
|
|
42
|
+
normalizeDingtalkSenderForPermit,
|
|
43
|
+
platformPermit,
|
|
44
|
+
} from './platform-permit.js';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 钉钉 DingTalk platform permit
|
|
3
|
+
*/
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
|
+
|
|
6
|
+
const ADAPTER = 'dingtalk';
|
|
7
|
+
|
|
8
|
+
export function platformPermit(perm: string): string {
|
|
9
|
+
return `platform(${ADAPTER},${perm})`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const FACTORY_PERM_MAP: Record<string, string> = {
|
|
13
|
+
scene_admin: 'chat_admin',
|
|
14
|
+
scene_owner: 'chat_owner',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function dingtalkGroupPermitResolver(logicalPerm: string): string {
|
|
18
|
+
return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function normalizeDingtalkSenderForPermit(input: {
|
|
22
|
+
isOwner?: boolean;
|
|
23
|
+
isAdmin?: boolean;
|
|
24
|
+
}): { role?: string; permissions?: string[] } {
|
|
25
|
+
if (input.isOwner) {
|
|
26
|
+
return { role: 'owner', permissions: ['chat_owner', 'chat_admin'] };
|
|
27
|
+
}
|
|
28
|
+
if (input.isAdmin) {
|
|
29
|
+
return { role: 'admin', permissions: ['chat_admin'] };
|
|
30
|
+
}
|
|
31
|
+
return { role: 'member', permissions: [] };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function checkDingtalkPlatformPermit(perm: string, subject: PermissionSubject): boolean {
|
|
35
|
+
const role = subject.sender?.role?.[0];
|
|
36
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
37
|
+
const has = (t: string) => permissions.includes(t);
|
|
38
|
+
|
|
39
|
+
switch (perm) {
|
|
40
|
+
case 'chat_owner':
|
|
41
|
+
return role === 'owner' || has('chat_owner');
|
|
42
|
+
case 'chat_admin':
|
|
43
|
+
return role === 'owner' || role === 'admin' || has('chat_admin') || has('chat_owner');
|
|
44
|
+
default:
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|