@zhin.js/adapter-dingtalk 1.1.0 → 1.1.3
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 +107 -0
- package/README.md +7 -7
- package/adapters/{dingtalk.js → dingtalk/index.js} +6 -6
- package/adapters/{dingtalk.ts → dingtalk/index.ts} +9 -9
- package/agents/dingtalk/agent.json +20 -0
- package/agents/dingtalk/boundaries.md +3 -0
- package/agents/dingtalk/conventions.md +3 -0
- package/agents/dingtalk/skills/dingtalk/SKILL.md +26 -0
- package/agents/dingtalk/skills/dingtalk/tools/add_chat_members/index.js +19 -0
- package/{agent/tools/add_chat_members.ts → agents/dingtalk/skills/dingtalk/tools/add_chat_members/index.ts} +3 -3
- package/agents/dingtalk/skills/dingtalk/tools/create_chat/index.js +20 -0
- package/{agent/tools/create_chat.ts → agents/dingtalk/skills/dingtalk/tools/create_chat/index.ts} +3 -3
- package/agents/dingtalk/skills/dingtalk/tools/dept_info/index.js +15 -0
- package/{agent/tools/dept_info.ts → agents/dingtalk/skills/dingtalk/tools/dept_info/index.ts} +1 -1
- package/agents/dingtalk/skills/dingtalk/tools/get_dept_users/index.js +16 -0
- package/{agent/tools/get_dept_users.ts → agents/dingtalk/skills/dingtalk/tools/get_dept_users/index.ts} +1 -1
- package/agents/dingtalk/skills/dingtalk/tools/get_user/index.js +15 -0
- package/{agent/tools/get_user.ts → agents/dingtalk/skills/dingtalk/tools/get_user/index.ts} +1 -1
- package/agents/dingtalk/skills/dingtalk/tools/list_departments/index.js +16 -0
- package/{agent/tools/list_departments.ts → agents/dingtalk/skills/dingtalk/tools/list_departments/index.ts} +1 -1
- package/agents/dingtalk/skills/dingtalk/tools/send_work_notice/index.js +18 -0
- package/{agent/tools/send_work_notice.ts → agents/dingtalk/skills/dingtalk/tools/send_work_notice/index.ts} +1 -1
- package/agents/dingtalk/skills/dingtalk/tools/update_chat/index.js +29 -0
- package/{agent/tools/update_chat.ts → agents/dingtalk/skills/dingtalk/tools/update_chat/index.ts} +1 -1
- package/agents/dingtalk/system.md +3 -0
- package/commands/{endpoint/add/[id].js → dingtalk/endpoint/add/[id]/index.js} +1 -1
- package/commands/dingtalk/endpoint/add/[id]/index.ts +3 -0
- package/{lib/dingtalk-endpoint-commands.js → commands/dingtalk/endpoint/definition.js} +4 -3
- package/{src/dingtalk-endpoint-commands.ts → commands/dingtalk/endpoint/definition.ts} +3 -3
- package/commands/{endpoint/list.js → dingtalk/endpoint/list/index.js} +1 -1
- package/commands/dingtalk/endpoint/list/index.ts +3 -0
- package/commands/{endpoint/remove/[id].js → dingtalk/endpoint/remove/[id]/index.js} +1 -1
- package/commands/dingtalk/endpoint/remove/[id]/index.ts +3 -0
- package/lib/dingtalk-runtime-state.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/protocol.d.ts +7 -11
- package/lib/protocol.js +14 -15
- package/package.json +32 -21
- package/schema.json +9 -4
- package/src/dingtalk-runtime-state.ts +1 -1
- package/src/index.ts +1 -1
- package/src/protocol.ts +23 -31
- package/agent/skills/dingtalk.md +0 -91
- package/commands/endpoint/add/[id].ts +0 -3
- package/commands/endpoint/list.ts +0 -3
- package/commands/endpoint/remove/[id].ts +0 -3
- package/lib/dingtalk-endpoint-commands.d.ts +0 -1
- /package/{agent/PERMITS.md → PERMITS.md} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,112 @@
|
|
|
1
1
|
# @zhin.js/adapter-dingtalk
|
|
2
2
|
|
|
3
|
+
## 1.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [5b5d270]
|
|
8
|
+
- Updated dependencies [36c2eb9]
|
|
9
|
+
- @zhin.js/im-contract@1.1.2
|
|
10
|
+
- @zhin.js/core@1.1.38
|
|
11
|
+
- @zhin.js/adapter@1.1.15
|
|
12
|
+
- @zhin.js/host-http@1.1.2
|
|
13
|
+
- @zhin.js/agent-feature@1.1.2
|
|
14
|
+
- @zhin.js/feature-kit@1.1.2
|
|
15
|
+
- @zhin.js/skill@1.1.2
|
|
16
|
+
- @zhin.js/tool@1.1.2
|
|
17
|
+
|
|
18
|
+
## 1.1.2
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- a9e4a40: Derive Command user routes only from explicit `commands/**/*/index.ts(x)` entry paths instead of prepending the plugin owner. Child plugins can now publish top-level static or dynamic commands, while duplicate routes across owners fail during generation construction. Adapter endpoint commands move to explicit paths such as `commands/qq/endpoint/list/index.ts` and are invoked as `qq endpoint list`.
|
|
23
|
+
- 8740059: Standardize TypeScript capabilities on named module directories such as `commands/foo/index.ts`, `middlewares/audit/index.ts`, `handlers/message-receive/index.ts`, `pages/workroom/index.tsx`, and `mcps/filesystem/index.ts`. Only the fixed `index` entry is discovered; sibling files remain private helpers.
|
|
24
|
+
|
|
25
|
+
Command route segments come from directories, while `[name]`, `[[name]]`, `[...name]`, and `[[...name]]` directories declare dynamic parameters. Plugin owners do not enter the route unless their config explicitly sets `commandNamespace`; Endpoint `commandPrefix` remains platform-owned and defaults to an empty string.
|
|
26
|
+
|
|
27
|
+
Migrate the built-in adapters, plugins, examples, generators, migration tooling, hot reload classification, Agent authoring surfaces, documentation, and release artifacts to the explicit entry convention.
|
|
28
|
+
|
|
29
|
+
Make Tool ownership and progressive disclosure explicit across all four supported locations: plugin-public `tools/`, Agent-private `agents/<name>/tools/`, Skill-private `skills/<name>/tools/`, and Agent-Skill-private `agents/<name>/skills/<name>/tools/`. Move adapter and group-suite operations that require domain instructions into their owning Skills so `load_skill` is the only path that unlocks their schemas.
|
|
30
|
+
|
|
31
|
+
Remove the package-root `agent/` convention. Public capabilities now use named package-root directories, schedules use `schedules/<name>/index.ts` or `plugin.ts` injection, MCP connections use `mcps/<name>/index.ts`, Prompt Sections use `prompt-sections/<name>/index.ts`, Agent definitions use `agents/<name>/`, and permission vocabulary is published as `PERMITS.md`.
|
|
32
|
+
|
|
33
|
+
- 25a845a: Unify Skills on `skills/<name>/SKILL.md`, support Agent-private Skills and nested Skill-private Tools, publish and mount existing plugin Skills, add governed Skill metadata and Turn access filtering, unlock only already-admitted same-owner Tools, and make `on-risk` and `once` approval behavior precise.
|
|
34
|
+
- ddbb92e: Isolate adapter Skills under platform-specific Agents and automatically select the matching platform Agent for IM ingress, preventing unrelated adapter Skills from entering another platform's prompt surface.
|
|
35
|
+
- 4380cf9: Colocate adapter command definitions and Agent Skill handlers with their owning capabilities, and provide a shared validated platform permission constructor.
|
|
36
|
+
- ab6bde9: Require the canonical expanded DingTalk endpoint configuration. The protocol no longer reinterprets nested `endpoints` or reads endpoint identity and app credentials from `process.env`. The public config type is now `DingTalkEndpointConfig`; optional webhook and robot fields are no longer incorrectly required by the schema.
|
|
37
|
+
- 5c3858e: Make `@zhin.js/im-contract` the explicit zero-dependency owner of transport identities, canonical segments, media guards, conversation facts, stores, and delivery contracts. Platform adapters now read media contracts from that foundation instead of reaching through Core.
|
|
38
|
+
- 33ea736: Use `tools/<name>/index.ts` and `defineAgentTool` from `@zhin.js/tool` as the sole Agent Tool authoring model. Remove the duplicate `@zhin.js/tools` definition, context, bridge, export, and discovery path; migrate plugin manifests, examples, scaffolding, HMR, and prepack compilation to the generation-owned Tool Feature.
|
|
39
|
+
- Updated dependencies [c861789]
|
|
40
|
+
- Updated dependencies [1414ccb]
|
|
41
|
+
- Updated dependencies [743d470]
|
|
42
|
+
- Updated dependencies [62dee52]
|
|
43
|
+
- Updated dependencies [cd54131]
|
|
44
|
+
- Updated dependencies [244e475]
|
|
45
|
+
- Updated dependencies [a9e4a40]
|
|
46
|
+
- Updated dependencies [5855db7]
|
|
47
|
+
- Updated dependencies [ec921d2]
|
|
48
|
+
- Updated dependencies [8740059]
|
|
49
|
+
- Updated dependencies [63d1f7a]
|
|
50
|
+
- Updated dependencies [25a845a]
|
|
51
|
+
- Updated dependencies [103f2c3]
|
|
52
|
+
- Updated dependencies [9110ab8]
|
|
53
|
+
- Updated dependencies [cd2a888]
|
|
54
|
+
- Updated dependencies [eb3227a]
|
|
55
|
+
- Updated dependencies [b853dba]
|
|
56
|
+
- Updated dependencies [e561309]
|
|
57
|
+
- Updated dependencies [d4c6175]
|
|
58
|
+
- Updated dependencies [7a0e1ca]
|
|
59
|
+
- Updated dependencies [103b5d3]
|
|
60
|
+
- Updated dependencies [5a7a7f7]
|
|
61
|
+
- Updated dependencies [b076eae]
|
|
62
|
+
- Updated dependencies [535fed1]
|
|
63
|
+
- Updated dependencies [73a24b7]
|
|
64
|
+
- Updated dependencies [2dbbc15]
|
|
65
|
+
- Updated dependencies [1cb1163]
|
|
66
|
+
- Updated dependencies [be3061e]
|
|
67
|
+
- Updated dependencies [75f8332]
|
|
68
|
+
- Updated dependencies [81935e2]
|
|
69
|
+
- Updated dependencies [f9ed01b]
|
|
70
|
+
- Updated dependencies [ac0ab50]
|
|
71
|
+
- Updated dependencies [5140ce1]
|
|
72
|
+
- Updated dependencies [522d75f]
|
|
73
|
+
- Updated dependencies [a7611b3]
|
|
74
|
+
- Updated dependencies [8823044]
|
|
75
|
+
- Updated dependencies [379439b]
|
|
76
|
+
- Updated dependencies [11c9352]
|
|
77
|
+
- Updated dependencies [6b70e46]
|
|
78
|
+
- Updated dependencies [135ac91]
|
|
79
|
+
- Updated dependencies [140cf0f]
|
|
80
|
+
- Updated dependencies [251e4d2]
|
|
81
|
+
- Updated dependencies [203ad34]
|
|
82
|
+
- Updated dependencies [e6c5113]
|
|
83
|
+
- Updated dependencies [e0f6478]
|
|
84
|
+
- Updated dependencies [baef56b]
|
|
85
|
+
- Updated dependencies [698f16f]
|
|
86
|
+
- Updated dependencies [da0a8e3]
|
|
87
|
+
- Updated dependencies [2fd8017]
|
|
88
|
+
- Updated dependencies [5c3858e]
|
|
89
|
+
- Updated dependencies [33ea736]
|
|
90
|
+
- Updated dependencies [507d602]
|
|
91
|
+
- Updated dependencies [df9f76b]
|
|
92
|
+
- @zhin.js/core@1.1.37
|
|
93
|
+
- @zhin.js/tool@1.1.1
|
|
94
|
+
- @zhin.js/host-http@1.1.1
|
|
95
|
+
- @zhin.js/adapter@1.1.14
|
|
96
|
+
- @zhin.js/feature-kit@1.1.1
|
|
97
|
+
- @zhin.js/agent-feature@1.1.1
|
|
98
|
+
- @zhin.js/skill@1.1.1
|
|
99
|
+
- @zhin.js/logger@1.1.1
|
|
100
|
+
- @zhin.js/im-contract@1.1.1
|
|
101
|
+
|
|
102
|
+
## 1.1.1
|
|
103
|
+
|
|
104
|
+
### Patch Changes
|
|
105
|
+
|
|
106
|
+
- Updated dependencies [769e67f]
|
|
107
|
+
- @zhin.js/adapter@1.1.13
|
|
108
|
+
- @zhin.js/core@1.1.36
|
|
109
|
+
|
|
3
110
|
## 1.1.0
|
|
4
111
|
|
|
5
112
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ pnpm add @zhin.js/adapter-dingtalk
|
|
|
18
18
|
|
|
19
19
|
## Plugin Runtime
|
|
20
20
|
|
|
21
|
-
- `@zhin.js/adapter` — 约定式薄入口 `adapters/dingtalk.ts`(`defineAdapter`)
|
|
21
|
+
- `@zhin.js/adapter` — 约定式薄入口 `adapters/dingtalk/index.ts`(`defineAdapter`)
|
|
22
22
|
- 实现:`src/endpoint.ts`(生命周期/出站/OpenAPI)、`src/webhook.ts`(验签入站)、`src/protocol.ts`
|
|
23
23
|
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
24
24
|
- `@zhin.js/host-http` — `httpHostToken` 注册 Webhook 路由(**非** legacy host-router/Koa)
|
|
@@ -35,7 +35,7 @@ pnpm add @zhin.js/adapter-dingtalk
|
|
|
35
35
|
3. 设置消息接收 URL 为 `https://your-domain/dingtalk/webhook`
|
|
36
36
|
4. Runtime Host(`http`)须已 listen,Webhook 才可达
|
|
37
37
|
|
|
38
|
-
必填字段(`endpoints[i]`):`
|
|
38
|
+
必填字段(`endpoints[i]`):`id`、`appKey`、`appSecret`。
|
|
39
39
|
|
|
40
40
|
## 最小配置
|
|
41
41
|
|
|
@@ -45,7 +45,7 @@ plugins:
|
|
|
45
45
|
dingtalk:
|
|
46
46
|
apiBaseUrl: https://oapi.dingtalk.com # 可选,顶层共享
|
|
47
47
|
endpoints:
|
|
48
|
-
-
|
|
48
|
+
- id: my-dingtalk-bot
|
|
49
49
|
appKey: ${DINGTALK_APP_KEY}
|
|
50
50
|
appSecret: ${DINGTALK_APP_SECRET}
|
|
51
51
|
robotCode: ${DINGTALK_ROBOT_CODE}
|
|
@@ -58,9 +58,9 @@ plugins:
|
|
|
58
58
|
|
|
59
59
|
| 变量 | 说明 |
|
|
60
60
|
|------|------|
|
|
61
|
-
| `DINGTALK_APP_KEY` |
|
|
62
|
-
| `DINGTALK_APP_SECRET` |
|
|
63
|
-
| `DINGTALK_ROBOT_CODE` | RobotCode
|
|
61
|
+
| `DINGTALK_APP_KEY` | 示例中由 YAML `${DINGTALK_APP_KEY}` 引用的 AppKey;变量名可自行定义 |
|
|
62
|
+
| `DINGTALK_APP_SECRET` | 示例中由 YAML `${DINGTALK_APP_SECRET}` 引用的 AppSecret;变量名可自行定义 |
|
|
63
|
+
| `DINGTALK_ROBOT_CODE` | 示例中由 YAML `${DINGTALK_ROBOT_CODE}` 引用的 RobotCode;变量名可自行定义 |
|
|
64
64
|
|
|
65
65
|
## 消息类型映射
|
|
66
66
|
|
|
@@ -75,7 +75,7 @@ plugins:
|
|
|
75
75
|
|
|
76
76
|
## Agent 工具
|
|
77
77
|
|
|
78
|
-
`
|
|
78
|
+
`agents/dingtalk/skills/dingtalk/tools/` 在 DingTalk Skill 激活后提供 get_user、部门、群聊、工作通知等 Tool。工具声明 `adapter: 'dingtalk'` 后,通过惰性的 `context.$client` 自动取得当前操作的 `DingTalkClient`;无需把 Endpoint id 暴露给模型。
|
|
79
79
|
|
|
80
80
|
## 平台权限(platform permit)
|
|
81
81
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
/**
|
|
3
|
-
* Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
|
|
3
|
+
* Convention entry: discover `adapters/dingtalk/index.ts` → defineAdapter.
|
|
4
4
|
*/
|
|
5
5
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
6
6
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
7
|
-
import { DingTalkEndpoint } from "
|
|
8
|
-
import { resolveDingTalkConfig, } from "
|
|
9
|
-
import { dingtalkRuntimeStateToken } from "
|
|
10
|
-
export { DingTalkEndpoint } from "
|
|
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
11
|
export default defineAdapter({
|
|
12
12
|
capabilities: ['inbound', 'outbound'],
|
|
13
13
|
// 钉钉机器人媒体消息仅消费远程 URL;Markdown 走原生 msgtype;
|
|
@@ -19,7 +19,7 @@ export default defineAdapter({
|
|
|
19
19
|
},
|
|
20
20
|
create(context) {
|
|
21
21
|
const config = resolveDingTalkConfig(context.config);
|
|
22
|
-
// 注册到插件运行时状态(dingtalk
|
|
22
|
+
// 注册到插件运行时状态(dingtalk endpoint list 的"运行中"数据源)
|
|
23
23
|
context.use(dingtalkRuntimeStateToken).endpoints.set(config.id, {
|
|
24
24
|
id: config.id,
|
|
25
25
|
mode: 'webhook',
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Convention entry: discover `adapters/dingtalk.ts` → defineAdapter.
|
|
2
|
+
* Convention entry: discover `adapters/dingtalk/index.ts` → defineAdapter.
|
|
3
3
|
*/
|
|
4
4
|
import { defineAdapter } from 'zhin.js/adapter';
|
|
5
5
|
import { httpHostToken } from '@zhin.js/host-http';
|
|
6
|
-
import { DingTalkEndpoint } from '
|
|
6
|
+
import { DingTalkEndpoint } from '../../src/endpoint.js';
|
|
7
7
|
import {
|
|
8
8
|
resolveDingTalkConfig,
|
|
9
|
-
type
|
|
10
|
-
} from '
|
|
11
|
-
import { dingtalkRuntimeStateToken } from '
|
|
9
|
+
type DingTalkEndpointConfig,
|
|
10
|
+
} from '../../src/protocol.js';
|
|
11
|
+
import { dingtalkRuntimeStateToken } from '../../src/dingtalk-runtime-state.js';
|
|
12
12
|
|
|
13
|
-
export { DingTalkEndpoint } from '
|
|
14
|
-
export type { DingTalkEndpointOptions, DingTalkFetch } from '
|
|
13
|
+
export { DingTalkEndpoint } from '../../src/endpoint.js';
|
|
14
|
+
export type { DingTalkEndpointOptions, DingTalkFetch } from '../../src/endpoint.js';
|
|
15
15
|
|
|
16
|
-
export default defineAdapter<
|
|
16
|
+
export default defineAdapter<DingTalkEndpointConfig>({
|
|
17
17
|
capabilities: ['inbound', 'outbound'],
|
|
18
18
|
// 钉钉机器人媒体消息仅消费远程 URL;Markdown 走原生 msgtype;
|
|
19
19
|
// 无按钮交互面,交互段降级纯文本。
|
|
@@ -24,7 +24,7 @@ export default defineAdapter<DingTalkAdapterConfig>({
|
|
|
24
24
|
},
|
|
25
25
|
create(context) {
|
|
26
26
|
const config = resolveDingTalkConfig(context.config);
|
|
27
|
-
// 注册到插件运行时状态(dingtalk
|
|
27
|
+
// 注册到插件运行时状态(dingtalk endpoint list 的"运行中"数据源)
|
|
28
28
|
context.use(dingtalkRuntimeStateToken).endpoints.set(config.id, {
|
|
29
29
|
id: config.id,
|
|
30
30
|
mode: 'webhook',
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "DINGTALK Platform Agent",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Handles dingtalk platform-specific operations and progressively loads only the required platform Skill.",
|
|
5
|
+
"trigger_rules": {
|
|
6
|
+
"file_patterns": [],
|
|
7
|
+
"keywords": [
|
|
8
|
+
"dingtalk",
|
|
9
|
+
"adapter:dingtalk"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"entry_points": [
|
|
13
|
+
"system.md",
|
|
14
|
+
"boundaries.md",
|
|
15
|
+
"conventions.md"
|
|
16
|
+
],
|
|
17
|
+
"platforms": [
|
|
18
|
+
"dingtalk"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dingtalk
|
|
3
|
+
platforms: [dingtalk]
|
|
4
|
+
description: 钉钉组织查询、工作通知和群聊创建维护能力。
|
|
5
|
+
keywords: [dingtalk, 钉钉, 部门, 用户, 工作通知, 群聊]
|
|
6
|
+
tags: [adapter, collaboration]
|
|
7
|
+
tools:
|
|
8
|
+
- get_user
|
|
9
|
+
- get_dept_users
|
|
10
|
+
- list_departments
|
|
11
|
+
- send_work_notice
|
|
12
|
+
- create_chat
|
|
13
|
+
- add_chat_members
|
|
14
|
+
- dept_info
|
|
15
|
+
- update_chat
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# 钉钉
|
|
19
|
+
|
|
20
|
+
用户或部门信息不完整时,先查询再执行写操作:
|
|
21
|
+
|
|
22
|
+
1. 用 `list_departments` / `dept_info` 确认部门。
|
|
23
|
+
2. 用 `get_dept_users` / `get_user` 解析稳定的用户 ID。
|
|
24
|
+
3. 发送工作通知,或创建、更新群聊并添加成员。
|
|
25
|
+
|
|
26
|
+
不要把昵称直接当作用户 ID。当前 Agent Tool 不提供踢人、改群名或读取当前群详情能力;遇到这些请求时应明确说明能力边界。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { platformPermission } from '@zhin.js/permission';
|
|
5
|
+
export default defineAgentTool({
|
|
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: [platformPermission('dingtalk', 'chat_admin')],
|
|
14
|
+
async execute({ chat_id, user_ids }, 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
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineAgentTool } from '@zhin.js/
|
|
1
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
3
|
+
import { platformPermission } from '@zhin.js/permission';
|
|
4
4
|
|
|
5
5
|
export default defineAgentTool<{ chat_id: string; user_ids: string }>({
|
|
6
6
|
description: '向钉钉群聊添加成员',
|
|
@@ -10,7 +10,7 @@ export default defineAgentTool<{ chat_id: string; user_ids: string }>({
|
|
|
10
10
|
}),
|
|
11
11
|
adapter: 'dingtalk',
|
|
12
12
|
tags: ['dingtalk'],
|
|
13
|
-
permissions: [
|
|
13
|
+
permissions: [platformPermission('dingtalk', 'chat_admin')],
|
|
14
14
|
async execute({ chat_id, user_ids }: { chat_id: string; user_ids: string }, context) {
|
|
15
15
|
const endpoint = context.$client;
|
|
16
16
|
const success = await endpoint.updateChat(chat_id, { add_useridlist: user_ids.split(',') });
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { platformPermission } from '@zhin.js/permission';
|
|
5
|
+
export default defineAgentTool({
|
|
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: [platformPermission('dingtalk', 'chat_owner')],
|
|
15
|
+
async execute({ name, owner, members }, 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
|
+
});
|
package/{agent/tools/create_chat.ts → agents/dingtalk/skills/dingtalk/tools/create_chat/index.ts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defineAgentTool } from '@zhin.js/
|
|
1
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
3
|
+
import { platformPermission } from '@zhin.js/permission';
|
|
4
4
|
|
|
5
5
|
export default defineAgentTool<{ name: string; owner: string; members: string }>({
|
|
6
6
|
description: '创建钉钉群聊',
|
|
@@ -11,7 +11,7 @@ export default defineAgentTool<{ name: string; owner: string; members: string }>
|
|
|
11
11
|
}),
|
|
12
12
|
adapter: 'dingtalk',
|
|
13
13
|
tags: ['dingtalk'],
|
|
14
|
-
permissions: [
|
|
14
|
+
permissions: [platformPermission('dingtalk', 'chat_owner')],
|
|
15
15
|
async execute({ name, owner, members }: { name: string; owner: string; members: string }, context) {
|
|
16
16
|
const endpoint = context.$client;
|
|
17
17
|
const chatId = await endpoint.createChat(name, owner, members.split(','));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '获取钉钉部门详细信息',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
dept_id: z.string().describe('部门 ID'),
|
|
8
|
+
}),
|
|
9
|
+
adapter: 'dingtalk',
|
|
10
|
+
tags: ['dingtalk'],
|
|
11
|
+
async execute({ dept_id }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
13
|
+
return await endpoint.getDepartmentInfo(Number(dept_id));
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '获取钉钉部门用户列表',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
dept_id: z.string().describe('部门 ID'),
|
|
8
|
+
}),
|
|
9
|
+
adapter: 'dingtalk',
|
|
10
|
+
tags: ['dingtalk'],
|
|
11
|
+
async execute({ dept_id }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
13
|
+
const users = await endpoint.getDepartmentUsers(Number(dept_id));
|
|
14
|
+
return { users, count: users.length };
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '获取钉钉用户信息',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
user_id: z.string().describe('用户 ID'),
|
|
8
|
+
}),
|
|
9
|
+
adapter: 'dingtalk',
|
|
10
|
+
tags: ['dingtalk'],
|
|
11
|
+
async execute({ user_id }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
13
|
+
return await endpoint.getUserInfo(user_id);
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '获取钉钉部门列表',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
dept_id: z.string().optional().describe('父部门 ID,默认 1(根部门)'),
|
|
8
|
+
}),
|
|
9
|
+
adapter: 'dingtalk',
|
|
10
|
+
tags: ['dingtalk'],
|
|
11
|
+
async execute({ dept_id }, context) {
|
|
12
|
+
const endpoint = context.$client;
|
|
13
|
+
const departments = await endpoint.getDepartmentList(Number(dept_id || '1'));
|
|
14
|
+
return { departments, count: departments.length };
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '向指定用户发送钉钉工作通知',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
user_ids: z.string().describe('用户 ID 列表,逗号分隔'),
|
|
8
|
+
content: z.string().describe('通知内容'),
|
|
9
|
+
}),
|
|
10
|
+
adapter: 'dingtalk',
|
|
11
|
+
tags: ['dingtalk'],
|
|
12
|
+
async execute({ user_ids, content }, context) {
|
|
13
|
+
const endpoint = context.$client;
|
|
14
|
+
const msgContent = { msgtype: 'text', text: { content } };
|
|
15
|
+
const success = await endpoint.sendWorkNotice(user_ids.split(','), msgContent);
|
|
16
|
+
return { success, message: success ? '工作通知已发送' : '发送失败' };
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
export default defineAgentTool({
|
|
5
|
+
description: '更新钉钉群聊设置(改名、换群主、增减成员)',
|
|
6
|
+
inputSchema: z.object({
|
|
7
|
+
chat_id: z.string().describe('群聊 ID'),
|
|
8
|
+
name: z.string().optional().describe('新群名(可选)'),
|
|
9
|
+
owner: z.string().optional().describe('新群主 userId(可选)'),
|
|
10
|
+
add_members: z.string().optional().describe('要添加的成员 userId,逗号分隔(可选)'),
|
|
11
|
+
remove_members: z.string().optional().describe('要移除的成员 userId,逗号分隔(可选)'),
|
|
12
|
+
}),
|
|
13
|
+
adapter: 'dingtalk',
|
|
14
|
+
tags: ['dingtalk'],
|
|
15
|
+
async execute({ chat_id, name, owner, add_members, remove_members }, context) {
|
|
16
|
+
const endpoint = context.$client;
|
|
17
|
+
const options = {};
|
|
18
|
+
if (name)
|
|
19
|
+
options.name = name;
|
|
20
|
+
if (owner)
|
|
21
|
+
options.owner = owner;
|
|
22
|
+
if (add_members)
|
|
23
|
+
options.add_useridlist = add_members.split(',').map((s) => s.trim());
|
|
24
|
+
if (remove_members)
|
|
25
|
+
options.del_useridlist = remove_members.split(',').map((s) => s.trim());
|
|
26
|
+
await endpoint.updateChat(chat_id, options);
|
|
27
|
+
return { success: true, message: '群聊设置已更新' };
|
|
28
|
+
},
|
|
29
|
+
});
|
package/{agent/tools/update_chat.ts → agents/dingtalk/skills/dingtalk/tools/update_chat/index.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineAgentTool } from '@zhin.js/
|
|
1
|
+
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
export default defineAgentTool<{ chat_id: string; name?: string; owner?: string; add_members?: string; remove_members?: string }>({
|
|
4
4
|
description: '更新钉钉群聊设置(改名、换群主、增减成员)',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
1
2
|
/**
|
|
2
|
-
* `dingtalk
|
|
3
|
-
* commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
3
|
+
* `dingtalk endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
4
|
+
* commands/dingtalk/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
5
|
*/
|
|
5
6
|
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
7
|
import { defineCommand } from 'zhin.js/command';
|
|
7
|
-
import { dingtalkRuntimeStateToken } from
|
|
8
|
+
import { dingtalkRuntimeStateToken } from "../../../lib/dingtalk-runtime-state.js";
|
|
8
9
|
export const dingtalkEndpointCommands = createEndpointCommands({
|
|
9
10
|
adapterKey: 'dingtalk',
|
|
10
11
|
adapterDisplayName: 'DingTalk',
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `dingtalk
|
|
3
|
-
* commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
2
|
+
* `dingtalk endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
3
|
+
* commands/dingtalk/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
4
|
*/
|
|
5
5
|
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
6
|
import { defineCommand } from 'zhin.js/command';
|
|
7
|
-
import { dingtalkRuntimeStateToken } from '
|
|
7
|
+
import { dingtalkRuntimeStateToken } from '../../../src/dingtalk-runtime-state.js';
|
|
8
8
|
|
|
9
9
|
export const dingtalkEndpointCommands = createEndpointCommands({
|
|
10
10
|
adapterKey: 'dingtalk',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DingTalk 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `dingtalk
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `dingtalk endpoint` 命令共享(同一 owner generation)。
|
|
4
4
|
*/
|
|
5
5
|
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
6
|
export const dingtalkRuntimeStateToken = defineEndpointRuntimeStateToken('dingtalk');
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { dingtalkInboundConversation, formatInboundContent, formatOutboundBody, generateMessageId, headerValue, normalizeWebhookPath, readTextBody, resolveChatType, resolveDingTalkConfig, resolveSender, verifySignature, type AccessToken, type
|
|
1
|
+
export { dingtalkInboundConversation, formatInboundContent, formatOutboundBody, generateMessageId, headerValue, normalizeWebhookPath, readTextBody, resolveChatType, resolveDingTalkConfig, resolveSender, verifySignature, type AccessToken, type DingTalkEndpointConfig, type DingTalkApiResponse, type DingTalkEvent, type DingTalkMessage, type DingTalkSendBody, type DingTalkWireSegment, type ResolvedDingTalkConfig, } from './protocol.js';
|
|
2
2
|
export { DingTalkClient, DingTalkEndpoint, type DingTalkClientApi, type DingTalkEndpointOptions, type DingTalkFetch, } from './endpoint.js';
|
|
3
3
|
export { registerDingTalkWebhookRoutes, handleDingTalkWebhookRequest, type DingTalkWebhookHandler, } from './webhook.js';
|
|
4
4
|
export { dingtalkClient, type DingtalkClientEventMap } from './client.js';
|
package/lib/protocol.d.ts
CHANGED
|
@@ -3,19 +3,15 @@
|
|
|
3
3
|
* Canonicalization is owned by gateway/core before endpoint.send.
|
|
4
4
|
*/
|
|
5
5
|
import type { IncomingMessage } from 'node:http';
|
|
6
|
-
import type
|
|
7
|
-
/**
|
|
8
|
-
export interface
|
|
9
|
-
readonly id
|
|
10
|
-
readonly appKey
|
|
11
|
-
readonly appSecret
|
|
6
|
+
import { type ConversationRef } from '@zhin.js/im-contract';
|
|
7
|
+
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
8
|
+
export interface DingTalkEndpointConfig {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly appKey: string;
|
|
11
|
+
readonly appSecret: string;
|
|
12
12
|
readonly webhookPath?: string;
|
|
13
13
|
readonly robotCode?: string;
|
|
14
14
|
readonly apiBaseUrl?: string;
|
|
15
|
-
/** Transitional: legacy root `endpoints[]` with `context: dingtalk`. */
|
|
16
|
-
readonly endpoints?: ReadonlyArray<Partial<ResolvedDingTalkConfig> & {
|
|
17
|
-
readonly context?: string;
|
|
18
|
-
}>;
|
|
19
15
|
}
|
|
20
16
|
export interface ResolvedDingTalkConfig {
|
|
21
17
|
readonly context: 'dingtalk';
|
|
@@ -102,7 +98,7 @@ export interface DingTalkSendBody {
|
|
|
102
98
|
};
|
|
103
99
|
readonly robotCode?: string;
|
|
104
100
|
}
|
|
105
|
-
export declare function resolveDingTalkConfig(config
|
|
101
|
+
export declare function resolveDingTalkConfig(config: DingTalkEndpointConfig): ResolvedDingTalkConfig;
|
|
106
102
|
export declare function normalizeWebhookPath(path: string): string;
|
|
107
103
|
export declare function resolveChatType(conversationType?: string): 'group' | 'private';
|
|
108
104
|
/**
|
package/lib/protocol.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Canonicalization is owned by gateway/core before endpoint.send.
|
|
4
4
|
*/
|
|
5
5
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
6
|
-
import { isMediaRef } from '@zhin.js/
|
|
6
|
+
import { isMediaRef } from '@zhin.js/im-contract';
|
|
7
7
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
8
8
|
const logger = getLogger('dingtalk');
|
|
9
9
|
/**
|
|
@@ -22,20 +22,13 @@ export function isDingtalkBotMentioned(event, robotCode) {
|
|
|
22
22
|
}
|
|
23
23
|
return (event.atUsers ?? []).some((user) => user.dingtalkId === robotCode);
|
|
24
24
|
}
|
|
25
|
-
export function resolveDingTalkConfig(config
|
|
26
|
-
const
|
|
27
|
-
const appKey = config.appKey
|
|
28
|
-
const appSecret = config.appSecret
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const id = (typeof config.id === 'string' && config.id)
|
|
33
|
-
|| (typeof entry?.id === 'string' && entry.id)
|
|
34
|
-
|| process.env.DINGTALK_BOT_NAME
|
|
35
|
-
|| 'dingtalk-bot';
|
|
36
|
-
const webhookPath = normalizeWebhookPath(config.webhookPath ?? entry?.webhookPath ?? '/dingtalk/webhook');
|
|
37
|
-
const apiBaseUrl = (config.apiBaseUrl ?? entry?.apiBaseUrl ?? 'https://oapi.dingtalk.com').replace(/\/$/, '');
|
|
38
|
-
const robotCode = config.robotCode ?? entry?.robotCode;
|
|
25
|
+
export function resolveDingTalkConfig(config) {
|
|
26
|
+
const id = requiredEndpointField(config.id, 'id');
|
|
27
|
+
const appKey = requiredEndpointField(config.appKey, 'appKey');
|
|
28
|
+
const appSecret = requiredEndpointField(config.appSecret, 'appSecret');
|
|
29
|
+
const webhookPath = normalizeWebhookPath(config.webhookPath ?? '/dingtalk/webhook');
|
|
30
|
+
const apiBaseUrl = (config.apiBaseUrl ?? 'https://oapi.dingtalk.com').replace(/\/$/, '');
|
|
31
|
+
const robotCode = config.robotCode;
|
|
39
32
|
return {
|
|
40
33
|
context: 'dingtalk',
|
|
41
34
|
id,
|
|
@@ -46,6 +39,12 @@ export function resolveDingTalkConfig(config = {}) {
|
|
|
46
39
|
apiBaseUrl,
|
|
47
40
|
};
|
|
48
41
|
}
|
|
42
|
+
function requiredEndpointField(value, field) {
|
|
43
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
44
|
+
throw new TypeError(`DingTalk endpoint requires a non-empty ${field}`);
|
|
45
|
+
}
|
|
46
|
+
return value.trim();
|
|
47
|
+
}
|
|
49
48
|
export function normalizeWebhookPath(path) {
|
|
50
49
|
const trimmed = path.trim() || '/dingtalk/webhook';
|
|
51
50
|
return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-dingtalk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Zhin.js DingTalk (钉钉) adapter for Plugin Runtime (HTTP webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -33,27 +33,26 @@
|
|
|
33
33
|
"directory": "plugins/adapters/dingtalk"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@zhin.js/adapter": "1.1.
|
|
37
|
-
"@zhin.js/
|
|
38
|
-
"@zhin.js/
|
|
39
|
-
"@zhin.js/
|
|
40
|
-
"@zhin.js/
|
|
41
|
-
"@zhin.js/
|
|
36
|
+
"@zhin.js/adapter": "1.1.15",
|
|
37
|
+
"@zhin.js/agent-feature": "1.1.2",
|
|
38
|
+
"@zhin.js/core": "1.1.38",
|
|
39
|
+
"@zhin.js/feature-kit": "1.1.2",
|
|
40
|
+
"@zhin.js/host-http": "1.1.2",
|
|
41
|
+
"@zhin.js/im-contract": "1.1.2",
|
|
42
|
+
"@zhin.js/logger": "1.1.1",
|
|
43
|
+
"@zhin.js/skill": "1.1.2",
|
|
44
|
+
"@zhin.js/tool": "1.1.2"
|
|
42
45
|
},
|
|
43
46
|
"peerDependencies": {
|
|
44
47
|
"zod": "^4.0.0",
|
|
45
|
-
"@zhin.js/adapter": "^1.1.
|
|
46
|
-
"@zhin.js/
|
|
47
|
-
"@zhin.js/
|
|
48
|
-
"@zhin.js/
|
|
49
|
-
"@zhin.js/
|
|
50
|
-
"
|
|
51
|
-
"zhin.js": "^1.1.0"
|
|
48
|
+
"@zhin.js/adapter": "^1.1.15",
|
|
49
|
+
"@zhin.js/command": "^1.1.2",
|
|
50
|
+
"@zhin.js/core": "^1.1.38",
|
|
51
|
+
"@zhin.js/host-http": "^1.1.2",
|
|
52
|
+
"@zhin.js/permission": "^1.1.2",
|
|
53
|
+
"zhin.js": "^1.1.3"
|
|
52
54
|
},
|
|
53
55
|
"peerDependenciesMeta": {
|
|
54
|
-
"@zhin.js/agent": {
|
|
55
|
-
"optional": true
|
|
56
|
-
},
|
|
57
56
|
"@zhin.js/command": {
|
|
58
57
|
"optional": true
|
|
59
58
|
},
|
|
@@ -69,8 +68,7 @@
|
|
|
69
68
|
"typescript": "^6.0.3",
|
|
70
69
|
"vitest": "^4.1.10",
|
|
71
70
|
"zod": "^4.4.3",
|
|
72
|
-
"
|
|
73
|
-
"zhin.js": "1.1.0"
|
|
71
|
+
"zhin.js": "1.1.3"
|
|
74
72
|
},
|
|
75
73
|
"files": [
|
|
76
74
|
"adapters",
|
|
@@ -79,9 +77,10 @@
|
|
|
79
77
|
"schema.json",
|
|
80
78
|
"src",
|
|
81
79
|
"lib",
|
|
82
|
-
"
|
|
80
|
+
"agents",
|
|
83
81
|
"README.md",
|
|
84
|
-
"CHANGELOG.md"
|
|
82
|
+
"CHANGELOG.md",
|
|
83
|
+
"PERMITS.md"
|
|
85
84
|
],
|
|
86
85
|
"publishConfig": {
|
|
87
86
|
"access": "public",
|
|
@@ -104,6 +103,18 @@
|
|
|
104
103
|
{
|
|
105
104
|
"package": "@zhin.js/command",
|
|
106
105
|
"api": "^1.0.0"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"package": "@zhin.js/tool",
|
|
109
|
+
"api": "^1.0.0"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"package": "@zhin.js/skill",
|
|
113
|
+
"api": "^1.0.0"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"package": "@zhin.js/agent-feature",
|
|
117
|
+
"api": "^1.0.0"
|
|
107
118
|
}
|
|
108
119
|
],
|
|
109
120
|
"plugins": []
|
package/schema.json
CHANGED
|
@@ -27,10 +27,11 @@
|
|
|
27
27
|
},
|
|
28
28
|
"endpoints": {
|
|
29
29
|
"type": "array",
|
|
30
|
+
"minItems": 1,
|
|
30
31
|
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
31
32
|
"items": {
|
|
32
33
|
"type": "object",
|
|
33
|
-
"additionalProperties":
|
|
34
|
+
"additionalProperties": false,
|
|
34
35
|
"properties": {
|
|
35
36
|
"master": {
|
|
36
37
|
"type": [
|
|
@@ -66,6 +67,12 @@
|
|
|
66
67
|
"type": "string",
|
|
67
68
|
"description": "Dingtalk robot code"
|
|
68
69
|
},
|
|
70
|
+
"apiBaseUrl": {
|
|
71
|
+
"type": "string"
|
|
72
|
+
},
|
|
73
|
+
"commandPrefix": {
|
|
74
|
+
"type": "string"
|
|
75
|
+
},
|
|
69
76
|
"id": {
|
|
70
77
|
"type": "string",
|
|
71
78
|
"description": "Dingtalk bot name"
|
|
@@ -74,9 +81,7 @@
|
|
|
74
81
|
"required": [
|
|
75
82
|
"id",
|
|
76
83
|
"appKey",
|
|
77
|
-
"appSecret"
|
|
78
|
-
"webhookPath",
|
|
79
|
-
"robotCode"
|
|
84
|
+
"appSecret"
|
|
80
85
|
]
|
|
81
86
|
}
|
|
82
87
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DingTalk 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `dingtalk
|
|
3
|
+
* 由 plugin.ts setup() provide,adapter create 与 `dingtalk endpoint` 命令共享(同一 owner generation)。
|
|
4
4
|
*/
|
|
5
5
|
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
6
|
|
package/src/index.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -6,24 +6,19 @@
|
|
|
6
6
|
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
7
7
|
import type { IncomingMessage } from 'node:http';
|
|
8
8
|
|
|
9
|
-
import { isMediaRef } from '@zhin.js/
|
|
10
|
-
import type { ConversationRef } from '@zhin.js/im-contract';
|
|
9
|
+
import { isMediaRef, type ConversationRef } from '@zhin.js/im-contract';
|
|
11
10
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
12
11
|
|
|
13
12
|
const logger = getLogger('dingtalk');
|
|
14
13
|
|
|
15
|
-
/**
|
|
16
|
-
export interface
|
|
17
|
-
readonly id
|
|
18
|
-
readonly appKey
|
|
19
|
-
readonly appSecret
|
|
14
|
+
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
15
|
+
export interface DingTalkEndpointConfig {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly appKey: string;
|
|
18
|
+
readonly appSecret: string;
|
|
20
19
|
readonly webhookPath?: string;
|
|
21
20
|
readonly robotCode?: string;
|
|
22
21
|
readonly apiBaseUrl?: string;
|
|
23
|
-
/** Transitional: legacy root `endpoints[]` with `context: dingtalk`. */
|
|
24
|
-
readonly endpoints?: ReadonlyArray<Partial<ResolvedDingTalkConfig> & {
|
|
25
|
-
readonly context?: string;
|
|
26
|
-
}>;
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
export interface ResolvedDingTalkConfig {
|
|
@@ -115,26 +110,13 @@ export interface DingTalkSendBody {
|
|
|
115
110
|
readonly robotCode?: string;
|
|
116
111
|
}
|
|
117
112
|
|
|
118
|
-
export function resolveDingTalkConfig(config:
|
|
119
|
-
const
|
|
120
|
-
const appKey = config.appKey
|
|
121
|
-
const appSecret = config.appSecret
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
const id = (typeof config.id === 'string' && config.id)
|
|
128
|
-
|| (typeof entry?.id === 'string' && entry.id)
|
|
129
|
-
|| process.env.DINGTALK_BOT_NAME
|
|
130
|
-
|| 'dingtalk-bot';
|
|
131
|
-
const webhookPath = normalizeWebhookPath(
|
|
132
|
-
config.webhookPath ?? entry?.webhookPath ?? '/dingtalk/webhook',
|
|
133
|
-
);
|
|
134
|
-
const apiBaseUrl = (
|
|
135
|
-
config.apiBaseUrl ?? entry?.apiBaseUrl ?? 'https://oapi.dingtalk.com'
|
|
136
|
-
).replace(/\/$/, '');
|
|
137
|
-
const robotCode = config.robotCode ?? entry?.robotCode;
|
|
113
|
+
export function resolveDingTalkConfig(config: DingTalkEndpointConfig): ResolvedDingTalkConfig {
|
|
114
|
+
const id = requiredEndpointField(config.id, 'id');
|
|
115
|
+
const appKey = requiredEndpointField(config.appKey, 'appKey');
|
|
116
|
+
const appSecret = requiredEndpointField(config.appSecret, 'appSecret');
|
|
117
|
+
const webhookPath = normalizeWebhookPath(config.webhookPath ?? '/dingtalk/webhook');
|
|
118
|
+
const apiBaseUrl = (config.apiBaseUrl ?? 'https://oapi.dingtalk.com').replace(/\/$/, '');
|
|
119
|
+
const robotCode = config.robotCode;
|
|
138
120
|
return {
|
|
139
121
|
context: 'dingtalk',
|
|
140
122
|
id,
|
|
@@ -146,6 +128,16 @@ export function resolveDingTalkConfig(config: DingTalkAdapterConfig = {}): Resol
|
|
|
146
128
|
};
|
|
147
129
|
}
|
|
148
130
|
|
|
131
|
+
function requiredEndpointField(
|
|
132
|
+
value: unknown,
|
|
133
|
+
field: 'id' | 'appKey' | 'appSecret',
|
|
134
|
+
): string {
|
|
135
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
136
|
+
throw new TypeError(`DingTalk endpoint requires a non-empty ${field}`);
|
|
137
|
+
}
|
|
138
|
+
return value.trim();
|
|
139
|
+
}
|
|
140
|
+
|
|
149
141
|
export function normalizeWebhookPath(path: string): string {
|
|
150
142
|
const trimmed = path.trim() || '/dingtalk/webhook';
|
|
151
143
|
return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
package/agent/skills/dingtalk.md
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dingtalk
|
|
3
|
-
platforms:
|
|
4
|
-
- dingtalk
|
|
5
|
-
description: >-
|
|
6
|
-
钉钉平台管理能力。当用户在钉钉中请求群管理(踢人、改群名、查群信息)、
|
|
7
|
-
组织架构查询(部门/用户查询)、发送工作通知、创建或管理群聊时使用。
|
|
8
|
-
即使用户没有提到钉钉,只要上下文是钉钉/DingTalk 场景且涉及群管理、
|
|
9
|
-
组织架构或工作通知,就应触发。仅有昵称时先查部门用户列表获取 user_id。
|
|
10
|
-
keywords:
|
|
11
|
-
- dingtalk
|
|
12
|
-
- 钉钉
|
|
13
|
-
- adapter:dingtalk
|
|
14
|
-
- 群管理
|
|
15
|
-
- 部门
|
|
16
|
-
- 工作通知
|
|
17
|
-
- 组织架构
|
|
18
|
-
- 企业
|
|
19
|
-
- list_members
|
|
20
|
-
tags:
|
|
21
|
-
- group
|
|
22
|
-
- management
|
|
23
|
-
- im
|
|
24
|
-
- enterprise
|
|
25
|
-
tools:
|
|
26
|
-
- dingtalk_get_user
|
|
27
|
-
- dingtalk_get_dept_users
|
|
28
|
-
- dingtalk_list_departments
|
|
29
|
-
- dingtalk_send_work_notice
|
|
30
|
-
- dingtalk_create_chat
|
|
31
|
-
- dingtalk_add_chat_members
|
|
32
|
-
- dingtalk_dept_info
|
|
33
|
-
- dingtalk_update_chat
|
|
34
|
-
- dingtalk_kick_member
|
|
35
|
-
- dingtalk_set_group_name
|
|
36
|
-
- dingtalk_get_group_info
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
# 钉钉群聊与组织管理技能
|
|
40
|
-
|
|
41
|
-
钉钉是企业 IM 平台,特有组织架构(部门树)和工作通知能力,区别于个人社交类 IM。
|
|
42
|
-
|
|
43
|
-
## 核心原则
|
|
44
|
-
|
|
45
|
-
### 组织架构是核心
|
|
46
|
-
|
|
47
|
-
钉钉的用户隶属于部门树,很多操作需要从组织架构出发:
|
|
48
|
-
```
|
|
49
|
-
dingtalk_list_departments → 获取部门列表(根部门 ID=1)
|
|
50
|
-
dingtalk_get_dept_users(dept_id) → 获取部门下的用户列表
|
|
51
|
-
dingtalk_get_user(user_id) → 获取用户详情
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### 工作通知 ≠ 群消息
|
|
55
|
-
|
|
56
|
-
`dingtalk_send_work_notice` 是直接发给个人的企业通知,出现在钉钉的「工作通知」入口,不需要群聊。用户说「通知一下张三」,如果是正式的企业通知,用 `send_work_notice`;如果只是聊天消息,用普通消息发送。
|
|
57
|
-
|
|
58
|
-
## 工具分类
|
|
59
|
-
|
|
60
|
-
### 群聊管理
|
|
61
|
-
|
|
62
|
-
| 工具 | 用途 | 说明 |
|
|
63
|
-
|------|------|------|
|
|
64
|
-
| `dingtalk_kick_member` | 踢出成员 | — |
|
|
65
|
-
| `dingtalk_set_group_name` | 改群名 | — |
|
|
66
|
-
| `dingtalk_get_group_info` | 群信息 | — |
|
|
67
|
-
| `dingtalk_create_chat` | 创建群聊 | 需群主 userId + 至少一个成员 |
|
|
68
|
-
| `dingtalk_add_chat_members` | 添加成员 | — |
|
|
69
|
-
| `dingtalk_update_chat` | 更新群设置 | 改名、换群主、增减成员 |
|
|
70
|
-
|
|
71
|
-
### 组织架构
|
|
72
|
-
|
|
73
|
-
| 工具 | 用途 | 说明 |
|
|
74
|
-
|------|------|------|
|
|
75
|
-
| `dingtalk_list_departments` | 部门列表 | 默认从根部门 ID=1 开始 |
|
|
76
|
-
| `dingtalk_dept_info` | 部门详情 | — |
|
|
77
|
-
| `dingtalk_get_dept_users` | 部门用户列表 | — |
|
|
78
|
-
| `dingtalk_get_user` | 用户详情 | — |
|
|
79
|
-
|
|
80
|
-
### 通知
|
|
81
|
-
|
|
82
|
-
| 工具 | 用途 | 说明 |
|
|
83
|
-
|------|------|------|
|
|
84
|
-
| `dingtalk_send_work_notice` | 工作通知 | 发给指定用户列表,不需要群 |
|
|
85
|
-
|
|
86
|
-
## 易错点
|
|
87
|
-
|
|
88
|
-
1. **部门查询从根部门 ID=1 开始**。不知道部门 ID 时先 `list_departments` 获取整棵部门树。
|
|
89
|
-
2. **群聊创建需要群主 userId 和至少一个成员**,不能创建空群。
|
|
90
|
-
3. **工作通知是独立于群聊的**,它发到个人的钉钉「工作通知」入口,不要与群消息混淆。
|
|
91
|
-
4. **操作成员需要钉钉 userId**,仅有昵称时先通过 `get_dept_users` 或 `get_group_info` 查找。
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const dingtalkEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
|
|
File without changes
|