@zhin.js/adapter-kook 5.0.2 → 6.0.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 (88) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +61 -453
  3. package/adapters/kook.ts +46 -0
  4. package/agent/tools/blacklist.ts +2 -2
  5. package/agent/tools/create_role.ts +2 -2
  6. package/agent/tools/delete_role.ts +2 -2
  7. package/agent/tools/grant_role.ts +2 -2
  8. package/agent/tools/list_roles.ts +2 -2
  9. package/agent/tools/revoke_role.ts +2 -2
  10. package/lib/endpoint.d.ts +84 -0
  11. package/lib/endpoint.js +299 -0
  12. package/lib/index.d.ts +6 -0
  13. package/lib/index.js +6 -0
  14. package/lib/kook-agent-deps.d.ts +29 -0
  15. package/lib/kook-agent-deps.js +30 -0
  16. package/lib/platform-permit.d.ts +23 -0
  17. package/lib/{src/platform-permit.js → platform-permit.js} +2 -3
  18. package/lib/protocol.d.ts +147 -0
  19. package/lib/protocol.js +279 -0
  20. package/lib/webhook.d.ts +15 -0
  21. package/lib/webhook.js +76 -0
  22. package/lib/ws.d.ts +42 -0
  23. package/lib/ws.js +63 -0
  24. package/package.json +44 -40
  25. package/plugin.ts +13 -0
  26. package/schema.json +92 -0
  27. package/src/endpoint.ts +287 -879
  28. package/src/index.ts +55 -177
  29. package/src/kook-agent-deps.ts +44 -11
  30. package/src/platform-permit.ts +13 -3
  31. package/src/protocol.ts +429 -0
  32. package/src/webhook.ts +116 -0
  33. package/src/ws.ts +120 -0
  34. package/client/Dashboard.tsx +0 -255
  35. package/client/index.tsx +0 -11
  36. package/client/tsconfig.json +0 -7
  37. package/client/utils/api.ts +0 -30
  38. package/dist/index.js +0 -31
  39. package/lib/agent/tools/blacklist.js +0 -33
  40. package/lib/agent/tools/blacklist.js.map +0 -1
  41. package/lib/agent/tools/create_role.js +0 -25
  42. package/lib/agent/tools/create_role.js.map +0 -1
  43. package/lib/agent/tools/delete_role.js +0 -21
  44. package/lib/agent/tools/delete_role.js.map +0 -1
  45. package/lib/agent/tools/grant_role.js +0 -22
  46. package/lib/agent/tools/grant_role.js.map +0 -1
  47. package/lib/agent/tools/list_roles.js +0 -27
  48. package/lib/agent/tools/list_roles.js.map +0 -1
  49. package/lib/agent/tools/revoke_role.js +0 -22
  50. package/lib/agent/tools/revoke_role.js.map +0 -1
  51. package/lib/src/adapter.js +0 -67
  52. package/lib/src/adapter.js.map +0 -1
  53. package/lib/src/endpoint.js +0 -796
  54. package/lib/src/endpoint.js.map +0 -1
  55. package/lib/src/index.js +0 -197
  56. package/lib/src/index.js.map +0 -1
  57. package/lib/src/kook-agent-deps.js +0 -10
  58. package/lib/src/kook-agent-deps.js.map +0 -1
  59. package/lib/src/kook-asset-upload.js +0 -46
  60. package/lib/src/kook-asset-upload.js.map +0 -1
  61. package/lib/src/kook-inbound.js +0 -22
  62. package/lib/src/kook-inbound.js.map +0 -1
  63. package/lib/src/kook-msg-route.js +0 -106
  64. package/lib/src/kook-msg-route.js.map +0 -1
  65. package/lib/src/kook-side-events.js +0 -166
  66. package/lib/src/kook-side-events.js.map +0 -1
  67. package/lib/src/outbound-keyboard.js +0 -66
  68. package/lib/src/outbound-keyboard.js.map +0 -1
  69. package/lib/src/outbound-media.js +0 -45
  70. package/lib/src/outbound-media.js.map +0 -1
  71. package/lib/src/outbound-sendable.js +0 -64
  72. package/lib/src/outbound-sendable.js.map +0 -1
  73. package/lib/src/platform-permit.js.map +0 -1
  74. package/lib/src/segment-mapper.js +0 -2
  75. package/lib/src/segment-mapper.js.map +0 -1
  76. package/lib/src/types.js +0 -8
  77. package/lib/src/types.js.map +0 -1
  78. package/plugin.yml +0 -3
  79. package/src/adapter.ts +0 -75
  80. package/src/kook-asset-upload.ts +0 -55
  81. package/src/kook-inbound.ts +0 -22
  82. package/src/kook-msg-route.ts +0 -122
  83. package/src/kook-side-events.ts +0 -230
  84. package/src/outbound-keyboard.ts +0 -77
  85. package/src/outbound-media.ts +0 -60
  86. package/src/outbound-sendable.ts +0 -73
  87. package/src/segment-mapper.ts +0 -1
  88. package/src/types.ts +0 -58
package/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # @zhin.js/adapter-kook
2
2
 
3
+ ## 6.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 7db69c1: 命令前缀改为适配器配置项:`MessageDispatcher` 不再硬编码 `/`,默认按消息所属适配器实例 config 的 `commandPrefix` 解析(默认 `''` 无前缀,任意文本按命令匹配),`endpoints[i].commandPrefix` 逐项覆盖;`ImRuntime({ commandPrefix })` 仍可设全局静态前缀。全部 20 个平台适配器 schema 新增 `commandPrefix` 属性。
8
+
9
+ BREAKING(行为变化):未配置时命令不再需要 `/` 前缀——原 `/zt` 写法不再命中,直接发 `zt` 即可;需要斜杠风格的适配器请在配置里显式设 `commandPrefix: '/'`。
10
+
11
+ - 713445c: 适配器配置格式定稿(不兼容旧格式):`plugins.<adapter>` 顶层仅共享字段 + `commandPrefix`,`endpoints[i]` 携带 endpoint 级字段(`name` + 凭据,各 schema 已类型化),`endpoints` 为必填(icqq 另需顶层 `master`);icqq 新增 `trusted` 列表(顶层/逐项均可)。scaffold-wizard 全部字段式与自定义 configure() 产出改为新格式,examples(full-bot / qq-games-bot)与 20 个适配器 README 同步迁移。
12
+ - Updated dependencies [7db69c1]
13
+ - Updated dependencies [e5c84ed]
14
+ - Updated dependencies [3ea84a0]
15
+ - Updated dependencies [1ddcd70]
16
+ - Updated dependencies [ac9da66]
17
+ - @zhin.js/core@1.4.0
18
+ - @zhin.js/adapter@1.1.0
19
+ - @zhin.js/plugin-runtime@1.1.0
20
+ - @zhin.js/agent@1.0.5
21
+ - @zhin.js/host-http@1.0.2
22
+ - zhin.js@5.0.0
23
+
24
+ ## 5.0.3
25
+
26
+ ### Patch Changes
27
+
28
+ - cc5c94d: 约定式插件运行时迁移(breaking):插件与适配器由 `usePlugin()` / `extends Adapter` 迁移为 `definePlugin` / `defineAdapter` + `plugin.ts` + 约定目录(`adapters/`、`commands/`、`components/`、`tools/` 等)。
29
+
30
+ - 新增约定式运行时包:`@zhin.js/plugin-runtime`、`@zhin.js/adapter`、`@zhin.js/runtime`、`@zhin.js/host-http`(首版 1.0.0 走 init-publish,不在本 changeset 内 bump)。
31
+ - 全部 20 个平台适配器改为约定式 `defineAdapter`,旧 `usePlugin` / `extends Adapter` / `segment-mapper` 生产入口已删除;onebot11 反向 WSS、onebot12 webhook/wss、milky sse/webhook/wss、satori webhook、kook webhook、qq webhook/middleware 等 slice 1 推迟的连接模式已补齐。
32
+ - 游戏 / 工具 / 服务插件同步迁移到约定目录结构。
33
+ - CLI 增加 plugin-runtime host installer(http/database/outbound/schedule/console 等)。
34
+
35
+ 后续加固(同批):
36
+
37
+ - CLI:`zhin runtime start --daemon`(pidfile/崩溃拉起/风暴保护),orphan watchdog 防僵尸进程;legacy `zhin dev` / `zhin start` 已移除(含 `zhin restart`),`zhin stop` 兼容新 daemon。
38
+ - 安全:builtin 工具统一走 `security/policy-facade.ts` 的 `runToolPolicies`(声明式策略表,deny 优先);审计日志 close flush + 背压队列;`splitCompoundCommand` 引号感知、`extractCommandName` 去引号堵绕过。
39
+ - 日志:Logger 双堆栈修复、本地时区、`getLogger` 挂树(`setLevel` 递归生效)、第三方库(log4js/discord)桥接、启动人读总结。
40
+ - 结构:`plugins/games/shared` 迁为 `packages/game-kit`(`@zhin.js/game-kit`);死目录 `plugins/adapters/common` 删除。
41
+ - 脚手架:`create-zhin-app` / `zhin new` / scaffold-wizard 生成物改为 Plugin Runtime 形态(minimal-bot 同构,新配置格式)。
42
+ - Console:endpoint.list 真实名称与 phase、schema:get-all 按 instanceKey 映射、db:\* 接 DatabaseHost。
43
+
44
+ 注:按仓库发布惯例(见 1bb345dd2),本次 breaking 迁移统一使用 patch,避免 zhin.js 5.0 级联。
45
+
46
+ - 447f3e2: 迁移缺口修复(legacy 功能对齐):
47
+
48
+ - html 段出站规范化:经 `@zhin.js/html-renderer` 渲染为 image 段(sandbox 豁免、无渲染器时降级文本),修复真实平台 `[object Object]`。
49
+ - 群聊 @ 触发 AI:适配器入站标注 `metadata.mentioned`(icqq/qq/slack/onebot11/onebot12/napcat/milky/discord/telegram/kook/dingtalk/satori),`matchAiTrigger` 补齐 ignorePrefixes/respondToAt/respondToPrivate/keywords(默认值与 legacy 对齐)。
50
+ - im_transcripts 全量流水恢复写入(chat_history 工具可用);群聊旁听上下文回迁。
51
+ - `ai.trigger.timeout/thinkingMessage/errorTemplate` 生效;masters/trusted 角色解析对齐 legacy。
52
+ - `Message.sender` 统一为用户 ID(onebot11/12、napcat、milky 原误传显示名);quote_id 经 metadata 接入 AI 引用上下文。
53
+
54
+ - Updated dependencies [16ec4e8]
55
+ - Updated dependencies [cc5c94d]
56
+ - Updated dependencies [447f3e2]
57
+ - @zhin.js/core@1.3.5
58
+ - @zhin.js/agent@1.0.4
59
+ - @zhin.js/host-http@1.0.1
60
+ - zhin.js@4.1.3
61
+ - @zhin.js/logger@1.0.75
62
+ - @zhin.js/plugin-runtime@1.0.1
63
+ - @zhin.js/adapter@1.0.1
64
+
3
65
  ## 5.0.2
4
66
 
5
67
  ### Patch Changes
package/README.md CHANGED
@@ -1,16 +1,14 @@
1
1
  # @zhin.js/adapter-kook
2
2
 
3
- Zhin.js KOOK(开黑啦)适配器,基于 KOOK 官方 API 开发,支持频道和私聊消息。
3
+ Zhin.js KOOK(开黑啦)适配器(Plugin Runtime),默认通过 **WebSocket Gateway**(`kook-client`)收发消息;可选 **Webhook** 模式经 `httpHostToken` 接收平台 POST 推送。
4
4
 
5
- ## 功能特性
5
+ ## 功能
6
6
 
7
- - 🗣️ 支持 KOOK 频道和私聊消息处理
8
- - 📨 消息发送和接收处理
9
- - 🔄 消息格式转换和适配
10
- - 📁 自动数据目录管理
11
- - 基于 WebSocket 的实时通信
12
- - 📝 支持 Markdown 消息格式
13
- - ⏳ AI 处理中表情回应(Typing Indicator / reaction,频道与私聊)
7
+ - WebSocket Gateway 入站(默认;无需公网 HTTPS / host)
8
+ - Webhook 入站(`connection: webhook` + `httpHostToken` + `verify_token`)
9
+ - 解析频道与私聊文本消息
10
+ - 出站 `send({ target, payload })` → KOOK KMarkdown(`channel:id` / `private:id`)
11
+ - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
14
12
 
15
13
  ## 安装
16
14
 
@@ -18,478 +16,88 @@ Zhin.js KOOK(开黑啦)适配器,基于 KOOK 官方 API 开发,支持频
18
16
  pnpm add @zhin.js/adapter-kook
19
17
  ```
20
18
 
19
+ ## Plugin Runtime
20
+
21
+ - `@zhin.js/adapter` — 约定式 `adapters/kook.ts`(`defineAdapter`)
22
+ - `@zhin.js/core` — `messageGatewayToken` 入站/出站
23
+ - `@zhin.js/host-http` — Webhook 模式 POST 路由(WebSocket 不需要)
24
+ - `@zhin.js/plugin-runtime` — `plugin.ts`(`definePlugin`)
25
+ - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
26
+ - **WebSocket 路径无需** `@zhin.js/host-http` / `@zhin.js/host-router`
27
+
28
+ 入站:`gateway.receive({ adapter, target: 'channel:…'|'private:…', content, sender, metadata })`
29
+ 出站:`send({ target, payload })` → `sendChannelMsg` / `sendPrivateMsg`
30
+
21
31
  ## 前置条件
22
32
 
23
33
  | 要求 | 说明 |
24
34
  |------|------|
25
35
  | **Bot Token** | 在 [KOOK 开发者平台](https://developer.kookapp.cn/) 创建应用并获取 |
26
36
  | **邀请入服** | 将机器人邀请到目标服务器,并授予查看频道、发送消息等权限 |
27
- | **连接方式** | 当前适配器通过 **WebSocket** 连接 KOOK(`kook-client`);无需公网 URL |
28
- | **host-router** | 不需要 |
37
+ | **WebSocket(默认)** | `kook-client` 正向连接;无需公网 URL |
38
+ | **Webhook** | 需公网 HTTPS + Host `httpHostToken`;与 WebSocket 互斥 |
39
+ | **host-http** | 仅 Webhook 模式需要 |
29
40
 
30
- 必填字段见 `KookEndpointConfig`:`context`、`name`、`token`。
41
+ 必填字段(`endpoints[i]`):`name`、`token`。
31
42
 
32
43
  ## 最小配置
33
44
 
34
45
  ```yaml
46
+ # zhin.config.yml(Plugin Runtime)
35
47
  plugins:
36
- - "@zhin.js/adapter-kook"
37
-
38
- endpoints:
39
- - context: kook
40
- name: my-kook-bot
41
- token: "${KOOK_TOKEN}"
42
- ```
43
-
44
- ## 配置
45
-
46
- 可选字段(见 `KookEndpointConfig`):`data_dir`、`timeout`、`max_retry`、`ignore`、`logLevel`、`typingIndicator`。
47
-
48
- ```yaml
49
- endpoints:
50
- - context: kook
51
- name: my-kook-bot
52
- token: "${KOOK_TOKEN}"
53
- data_dir: ./data/kook
54
- # AI 处理中:频道/私聊贴表情回应(不打「正在思考」消息)
55
- typingIndicator:
56
- enabled: true
57
- defaultEmoji: "⏳"
58
- autoRemove: true
59
- privateConfig:
60
- type: reaction
61
- emoji: "⏳"
62
- groupConfig:
63
- type: reaction
64
- emoji: "⏳"
65
- ```
66
-
67
- `emoji` 可用 Unicode(如 `⏳`)或 KOOK 自定义表情 ID;处理完成后会自动 `delete-reaction` 移除。
68
-
69
- TypeScript 等价写法:
70
-
71
- ```typescript
72
- import { defineConfig } from 'zhin.js'
73
-
74
- export default defineConfig({
75
- endpoints: [
76
- {
77
- context: 'kook',
78
- name: 'my-kook-bot',
79
- token: process.env.KOOK_TOKEN!,
80
- data_dir: './data/kook',
81
- },
82
- ],
83
- plugins: ['@zhin.js/adapter-kook'],
84
- })
85
- ```
86
-
87
- ## 获取配置信息
88
-
89
- ### 1. 创建 KOOK 机器人
90
-
91
- 1. 访问 [KOOK 开发者平台](https://developer.kookapp.cn/)
92
- 2. 登录并创建应用
93
- 3. 在应用设置中获取 **Bot Token**
94
-
95
- ### 2. 配置机器人
96
-
97
- 在应用设置中:
98
- - 获取 **Bot Token**(必需)
99
- - 将机器人邀请到需要的服务器并配置频道权限
100
-
101
- ### 3. 邀请机器人
102
-
103
- - 在应用详情页获取邀请链接
104
- - 将机器人邀请到需要的服务器
105
- - 确保机器人有相应的权限
106
-
107
- ## 使用示例
108
-
109
- ### 基础消息处理
110
-
111
- ```typescript
112
- import { usePlugin, MessageCommand } from 'zhin.js'
113
-
114
- const { addCommand } = usePlugin()
115
-
116
- addCommand(new MessageCommand('hello <name:text>')
117
- .action(async (message, result) => {
118
- return `你好,${result.params.name}!`
119
- })
120
- )
121
- ```
122
-
123
- ### 频道消息
124
-
125
- ```typescript
126
- import { onMessage } from 'zhin.js'
127
-
128
- onMessage(async (message) => {
129
- if (message.$channel.type === 'channel') {
130
- console.log(`频道消息:${message.$raw}`)
131
- }
132
- })
133
- ```
134
-
135
- ### 私聊消息
136
-
137
- ```typescript
138
- import { onPrivateMessage } from 'zhin.js'
139
-
140
- onPrivateMessage(async (message) => {
141
- await message.$reply('收到你的私信了!')
142
- })
143
- ```
144
-
145
- ### 系统通知(notice)
146
-
147
- KOOK 的入群、退群、消息删除、表情回应、频道变更等 **系统消息**(`type: 255`)由适配器在 gateway 层拦截并转为标准 `Notice`,与 ICQQ / NapCat 一样可通过插件生命周期订阅:
148
-
149
- ```typescript
150
- import { usePlugin } from 'zhin.js'
151
-
152
- const plugin = usePlugin()
153
-
154
- // 入群欢迎(与 group-suite 等插件兼容)
155
- plugin.on('notice.receive', async (notice) => {
156
- if (notice.$adapter !== 'kook') return
157
- if (notice.$type === 'group_member_increase') {
158
- console.log('新成员', notice.$target?.id, '加入服务器', notice.$channel.id)
159
- }
160
- })
161
- ```
162
-
163
- 常见映射(`extra.type` → `$type`):
164
-
165
- | KOOK `extra.type` | Zhin `$type` |
166
- |---|---|
167
- | `joined_guild` | `group_member_increase` |
168
- | `exited_guild` | `group_member_decrease` |
169
- | `deleted_message` | `group_recall` |
170
- | `deleted_private_message` | `friend_recall` |
171
- | `added_reaction` / `deleted_reaction` | `group_emoji_reaction` |
172
- | 其它系统事件 | 保留原始类型名(如 `updated_channel`) |
173
-
174
- 需要原始 gateway 载荷时,可监听适配器上的 `kook.gateway`(含 `post_type` / `notice_type` 增强字段):
175
-
176
- ```typescript
177
- import { usePlugin } from 'zhin.js'
178
-
179
- usePlugin().useContext('kook', (kook) => {
180
- kook.on('kook.gateway', (raw) => {
181
- if (raw.post_type === 'notice') {
182
- console.log('KOOK 系统事件', raw.notice_type, raw.extra?.body)
183
- }
184
- })
185
- })
186
- ```
187
-
188
- ### Markdown 消息
189
-
190
- ```typescript
191
- addCommand(new MessageCommand('md')
192
- .action(async (message) => {
193
- return [
194
- {
195
- type: 'text',
196
- data: {
197
- text: '**这是粗体** *这是斜体*\n[链接](https://kookapp.cn)'
198
- }
199
- }
200
- ]
201
- })
202
- )
203
- ```
204
- ### Card 消息 (卡片消息)
205
-
206
- ```typescript
207
- addCommand(new MessageCommand('card')
208
- .action(async (message) => {
209
- logger.info(message);
210
- if (message.$adapter !== 'kook') {
211
- return "暂未适配平台!";
212
- } else {
213
- const cardMessage = [{
214
- type: 'card',
215
- theme: "secondary",
216
- size: "lg",
217
- modules: [
218
- msgMod.section(
219
- element.markdown("(font) 卡片信息(font)[purple](font) Card信息(font)[warning]")
220
- ),
221
- msgMod.container(
222
- [
223
- element.image('https://api.owii.cn/gif/cache/2026-01-03_07-17-15.gif')
224
- ]
225
- )
226
- ]
227
- }];
228
- return cardMessage;
229
- }
230
- return `当前平台:${message.$adapter}`;
231
- })
232
- )
233
- ```
234
-
235
- ## 消息类型支持
236
-
237
- ### 接收消息类型
238
-
239
- - ✅ 文本消息
240
- - ✅ 图片消息
241
- - ✅ 视频消息
242
- - ✅ 文件消息
243
- - ✅ Markdown 消息
244
- - ✅ KMarkdown 消息
245
- - ✅ 卡片消息
246
-
247
- ### 发送消息类型
248
-
249
- - ✅ 文本消息
250
- - ✅ 图片消息
251
- - ✅ 视频消息
252
- - ✅ 文件消息
253
- - ✅ Markdown 消息
254
- - ✅ 卡片消息
255
-
256
- ## API 方法
257
-
258
- ```typescript
259
- const endpoint = app.adapters.get('kook')?.endpoints.get('my-kook-bot')
260
-
261
- // 发送频道消息
262
- await endpoint.sendChannelMsg(channelId, '消息内容')
263
-
264
- // 发送私聊消息
265
- await endpoint.sendPrivateMsg(userId, '消息内容')
266
-
267
- // 统一发送(出站返回带路由的 msg ref,见「消息 ID 与路由」)
268
- const msgRef = await endpoint.$sendMessage({
269
- context: 'kook',
270
- bot: 'my-kook-bot',
271
- type: 'group', // 或 'private'
272
- id: channelOrUserId,
273
- content: [{ type: 'text', data: { text: '你好' } }],
274
- })
275
-
276
- // 撤回:支持出站 ref,或入站 plain msg_id + 路由由适配器推断
277
- await endpoint.$recallMessage(msgRef)
278
- await endpoint.$recallMessage(message.$id, { route: 'direct' }) // 入站私聊
279
-
280
- // Typing Indicator:在用户消息上贴/删表情回应
281
- const reactionId = await endpoint.$addReaction(message.$id, '⏳', {
282
- sceneType: message.$channel.type === 'private' ? 'private' : 'channel',
283
- })
284
- await endpoint.$removeReaction(message.$id, reactionId)
285
- ```
286
-
287
- ## 🔧 频道管理工具(AI 可调用)
288
-
289
-
290
- 适配器自动注册了一系列频道管理工具,这些工具可以被 AI 调用,实现智能化的频道管理。
291
-
292
- ### 权限要求
293
-
294
- | 工具 | 所需权限 | 说明 |
295
- |------|----------|------|
296
- | `kook_kick_user` | 管理员 | 踢出用户 |
297
- | `kook_ban_user` | 管理员 | 将用户加入黑名单 |
298
- | `kook_unban_user` | 管理员 | 解除用户封禁 |
299
- | `kook_grant_role` | 管理员 | 授予用户角色 |
300
- | `kook_revoke_role` | 管理员 | 撤销用户角色 |
301
- | `kook_set_nickname` | 管理员 | 设置用户昵称 |
302
- | `kook_list_roles` | 普通用户 | 查看角色列表 |
303
- | `kook_create_role` | 服务器主人 | 创建新角色 |
304
- | `kook_delete_role` | 服务器主人 | 删除角色 |
305
- | `kook_list_members` | 普通用户 | 查看成员列表 |
306
-
307
- ### 使用示例
308
-
309
- #### 通过 AI 对话管理频道
310
-
311
- ```
312
- 用户(服务器主人):把 @小明 踢出服务器
313
- AI:已将用户 小明 踢出服务器。
314
-
315
- 用户(管理员):把 @捣蛋鬼 禁言,他总是发广告
316
- AI:已将用户 捣蛋鬼 加入黑名单,原因:发布广告。
317
-
318
- 用户:查看服务器角色列表
319
- AI:当前服务器有以下角色:
320
- 1. 管理员 (ID: 123)
321
- 2. 活跃成员 (ID: 456)
322
- 3. 新人 (ID: 789)
323
- ```
324
-
325
- #### 编程调用
326
-
327
- ```typescript
328
- // 获取 KOOK Endpoint 实例
329
- const kookAdapter = app.adapters.get('kook')
330
- const endpoint = kookAdapter?.endpoints.get('my-kook-bot')
331
-
332
- // 踢出用户
333
- await endpoint.kickUser(guildId, userId)
334
-
335
- // 加入黑名单(封禁)
336
- await endpoint.addToBlacklist(guildId, userId, '违规发言', 7) // 删除7天内消息
337
-
338
- // 解除封禁
339
- await endpoint.removeFromBlacklist(guildId, userId)
340
-
341
- // 授予角色
342
- await endpoint.grantRole(guildId, userId, roleId)
343
-
344
- // 撤销角色
345
- await endpoint.revokeRole(guildId, userId, roleId)
346
-
347
- // 设置昵称
348
- await endpoint.setNickname(guildId, userId, '新昵称')
349
-
350
- // 获取角色列表
351
- const roles = await endpoint.getRoleList(guildId)
352
-
353
- // 创建角色
354
- const newRole = await endpoint.createRole(guildId, '新角色')
355
-
356
- // 删除角色
357
- await endpoint.deleteRole(guildId, roleId)
358
-
359
- // 获取成员列表
360
- const members = await endpoint.getGuildMembers(guildId)
361
- ```
362
-
363
- ### 发送者权限信息
364
-
365
- 消息中的 `$sender` 现在包含 KOOK 特有的权限信息:
366
-
367
- ```typescript
368
- interface KookSenderInfo {
369
- id: string;
370
- name: string;
371
- permission?: KookPermission; // 1=普通, 2=管理员, 4=服务器主人, 5=频道管理员
372
- roles?: number[]; // 用户角色ID列表
373
- isGuildOwner?: boolean; // 是否为服务器主人
374
- isAdmin?: boolean; // 是否为管理员
375
- }
376
- ```
377
-
378
- #### 在插件中检查权限
379
-
380
- ```typescript
381
- onMessage(async (message) => {
382
- const sender = message.$sender as KookSenderInfo;
383
-
384
- if (sender.isGuildOwner) {
385
- console.log('这是服务器主人的消息');
386
- }
387
-
388
- if (sender.isAdmin) {
389
- console.log('这是管理员的消息');
390
- }
391
- })
48
+ kook:
49
+ # connection: websocket # 默认
50
+ endpoints:
51
+ - name: my-kook-bot
52
+ token: ${KOOK_TOKEN}
392
53
  ```
393
54
 
394
- ## 连接说明
395
-
396
- 本适配器固定使用 **WebSocket** 与 KOOK 通信(由 `kook-client` 实现),无需配置 Webhook 回调地址。
397
-
398
- ## 消息 ID 与路由
399
-
400
- KOOK 频道与私聊的删除 / 表情 API 路径不同(`/v3/message/*` vs `/v3/direct-message/*`)。适配器在出站返回值与 reaction 句柄里编码路由,避免撤回或删表情时误打另一套 API。
401
-
402
- | 场景 | ID 形式 | 说明 |
403
- |------|---------|------|
404
- | 入站消息 | plain `msg_id` | `message.$id` 为 KOOK 原始 UUID;`message.$recall()` 会按频道/私聊自动选路由 |
405
- | 出站 `$sendMessage` 返回值 | `kook:channel:{msgId}` 或 `kook:direct:{msgId}` | 供 `$recallMessage`、Typing Indicator message 模式删除 |
406
- | 出站 `$addReaction` 返回值 | `reaction:channel:{msgId}:{emoji}` 或 `reaction:direct:...` | 供 `$removeReaction` 精确删表情 |
407
-
408
- 实现细节见 `plugins/adapters/kook/src/kook-msg-route.ts`。
409
-
410
- ### @ 提及与 AI 触发
411
-
412
- 入站 `(met)userId(met)` / `at` 段会规范为带 `user_id` 的 `at` 元素;连接后日志会输出 `platform_user_id`,用于配置 AI 的 `@bot` 触发匹配。
413
-
414
- ## 注意事项
415
-
416
- ### 权限配置
417
-
418
- 确保机器人有以下权限:
419
- - 查看频道
420
- - 发送消息
421
- - 管理消息(如需撤回)
422
- - 查看服务器成员列表
423
-
424
- ### 频率限制
425
-
426
- KOOK 有消息发送频率限制:
427
- - 每秒最多 5 条消息
428
- - 建议添加发送队列管理
55
+ 根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-kook`(`instanceKey: kook`)。
429
56
 
430
- ## 故障排查
57
+ ## 环境变量
431
58
 
432
- ### 机器人无法收到消息
433
-
434
- 1. Token 是否正确
435
- 2. 机器人是否已加入服务器
436
- 3. 机器人是否有查看频道权限
437
- 4. WebSocket 连接是否正常(查看启动日志)
438
-
439
- ### 发送失败或频率限制
440
-
441
- KOOK 有发送频率限制(约每秒 5 条);建议队列化发送并检查 API 错误码。
59
+ | 变量 | 说明 |
60
+ |------|------|
61
+ | `KOOK_TOKEN` / `KOOK_BOT_TOKEN` | Bot Token |
62
+ | `KOOK_BOT_NAME` | 可选,默认 endpoint 名 |
63
+ | `KOOK_VERIFY_TOKEN` | Webhook 模式 verify token |
64
+ | `KOOK_ENCRYPT_KEY` | 可选,Webhook 消息加密密钥 |
65
+ | `KOOK_WEBHOOK_PATH` | 可选,默认 `/kook/webhook` |
442
66
 
443
- ### 如何发送卡片消息
67
+ ## Webhook
444
68
 
445
- 使用 KOOK 卡片消息格式:
69
+ KOOK 开发者后台选择 **WebHook** 连接模式,Callback URL 指向 Host 暴露的公网地址(建议在 URL 加 `?compress=0` 便于调试)。
446
70
 
447
- ```typescript
448
- await endpoint.sendChannelMsg(channelId, [
449
- {
450
- type: 'card',
451
- data: {
452
- // 卡片消息内容
453
- }
454
- }
455
- ])
71
+ ```yaml
72
+ plugins:
73
+ kook:
74
+ connection: webhook
75
+ webhookPath: /kook/webhook
76
+ endpoints:
77
+ - name: my-kook-bot
78
+ token: ${KOOK_TOKEN}
79
+ verify_token: ${KOOK_VERIFY_TOKEN}
80
+ # encrypt_key: ${KOOK_ENCRYPT_KEY} # 启用消息加密时必填
456
81
  ```
457
82
 
458
- ## 文档链接
459
-
460
- - [KOOK 适配器文档](https://zhin.js.org/adapters/kook)
461
- - [适配器概览](https://zhin.js.org/essentials/adapters)
462
- - [KOOK 开发者平台](https://developer.kookapp.cn/)
463
- - [KOOK 开发文档](https://developer.kookapp.cn/doc/)
464
- - [kook-client](https://github.com/zhinjs/kook-client)
465
-
466
- ## full-bot L4 参考
83
+ Host 需注入 `httpHostToken`。Challenge(`type: 255`)会校验 `verify_token` 并回显 `challenge`;普通事件经 `gateway.receive` 入站,出站仍走 KOOK HTTP API。
467
84
 
468
- [`examples/full-bot`](../../../examples/full-bot/) 默认加载本适配器(`endpoints` 段需填写 `KOOK_TOKEN` 后取消注释)。
85
+ ## AI 工具(Skill)
469
86
 
470
- - 入站 `ZhinAgent` → 出站走 `Adapter.sendMessage` 统一链路
471
- - 契约测试:`plugins/adapters/kook/tests/l4-contract.test.ts` + `integration.test.ts`
472
- - CI:`L4_SKIP_PLATFORM=1` 跳过实机;本地验证配置 `KOOK_TOKEN` 后可跑 optional smoke
473
-
474
- 详见 [full-bot ACCEPTANCE.md](../../../examples/full-bot/ACCEPTANCE.md)。
87
+ | 类别 | 路径 |
88
+ |------|------|
89
+ | Permit 词汇 | `agent/PERMITS.md` |
90
+ | 平台工具 | `agent/tools/`(角色、黑名单等) |
91
+ | 技能说明 | `agent/skills/kook.md` |
475
92
 
476
- ## 依赖项
93
+ ## 平台权限(platform permit)
477
94
 
478
- - `kook-client` - KOOK 客户端库
479
- - `zhin.js` - Zhin 核心框架
95
+ platform permit checker 由 `plugin.ts` generation 生命周期注册;CapabilityIngress 与 ToolSystem 统一经 Core `canAccessTool()` 消费工具的 platform permit 声明。
480
96
 
481
- ## 开发
97
+ ## 迁移后出站能力变化
482
98
 
483
- ```bash
484
- pnpm build # 构建
485
- pnpm clean # 清理构建文件
486
- ```
99
+ 迁移到 Plugin Runtime 后,出站统一经 `messageGatewayToken` 渲染为文本后发送(`sendChannelMsg` / `sendPrivateMsg`,KMarkdown 文本)。旧 Adapter 的富媒体出站能力(图片 / 卡片消息 / 附件等多模态 segment 直发)暂未迁移,当前出站等价于纯文本(KMarkdown)。如需发送卡片或附件,可直接使用 endpoint 上的 KOOK OpenAPI 封装(`getRoleList` 等同款 client)作为逃生舱。
487
100
 
488
101
  ## 许可证
489
102
 
490
103
  MIT License
491
-
492
- ## 贡献
493
-
494
- 欢迎提交 Issue 和 Pull Request!
495
-
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Convention entry: discover `adapters/kook.ts` → defineAdapter.
3
+ * Implementation lives under `src/` (endpoint / webhook / ws / protocol).
4
+ */
5
+ import { defineAdapter } from '@zhin.js/adapter';
6
+ import { messageGatewayToken } from '@zhin.js/core/runtime';
7
+ import { httpHostToken } from '@zhin.js/host-http';
8
+ import {
9
+ KookWebhookEndpoint,
10
+ KookWebsocketEndpoint,
11
+ } from '../src/endpoint.js';
12
+ import {
13
+ resolveKookConfig,
14
+ type KookAdapterConfig,
15
+ } from '../src/protocol.js';
16
+
17
+ export {
18
+ KookWebhookEndpoint,
19
+ KookWebsocketEndpoint,
20
+ } from '../src/endpoint.js';
21
+ export type {
22
+ KookEndpointOptions,
23
+ KookWebhookEndpointOptions,
24
+ } from '../src/endpoint.js';
25
+ export type { CreateKookClient, KookClientTransport } from '../src/ws.js';
26
+
27
+ export default defineAdapter<KookAdapterConfig>({
28
+ capabilities: ['inbound', 'outbound'],
29
+ create(context) {
30
+ const config = resolveKookConfig(context.config);
31
+ const gateway = context.use(messageGatewayToken);
32
+ if (config.connection === 'webhook') {
33
+ return new KookWebhookEndpoint({
34
+ id: context.id,
35
+ gateway,
36
+ http: context.use(httpHostToken),
37
+ config,
38
+ });
39
+ }
40
+ return new KookWebsocketEndpoint({
41
+ id: context.id,
42
+ gateway,
43
+ config,
44
+ });
45
+ },
46
+ });
@@ -1,9 +1,9 @@
1
- import { defineTool } from '@zhin.js/agent/tools';
1
+ import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
4
  import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
5
 
6
- export default defineTool<{ endpoint_id: string; guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }>({
6
+ export default defineAgentTool<{ endpoint_id: string; guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }>({
7
7
  description: 'KOOK 服务器黑名单管理:添加/移除',
8
8
  inputSchema: z.object({
9
9
  endpoint_id: z.string().describe('Endpoint 名称'),