@zhin.js/adapter-milky 1.0.0 → 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 (100) hide show
  1. package/CHANGELOG.md +962 -0
  2. package/README.md +58 -117
  3. package/adapters/milky.js +51 -0
  4. package/adapters/milky.ts +74 -0
  5. package/agent/PERMITS.md +14 -0
  6. package/{skills/milky/SKILL.md → agent/skills/milky.md} +1 -1
  7. package/commands/endpoint/add/[id].js +3 -0
  8. package/commands/endpoint/add/[id].ts +3 -0
  9. package/commands/endpoint/list.js +3 -0
  10. package/commands/endpoint/list.ts +3 -0
  11. package/commands/endpoint/remove/[id].js +3 -0
  12. package/commands/endpoint/remove/[id].ts +3 -0
  13. package/lib/client.d.ts +21 -0
  14. package/lib/client.js +33 -0
  15. package/lib/endpoint-management.d.ts +17 -0
  16. package/lib/endpoint-management.js +47 -0
  17. package/lib/endpoint.d.ts +7 -0
  18. package/lib/endpoint.js +6 -0
  19. package/lib/index.d.ts +6 -20
  20. package/lib/index.js +4 -33
  21. package/lib/milky-auth.d.ts +2 -0
  22. package/lib/milky-auth.js +16 -0
  23. package/lib/milky-endpoint-commands.d.ts +1 -0
  24. package/lib/milky-endpoint-commands.js +18 -0
  25. package/lib/milky-runtime-state.d.ts +1 -0
  26. package/lib/milky-runtime-state.js +6 -0
  27. package/lib/protocol.d.ts +174 -0
  28. package/lib/protocol.js +494 -0
  29. package/lib/sse-client.d.ts +20 -0
  30. package/lib/sse-client.js +85 -0
  31. package/lib/sse-endpoint.d.ts +32 -0
  32. package/lib/sse-endpoint.js +207 -0
  33. package/lib/webhook-endpoint.d.ts +22 -0
  34. package/lib/webhook-endpoint.js +149 -0
  35. package/lib/ws-endpoint.d.ts +23 -0
  36. package/lib/ws-endpoint.js +233 -0
  37. package/lib/ws-types.d.ts +11 -0
  38. package/lib/ws-types.js +1 -0
  39. package/lib/wss-endpoint.d.ts +25 -0
  40. package/lib/wss-endpoint.js +184 -0
  41. package/package.json +73 -19
  42. package/plugin.js +14 -0
  43. package/schema.json +100 -0
  44. package/src/client.ts +80 -0
  45. package/src/endpoint-management.ts +74 -0
  46. package/src/endpoint.ts +26 -0
  47. package/src/index.ts +63 -45
  48. package/src/milky-auth.ts +14 -0
  49. package/src/milky-endpoint-commands.ts +19 -0
  50. package/src/milky-runtime-state.ts +7 -0
  51. package/src/protocol.ts +647 -0
  52. package/src/sse-client.ts +106 -0
  53. package/src/sse-endpoint.ts +258 -0
  54. package/src/webhook-endpoint.ts +196 -0
  55. package/src/ws-endpoint.ts +291 -0
  56. package/src/ws-types.ts +12 -0
  57. package/src/wss-endpoint.ts +228 -0
  58. package/lib/adapter.d.ts +0 -28
  59. package/lib/adapter.d.ts.map +0 -1
  60. package/lib/adapter.js +0 -90
  61. package/lib/adapter.js.map +0 -1
  62. package/lib/api.d.ts +0 -10
  63. package/lib/api.d.ts.map +0 -1
  64. package/lib/api.js +0 -48
  65. package/lib/api.js.map +0 -1
  66. package/lib/bot-sse.d.ts +0 -31
  67. package/lib/bot-sse.d.ts.map +0 -1
  68. package/lib/bot-sse.js +0 -195
  69. package/lib/bot-sse.js.map +0 -1
  70. package/lib/bot-webhook.d.ts +0 -34
  71. package/lib/bot-webhook.d.ts.map +0 -1
  72. package/lib/bot-webhook.js +0 -187
  73. package/lib/bot-webhook.js.map +0 -1
  74. package/lib/bot-ws.d.ts +0 -35
  75. package/lib/bot-ws.d.ts.map +0 -1
  76. package/lib/bot-ws.js +0 -262
  77. package/lib/bot-ws.js.map +0 -1
  78. package/lib/bot-wss.d.ts +0 -34
  79. package/lib/bot-wss.d.ts.map +0 -1
  80. package/lib/bot-wss.js +0 -225
  81. package/lib/bot-wss.js.map +0 -1
  82. package/lib/index.d.ts.map +0 -1
  83. package/lib/index.js.map +0 -1
  84. package/lib/types.d.ts +0 -75
  85. package/lib/types.d.ts.map +0 -1
  86. package/lib/types.js +0 -5
  87. package/lib/types.js.map +0 -1
  88. package/lib/utils.d.ts +0 -35
  89. package/lib/utils.d.ts.map +0 -1
  90. package/lib/utils.js +0 -157
  91. package/lib/utils.js.map +0 -1
  92. package/plugin.yml +0 -3
  93. package/src/adapter.ts +0 -101
  94. package/src/api.ts +0 -63
  95. package/src/bot-sse.ts +0 -228
  96. package/src/bot-webhook.ts +0 -221
  97. package/src/bot-ws.ts +0 -296
  98. package/src/bot-wss.ts +0 -268
  99. package/src/types.ts +0 -73
  100. package/src/utils.ts +0 -174
package/README.md CHANGED
@@ -1,158 +1,99 @@
1
1
  # @zhin.js/adapter-milky
2
2
 
3
- Zhin.js [Milky](https://milky.ntqqrev.org/) 协议适配器,**一个适配器**支持 WebSocket 正向/反向、SSE、Webhook 四种连接方式,由配置项 `connection` 区分;支持 HTTP API 调用与 `access_token` 鉴权。
3
+ Zhin.js [Milky](https://milky.ntqqrev.org/) 协议适配器(Plugin Runtime)。默认 **正向 WebSocket 客户端**(`connection: ws`);亦支持 **Webhook**、**反向 WS**(经 `httpHostToken`)与 **SSE**(HTTP GET `/event`,fetch 解析 `text/event-stream`)。
4
4
 
5
5
  ## 功能特性
6
6
 
7
- - 🔌 Milky 协议兼容([通信说明](https://milky.ntqqrev.org/guide/communication))
8
- - 📦 **单一适配器**:`context: milky`,通过 `connection` 选择连接方式
9
- - 🌐 **WebSocket 正向**(`connection: ws`):应用连协议端 `ws(s)://baseUrl/event`
10
- - 📡 **SSE**(`connection: sse`):应用 GET 协议端 `/event`
11
- - 📮 **Webhook**(`connection: webhook`):应用提供 POST 端点收事件
12
- - 🔄 **WebSocket 反向**(`connection: wss`):应用开 WS 服务端,协议端来连
13
- - 🔐 `access_token` 鉴权(Header 或 query)
14
- - 📨 群聊 / 私聊消息收发与消息段映射
15
- - 🛠️ HTTP API 封装,供发消息、撤回、群管等复用
7
+ - [Milky 协议](https://milky.ntqqrev.org/guide/communication) 兼容(事件 + HTTP API
8
+ - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
9
+ - **正向 WebSocket**(`connection: ws`):应用连协议端 `ws(s)://baseUrl/event`
10
+ - `access_token` 鉴权(Bearer + query)
11
+ - 入站经 `Endpoint.emit(...)`;出站 `send({ conversation, payload })` → HTTP `send_*_message`
16
12
 
17
13
  ## 安装
18
14
 
19
15
  ```bash
20
- pnpm add @zhin.js/adapter-milky ws eventsource
16
+ pnpm add @zhin.js/adapter-milky
21
17
  ```
22
18
 
23
- 适配器依赖 `@zhin.js/host-router` 提供的 `router` 才能注册(Webhook/反向 WS 需挂路由),请同时启用 HTTP 服务:
19
+ ## Plugin Runtime
24
20
 
25
- ```bash
26
- pnpm add @zhin.js/host-router
27
- ```
21
+ - `@zhin.js/adapter` — 约定式 `adapters/milky.ts`(`defineAdapter`)
22
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
23
+ - `zhin.js` — `plugin.ts`(`definePlugin`)
24
+ - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
25
+
26
+ 入站:`gateway.receive({ conversation: ConversationRef(kind: "private"|"group", id), message, content, sender, metadata })`
27
+ 出站:`send({ conversation, payload })` → HTTP `send_private_message` / `send_group_message`(payload 已由 gateway/core 渲染;无 segment-mapper)
28
+
29
+ 每个 Endpoint 的 `$client` 是 `@imhelper/milky-v1` 的 `MilkyV1Client`。插件可直接调用
30
+ `$client.call()`、`getGroupList()` 等公开能力;`defineHandler({ adapter: 'milky', event: ... })`
31
+ 使用 imhelper 的精确事件名与 payload 类型。HTTP、纯事件 WS/WSS 和 `ingest()` 都汇入同一个
32
+ Client 事件流,Endpoint 仍独占账号连接、鉴权、重连和心跳。
28
33
 
29
- ## 配置
34
+ ## 前置条件
30
35
 
31
- 所有 Bot 使用 **同一 context:`milky`**,通过 **`connection`** 区分连接方式。
36
+ 1. 启动兼容 Milky 的实现,并记录 HTTP API 与事件连接地址。
37
+ 2. 正向 WS/SSE 需 Zhin 主动可达实现端;Webhook/反向 WS 需实现端可达 Zhin HTTP Host。
38
+ 3. 两端配置相同的 `access_token`,生产环境不要暴露无鉴权接口。
32
39
 
33
- ### WebSocket 正向
40
+ ## 最小配置
34
41
 
35
42
  ```yaml
43
+ # zhin.config.yml(Plugin Runtime)
36
44
  plugins:
37
- - "@zhin.js/host-router"
38
- - "@zhin.js/adapter-milky"
39
-
40
- bots:
41
- - context: milky
45
+ milky:
42
46
  connection: ws
43
- name: milky-bot
44
- baseUrl: "http://127.0.0.1:8080"
45
- access_token: "${MILKY_ACCESS_TOKEN}"
46
47
  reconnect_interval: 5000
47
48
  heartbeat_interval: 30000
49
+ endpoints:
50
+ - name: milky-bot
51
+ baseUrl: "http://127.0.0.1:8080"
52
+ access_token: "${MILKY_ACCESS_TOKEN}"
48
53
  ```
49
54
 
50
- ### SSE
51
-
52
- ```yaml
53
- bots:
54
- - context: milky
55
- connection: sse
56
- name: milky-sse-bot
57
- baseUrl: "http://127.0.0.1:8080"
58
- access_token: "${MILKY_ACCESS_TOKEN}"
59
- ```
55
+ 根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-milky`(`instanceKey: milky`)。
60
56
 
61
- ### Webhook
57
+ ## 连接方式
62
58
 
63
- ```yaml
64
- bots:
65
- - context: milky
66
- connection: webhook
67
- name: milky-webhook-bot
68
- baseUrl: "http://协议端地址"
69
- path: "/milky/webhook" # 应用接收事件的 POST 路径
70
- access_token: "${MILKY_ACCESS_TOKEN}"
71
- ```
72
-
73
- ### WebSocket 反向
74
-
75
- ```yaml
76
- bots:
77
- - context: milky
78
- connection: wss
79
- name: milky-wss-bot
80
- baseUrl: "http://协议端地址"
81
- path: "/milky/event" # 应用 WS 服务端路径
82
- access_token: "${MILKY_ACCESS_TOKEN}"
83
- heartbeat_interval: 30000
84
- ```
59
+ | connection | 状态 |
60
+ |------------|------|
61
+ | `ws` | 已实现(推荐) |
62
+ | `sse` | HTTP GET `/event`(`Accept: text/event-stream`) |
63
+ | `webhook` | 已实现:POST 入站 + baseUrl HTTP API 出站 |
64
+ | `wss` | 已实现:反向 WS(httpHostToken) |
85
65
 
86
66
  ## 鉴权
87
67
 
88
- 所有连接方式统一支持:
68
+ - **Bearer**:`Authorization: Bearer <access_token>`
69
+ - 正向 WS 在 Upgrade 时附带请求头,并在 URL query 写入 `access_token`
70
+ - HTTP API 同样使用 Header / query 鉴权
89
71
 
90
- - **Header**:`Authorization: Bearer {access_token}`
91
- - **Query**:`access_token=xxx`
72
+ ## 消息 ID
92
73
 
93
- 建议配置 `access_token`,并与协议端一致。
74
+ `{message_scene}:{peer_id}:{message_seq}`(如 `group:123456:10001`)。
94
75
 
95
- ## 连接方式对比
76
+ ## AI 工具
96
77
 
97
- | connection | 说明 |
98
- |------------|--------------------------------|
99
- | `ws` | 应用主动连协议端 `/event` |
100
- | `sse` | 应用 GET `/event` 拉取事件流 |
101
- | `webhook` | 协议端 POST 到应用配置的 path |
102
- | `wss` | 协议端连应用提供的 WS path |
78
+ | 类别 | 路径 |
79
+ |------|------|
80
+ | Permit 词汇 | `agent/PERMITS.md` |
81
+ | 技能说明 | `agent/skills/milky.md` |
103
82
 
104
- ## 使用示例
105
-
106
- ### 消息处理
107
-
108
- ```typescript
109
- import { addCommand, MessageCommand } from 'zhin.js'
110
-
111
- addCommand(new MessageCommand('hello <name:text>')
112
- .action(async (message, result) => {
113
- return `你好,${result.params.name}!`
114
- })
115
- )
116
- ```
117
-
118
- ### 发送消息段
119
-
120
- ```typescript
121
- addCommand(new MessageCommand('pic')
122
- .action(async () => {
123
- return [
124
- { type: 'text', data: { text: '图片:' } },
125
- { type: 'image', data: { url: 'https://example.com/img.png' } }
126
- ]
127
- })
128
- )
129
- ```
130
-
131
- 发消息、撤回、群管等通过适配器封装的 HTTP API 完成。群管能力通过 `IGroupManagement` 自动注册为工具,详见 [工具与技能](/advanced/tools-skills)。
132
-
133
- ## 消息 ID 格式
134
-
135
- `{message_scene}:{peer_id}:{message_seq}`(如 `group:123456:10001`)。撤回时使用该 ID。
136
-
137
- ## 协议与 API 参考
83
+ ## 文档链接
138
84
 
139
85
  - [Milky 快速开始](https://milky.ntqqrev.org/)
140
86
  - [Milky 通信](https://milky.ntqqrev.org/guide/communication)
141
- - [事件结构](https://milky.ntqqrev.org/struct/Event)、[接收消息](https://milky.ntqqrev.org/struct/IncomingMessage)、[消息 API](https://milky.ntqqrev.org/api/message)、[群聊 API](https://milky.ntqqrev.org/api/group)
142
-
143
- ## 依赖项
87
+ - [适配器概览](https://zhin.js.org/essentials/adapters)
144
88
 
145
- - `ws` - WebSocket 客户端/服务端
146
- - `eventsource` - SSE 客户端
147
- - `zhin.js` - Zhin 核心
148
- - `@zhin.js/host-router` - 提供 router,适配器注册依赖
89
+ ## 故障排查
149
90
 
150
- ## 开发
151
-
152
- ```bash
153
- pnpm build # 构建
154
- pnpm clean # 清理
155
- ```
91
+ | 现象 | 排查 |
92
+ | --- | --- |
93
+ | WS/SSE 无事件 | 核对 `baseUrl`、连接模式与实现端事件服务 |
94
+ | 401 或握手失败 | 确认 Bearer/query 中的 `access_token` 与实现端一致 |
95
+ | Webhook/WSS 无法连接 | 检查 HTTP Host、网络可达性与回调路径 |
96
+ | 能收不能发 | 检查 HTTP API 与发送动作支持情况 |
156
97
 
157
98
  ## 许可证
158
99
 
@@ -0,0 +1,51 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ /**
3
+ * Convention entry: discover `adapters/milky.ts` → defineAdapter.
4
+ */
5
+ import { defineAdapter } from 'zhin.js/adapter';
6
+ import { httpHostToken } from '@zhin.js/host-http';
7
+ import { MilkySseEndpoint, MilkyWebhookEndpoint, MilkyWssEndpoint, MilkyWsEndpoint, } from "../lib/endpoint.js";
8
+ import { resolveMilkyConfig, } from "../lib/protocol.js";
9
+ import { milkyRuntimeStateToken } from "../lib/milky-runtime-state.js";
10
+ export { MilkySseEndpoint, MilkyWebhookEndpoint, MilkyWssEndpoint, MilkyWsEndpoint, } from "../lib/endpoint.js";
11
+ export default defineAdapter({
12
+ capabilities: ['inbound', 'outbound'],
13
+ operations: ['recall'],
14
+ // Milky 协议资源 uri 消费 http(s):// 与 base64:// 形式;无卡片交互面,交互段降级纯文本。
15
+ segments: {
16
+ outboundMedia: ['url', 'base64'],
17
+ interactive: 'text',
18
+ },
19
+ create(context) {
20
+ const config = resolveMilkyConfig(context.config);
21
+ // 注册到插件运行时状态(milky.endpoint list 的"运行中"数据源)
22
+ context.use(milkyRuntimeStateToken).endpoints.set(config.id, {
23
+ id: config.id,
24
+ mode: config.connection,
25
+ });
26
+ if (config.connection === 'webhook') {
27
+ return new MilkyWebhookEndpoint({
28
+ id: context.id,
29
+ http: context.use(httpHostToken),
30
+ config,
31
+ });
32
+ }
33
+ if (config.connection === 'wss') {
34
+ return new MilkyWssEndpoint({
35
+ id: context.id,
36
+ http: context.use(httpHostToken),
37
+ config,
38
+ });
39
+ }
40
+ if (config.connection === 'sse') {
41
+ return new MilkySseEndpoint({
42
+ id: context.id,
43
+ config,
44
+ });
45
+ }
46
+ return new MilkyWsEndpoint({
47
+ id: context.id,
48
+ config,
49
+ });
50
+ },
51
+ });
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Convention entry: discover `adapters/milky.ts` → defineAdapter.
3
+ */
4
+ import { defineAdapter } from 'zhin.js/adapter';
5
+ import { httpHostToken } from '@zhin.js/host-http';
6
+ import {
7
+ MilkySseEndpoint,
8
+ MilkyWebhookEndpoint,
9
+ MilkyWssEndpoint,
10
+ MilkyWsEndpoint,
11
+ } from '../src/endpoint.js';
12
+ import {
13
+ resolveMilkyConfig,
14
+ type MilkyAdapterConfig,
15
+ } from '../src/protocol.js';
16
+ import { milkyRuntimeStateToken } from '../src/milky-runtime-state.js';
17
+
18
+ export {
19
+ MilkySseEndpoint,
20
+ MilkyWebhookEndpoint,
21
+ MilkyWssEndpoint,
22
+ MilkyWsEndpoint,
23
+ } from '../src/endpoint.js';
24
+ export type {
25
+ CreateMilkySseStream,
26
+ MilkySseEndpointOptions,
27
+ MilkyWebhookEndpointOptions,
28
+ MilkyWssEndpointOptions,
29
+ MilkyWsEndpointOptions,
30
+ MilkyWsCreateOptions,
31
+ MilkyWsSocket,
32
+ } from '../src/endpoint.js';
33
+
34
+ export default defineAdapter<MilkyAdapterConfig>({
35
+ capabilities: ['inbound', 'outbound'],
36
+ operations: ['recall'],
37
+ // Milky 协议资源 uri 消费 http(s):// 与 base64:// 形式;无卡片交互面,交互段降级纯文本。
38
+ segments: {
39
+ outboundMedia: ['url', 'base64'],
40
+ interactive: 'text',
41
+ },
42
+ create(context) {
43
+ const config = resolveMilkyConfig(context.config);
44
+ // 注册到插件运行时状态(milky.endpoint list 的"运行中"数据源)
45
+ context.use(milkyRuntimeStateToken).endpoints.set(config.id, {
46
+ id: config.id,
47
+ mode: config.connection,
48
+ });
49
+ if (config.connection === 'webhook') {
50
+ return new MilkyWebhookEndpoint({
51
+ id: context.id,
52
+ http: context.use(httpHostToken),
53
+ config,
54
+ });
55
+ }
56
+ if (config.connection === 'wss') {
57
+ return new MilkyWssEndpoint({
58
+ id: context.id,
59
+ http: context.use(httpHostToken),
60
+ config,
61
+ });
62
+ }
63
+ if (config.connection === 'sse') {
64
+ return new MilkySseEndpoint({
65
+ id: context.id,
66
+ config,
67
+ });
68
+ }
69
+ return new MilkyWsEndpoint({
70
+ id: context.id,
71
+ config,
72
+ });
73
+ },
74
+ });
@@ -0,0 +1,14 @@
1
+ # Milky Platform Permits(QQ 群)
2
+
3
+ ## 入站字段
4
+
5
+ `data.group_member.role` → `applyQqSenderRoleToMessageSender`。
6
+
7
+ ## Permit 词汇表
8
+
9
+ | `platform(milky,…)` | 含义 |
10
+ |---------------------|------|
11
+ | `scene_owner` | 群主 |
12
+ | `scene_admin` | 群管理员(含群主) |
13
+
14
+ 与 OneBot QQ 系相同,使用 core 默认 checker。
@@ -4,7 +4,7 @@ platforms:
4
4
  - milky
5
5
  description: >-
6
6
  Milky 协议群管理能力。当用户在 Milky 协议的 QQ 群中请求踢人、禁言、设管理员、
7
- 改名片/群名或查成员/群信息时使用。即使用户没有提到 Milky,只要 Bot 平台是
7
+ 改名片/群名或查成员/群信息时使用。即使用户没有提到 Milky,只要 Endpoint 平台是
8
8
  Milky 协议且涉及群管理操作,就应触发。仅有昵称时必须先查成员列表获取 user_id。
9
9
  keywords:
10
10
  - milky
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { milkyEndpointCommands } from "../../../lib/milky-endpoint-commands.js";
3
+ export default milkyEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ import { milkyEndpointCommands } from '../../../src/milky-endpoint-commands.js';
2
+
3
+ export default milkyEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { milkyEndpointCommands } from "../../lib/milky-endpoint-commands.js";
3
+ export default milkyEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ import { milkyEndpointCommands } from '../../src/milky-endpoint-commands.js';
2
+
3
+ export default milkyEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { milkyEndpointCommands } from "../../../lib/milky-endpoint-commands.js";
3
+ export default milkyEndpointCommands.remove;
@@ -0,0 +1,3 @@
1
+ import { milkyEndpointCommands } from '../../../src/milky-endpoint-commands.js';
2
+
3
+ export default milkyEndpointCommands.remove;
@@ -0,0 +1,21 @@
1
+ import { MilkyV1Client, type MilkyV1Event } from '@imhelper/milky-v1';
2
+ import { type EventMap, type ImHelperEventMap } from 'imhelper';
3
+ import { type ClientEventPayloads } from 'zhin.js/adapter';
4
+ import type { ResolvedMilkyConfig, callApi } from './protocol.js';
5
+ export { MilkyV1Client as MilkyClient } from '@imhelper/milky-v1';
6
+ type MilkyClientEvents = ImHelperEventMap<string, MilkyV1Event, EventMap<string>>;
7
+ export type MilkyClientEventMap = ClientEventPayloads<MilkyClientEvents>;
8
+ /** Construct the exact public imhelper Client without handing it transport ownership. */
9
+ export declare function createMilkyEndpointClient(config: ResolvedMilkyConfig, request: typeof callApi): MilkyV1Client;
10
+ /** Use the Client's complete protocol response while keeping Endpoint internals data-oriented. */
11
+ export declare function callMilkyClient<T = unknown>(client: MilkyV1Client, action: string, params?: Record<string, unknown>): Promise<T | undefined>;
12
+ export declare function forwardMilkyClientEvents(client: MilkyV1Client, receive: (name: string, payload: unknown) => void): () => void;
13
+ declare module '@zhin.js/feature-kit' {
14
+ interface AdapterClientRegistry {
15
+ readonly milky: {
16
+ readonly client: MilkyV1Client;
17
+ readonly events: MilkyClientEventMap;
18
+ };
19
+ }
20
+ }
21
+ export declare const milkyClient: import("@zhin.js/adapter").EndpointClientToken<MilkyV1Client, ClientEventPayloads<MilkyClientEvents>>;
package/lib/client.js ADDED
@@ -0,0 +1,33 @@
1
+ import { MilkyV1Client, } from '@imhelper/milky-v1';
2
+ import { EventFactory, } from 'imhelper';
3
+ import { defineEndpointClient, forwardEndpointClientEvents, } from 'zhin.js/adapter';
4
+ export { MilkyV1Client as MilkyClient } from '@imhelper/milky-v1';
5
+ /** Construct the exact public imhelper Client without handing it transport ownership. */
6
+ export function createMilkyEndpointClient(config, request) {
7
+ return new MilkyV1Client({
8
+ baseUrl: config.baseUrl,
9
+ selfId: config.id,
10
+ accessToken: config.access_token,
11
+ receiveMode: 'manual',
12
+ call: (action, params) => request({
13
+ baseUrl: config.baseUrl,
14
+ access_token: config.access_token,
15
+ }, action, params),
16
+ });
17
+ }
18
+ /** Use the Client's complete protocol response while keeping Endpoint internals data-oriented. */
19
+ export async function callMilkyClient(client, action, params) {
20
+ const response = await client.call(action, params);
21
+ if (response.status !== 'ok') {
22
+ throw new Error(`Milky API ${action}: retcode=${response.retcode}${response.message ? ` ${response.message}` : ''}`);
23
+ }
24
+ return response.data;
25
+ }
26
+ const milkyClientEventNames = Object.freeze([
27
+ ...EventFactory.getSupportedEventTypes(),
28
+ 'event',
29
+ ]);
30
+ export function forwardMilkyClientEvents(client, receive) {
31
+ return forwardEndpointClientEvents(client, milkyClientEventNames, receive);
32
+ }
33
+ export const milkyClient = defineEndpointClient('milky');
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Milky endpoint management 语义端口(Console 社交面 RPC 消费,见
3
+ * packages/im/adapter/src/endpoint-management.ts)。
4
+ *
5
+ * Milky 协议响应 data 为包裹对象:get_friend_list → {friends:[...]}、
6
+ * get_group_list → {groups:[...]}、get_group_member_list → {members:[...]}。
7
+ * 归一化取舍:
8
+ * - friend → {user_id:number, nickname, remark: remark ?? ''}
9
+ * - group → {group_id:number, name: group_name ?? name}
10
+ * - 群成员列表保持 Milky 原生形状,仅保证数组
11
+ */
12
+ import type { EndpointManagement } from 'zhin.js/adapter';
13
+ /** 管理面只依赖 endpoint 的 callApi(ws/wss/sse/webhook 四种传输各自实现)。 */
14
+ export interface MilkyManagementCaller {
15
+ callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
16
+ }
17
+ export declare function createMilkyEndpointManagement(endpoint: MilkyManagementCaller): EndpointManagement;
@@ -0,0 +1,47 @@
1
+ export function createMilkyEndpointManagement(endpoint) {
2
+ return Object.freeze({
3
+ async listFriends() {
4
+ const data = asRecord(await endpoint.callApi('get_friend_list'));
5
+ return toArray(data.friends).map((value) => {
6
+ const friend = asRecord(value);
7
+ return {
8
+ user_id: toNumberId(friend.user_id, 'user_id'),
9
+ nickname: String(friend.nickname ?? ''),
10
+ remark: String(friend.remark ?? ''),
11
+ };
12
+ });
13
+ },
14
+ async listGroups() {
15
+ const data = asRecord(await endpoint.callApi('get_group_list'));
16
+ return toArray(data.groups).map((value) => {
17
+ const group = asRecord(value);
18
+ return {
19
+ group_id: toNumberId(group.group_id, 'group_id'),
20
+ name: String(group.group_name ?? group.name ?? ''),
21
+ };
22
+ });
23
+ },
24
+ async listGroupMembers(groupId) {
25
+ const data = asRecord(await endpoint.callApi('get_group_member_list', {
26
+ group_id: toNumberId(groupId, 'group_id'),
27
+ }));
28
+ return toArray(data.members);
29
+ },
30
+ });
31
+ }
32
+ function asRecord(value) {
33
+ return value !== null && typeof value === 'object'
34
+ ? value
35
+ : {};
36
+ }
37
+ function toArray(value) {
38
+ return Array.isArray(value) ? value : [];
39
+ }
40
+ /** console RPC 传入的 gid/uid 可能是字符串,统一收敛为数字。 */
41
+ function toNumberId(value, label) {
42
+ const n = Number(value);
43
+ if (!Number.isFinite(n) || String(value ?? '').trim() === '') {
44
+ throw new TypeError(`milky ${label} 必须是数字: ${String(value)}`);
45
+ }
46
+ return n;
47
+ }
@@ -0,0 +1,7 @@
1
+ export { MilkyWsEndpoint, type MilkyWsEndpointOptions, } from './ws-endpoint.js';
2
+ export { MilkyWebhookEndpoint, type MilkyWebhookEndpointOptions, } from './webhook-endpoint.js';
3
+ export { MilkyWssEndpoint, type MilkyWssEndpointOptions, } from './wss-endpoint.js';
4
+ export { MilkySseEndpoint, type MilkySseEndpointOptions, type CreateMilkySseStream, } from './sse-endpoint.js';
5
+ export type { MilkyWsSocket, MilkyWsCreateOptions } from './ws-types.js';
6
+ export { verifyMilkyAccessToken } from './milky-auth.js';
7
+ export { openSseStream, consumeSseBuffer } from './sse-client.js';
@@ -0,0 +1,6 @@
1
+ export { MilkyWsEndpoint, } from './ws-endpoint.js';
2
+ export { MilkyWebhookEndpoint, } from './webhook-endpoint.js';
3
+ export { MilkyWssEndpoint, } from './wss-endpoint.js';
4
+ export { MilkySseEndpoint, } from './sse-endpoint.js';
5
+ export { verifyMilkyAccessToken } from './milky-auth.js';
6
+ export { openSseStream, consumeSseBuffer } from './sse-client.js';
package/lib/index.d.ts CHANGED
@@ -1,20 +1,6 @@
1
- import { MilkyAdapter } from './adapter.js';
2
- export * from './types.js';
3
- export { callApi } from './api.js';
4
- export * from './utils.js';
5
- export { MilkyWsClient } from './bot-ws.js';
6
- export { MilkySseClient } from './bot-sse.js';
7
- export { MilkyWebhookBot } from './bot-webhook.js';
8
- export { MilkyWssServer } from './bot-wss.js';
9
- export { MilkyAdapter, type MilkyBot } from './adapter.js';
10
- declare module 'zhin.js' {
11
- namespace Plugin {
12
- interface Contexts {
13
- router: import('@zhin.js/host-router').Router;
14
- }
15
- }
16
- interface Adapters {
17
- milky: MilkyAdapter;
18
- }
19
- }
20
- //# sourceMappingURL=index.d.ts.map
1
+ export { buildSendAction, buildSseConnectOptions, buildWsConnectOptions, callApi, extractInboundAudioUrl, formatInboundContent, formatOutboundSegments, isMentioned, isMessageReceiveEvent, milkyInboundConversation, parseMessageReceiveData, resolveMilkyConfig, senderNickname, type MilkyAdapterConfig, type MilkyApiClientOptions, type MilkyApiResponse, type MilkyConfigBase, type MilkyEndpointConfig, type MilkyEvent, type MilkyIncomingMessage, type MilkyIncomingSegment, type MilkyOutgoingSegment, type MilkySseConfig, type MilkyWebhookConfig, type MilkyWireSegment, type MilkyWsConfig, type MilkyWssConfig, type ResolvedMilkyConfig, } from './protocol.js';
2
+ export { MilkySseEndpoint, MilkyWebhookEndpoint, MilkyWssEndpoint, MilkyWsEndpoint, consumeSseBuffer, openSseStream, verifyMilkyAccessToken, type CreateMilkySseStream, type MilkySseEndpointOptions, type MilkyWebhookEndpointOptions, type MilkyWssEndpointOptions, type MilkyWsCreateOptions, type MilkyWsEndpointOptions, type MilkyWsSocket, } from './endpoint.js';
3
+ export { MilkyClient, milkyClient, type MilkyClientEventMap, } from './client.js';
4
+ export type { MilkyAdapterConfig as ImHelperMilkyAdapterConfig, MilkyActionUrlResolver, MilkyCall, MilkyMessageReceiveEvent, MilkyMessageRecallEvent, MilkyV1ClientConfig, MilkyV1Event, MilkyV1Response, } from '@imhelper/milky-v1';
5
+ export { ProtocolError } from '@imhelper/milky-v1';
6
+ export type { ProtocolErrorKind, ProtocolErrorOptions } from 'imhelper';
package/lib/index.js CHANGED
@@ -1,33 +1,4 @@
1
- /**
2
- * Milky 适配器入口:单一适配器,支持 WS/SSE/Webhook/反向 WS,依赖 router 注册
3
- */
4
- import { usePlugin, createGroupManagementTools } from 'zhin.js';
5
- import { MilkyAdapter } from './adapter.js';
6
- export * from './types.js';
7
- export { callApi } from './api.js';
8
- export * from './utils.js';
9
- export { MilkyWsClient } from './bot-ws.js';
10
- export { MilkySseClient } from './bot-sse.js';
11
- export { MilkyWebhookBot } from './bot-webhook.js';
12
- export { MilkyWssServer } from './bot-wss.js';
13
- export { MilkyAdapter } from './adapter.js';
14
- const plugin = usePlugin();
15
- const { provide, useContext } = plugin;
16
- provide({
17
- name: 'milky',
18
- description: 'Milky Adapter(WS 正向 / SSE / Webhook / 反向 WS)',
19
- mounted: async (p) => {
20
- const adapter = new MilkyAdapter(p);
21
- await adapter.start();
22
- return adapter;
23
- },
24
- dispose: async (adapter) => {
25
- await adapter.stop();
26
- },
27
- });
28
- useContext('tool', 'milky', (toolService, milky) => {
29
- const groupTools = createGroupManagementTools(milky, 'milky');
30
- const disposers = groupTools.map(t => toolService.addTool(t, plugin.name));
31
- return () => disposers.forEach(d => d());
32
- });
33
- //# sourceMappingURL=index.js.map
1
+ export { buildSendAction, buildSseConnectOptions, buildWsConnectOptions, callApi, extractInboundAudioUrl, formatInboundContent, formatOutboundSegments, isMentioned, isMessageReceiveEvent, milkyInboundConversation, parseMessageReceiveData, resolveMilkyConfig, senderNickname, } from './protocol.js';
2
+ export { MilkySseEndpoint, MilkyWebhookEndpoint, MilkyWssEndpoint, MilkyWsEndpoint, consumeSseBuffer, openSseStream, verifyMilkyAccessToken, } from './endpoint.js';
3
+ export { MilkyClient, milkyClient, } from './client.js';
4
+ export { ProtocolError } from '@imhelper/milky-v1';
@@ -0,0 +1,2 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ export declare function verifyMilkyAccessToken(accessToken: string | undefined, request: IncomingMessage): boolean;
@@ -0,0 +1,16 @@
1
+ export function verifyMilkyAccessToken(accessToken, request) {
2
+ if (!accessToken)
3
+ return true;
4
+ const auth = request.headers.authorization ?? '';
5
+ if (auth === `Bearer ${accessToken}`)
6
+ return true;
7
+ try {
8
+ const url = new URL(request.url ?? '/', 'http://localhost');
9
+ if (url.searchParams.get('access_token') === accessToken)
10
+ return true;
11
+ }
12
+ catch {
13
+ /* ignore */
14
+ }
15
+ return false;
16
+ }
@@ -0,0 +1 @@
1
+ export declare const milkyEndpointCommands: import("@zhin.js/adapter").EndpointCommands<Readonly<import("@zhin.js/command").CommandDefinition<unknown, unknown, import("@zhin.js/command").CommandMessage, string | undefined>>>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `milky.endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
3
+ * commands/endpoint/ 下的 list / add / remove 直接默认导出这三项。
4
+ */
5
+ import { createEndpointCommands } from 'zhin.js/adapter';
6
+ import { defineCommand } from 'zhin.js/command';
7
+ import { milkyRuntimeStateToken } from './milky-runtime-state.js';
8
+ export const milkyEndpointCommands = createEndpointCommands({
9
+ adapterKey: 'milky',
10
+ adapterDisplayName: 'Milky',
11
+ fields: [
12
+ { key: 'baseUrl', required: true, description: 'Milky HTTP API base URL' },
13
+ { key: 'path', description: 'webhook / reverse-wss 路径' },
14
+ { key: 'access_token', env: true, description: 'Milky access token' },
15
+ ],
16
+ running: (use) => use(milkyRuntimeStateToken).endpoints.values(),
17
+ describeEntry: (entry) => `baseUrl: ${String(entry.baseUrl)}`,
18
+ }, defineCommand);
@@ -0,0 +1 @@
1
+ export declare const milkyRuntimeStateToken: import("zhin.js").Token<import("@zhin.js/adapter").EndpointRuntimeState>;