@zhin.js/adapter-milky 1.0.1 → 1.1.2
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 +1046 -0
- package/{skills/milky/PERMITS.md → PERMITS.md} +2 -2
- package/README.md +60 -117
- package/adapters/milky/index.js +51 -0
- package/adapters/milky/index.ts +74 -0
- package/commands/milky/endpoint/add/[id]/index.js +3 -0
- package/commands/milky/endpoint/add/[id]/index.ts +3 -0
- package/commands/milky/endpoint/definition.js +19 -0
- package/commands/milky/endpoint/definition.ts +19 -0
- package/commands/milky/endpoint/list/index.js +3 -0
- package/commands/milky/endpoint/list/index.ts +3 -0
- package/commands/milky/endpoint/remove/[id]/index.js +3 -0
- package/commands/milky/endpoint/remove/[id]/index.ts +3 -0
- package/lib/client.d.ts +21 -0
- package/lib/client.js +33 -0
- package/lib/endpoint-management.d.ts +17 -0
- package/lib/endpoint-management.js +47 -0
- package/lib/endpoint.d.ts +7 -0
- package/lib/endpoint.js +6 -0
- package/lib/index.d.ts +6 -20
- package/lib/index.js +4 -35
- package/lib/milky-auth.d.ts +2 -0
- package/lib/milky-auth.js +16 -0
- package/lib/milky-runtime-state.d.ts +1 -0
- package/lib/milky-runtime-state.js +6 -0
- package/lib/protocol.d.ts +160 -0
- package/lib/protocol.js +491 -0
- package/lib/sse-client.d.ts +20 -0
- package/lib/sse-client.js +85 -0
- package/lib/sse-endpoint.d.ts +32 -0
- package/lib/sse-endpoint.js +207 -0
- package/lib/webhook-endpoint.d.ts +22 -0
- package/lib/webhook-endpoint.js +149 -0
- package/lib/ws-endpoint.d.ts +23 -0
- package/lib/ws-endpoint.js +233 -0
- package/lib/ws-types.d.ts +11 -0
- package/lib/ws-types.js +1 -0
- package/lib/wss-endpoint.d.ts +25 -0
- package/lib/wss-endpoint.js +199 -0
- package/package.json +78 -19
- package/plugin.js +14 -0
- package/schema.json +119 -0
- package/src/client.ts +80 -0
- package/src/endpoint-management.ts +74 -0
- package/src/endpoint.ts +26 -0
- package/src/index.ts +62 -47
- package/src/milky-auth.ts +14 -0
- package/src/milky-runtime-state.ts +7 -0
- package/src/protocol.ts +633 -0
- package/src/sse-client.ts +106 -0
- package/src/sse-endpoint.ts +258 -0
- package/src/webhook-endpoint.ts +196 -0
- package/src/ws-endpoint.ts +291 -0
- package/src/ws-types.ts +12 -0
- package/src/wss-endpoint.ts +241 -0
- package/lib/adapter.d.ts +0 -29
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -91
- package/lib/adapter.js.map +0 -1
- package/lib/api.d.ts +0 -10
- package/lib/api.d.ts.map +0 -1
- package/lib/api.js +0 -48
- package/lib/api.js.map +0 -1
- package/lib/endpoint-sse.d.ts +0 -31
- package/lib/endpoint-sse.d.ts.map +0 -1
- package/lib/endpoint-sse.js +0 -195
- package/lib/endpoint-sse.js.map +0 -1
- package/lib/endpoint-webhook.d.ts +0 -34
- package/lib/endpoint-webhook.d.ts.map +0 -1
- package/lib/endpoint-webhook.js +0 -187
- package/lib/endpoint-webhook.js.map +0 -1
- package/lib/endpoint-ws.d.ts +0 -35
- package/lib/endpoint-ws.d.ts.map +0 -1
- package/lib/endpoint-ws.js +0 -262
- package/lib/endpoint-ws.js.map +0 -1
- package/lib/endpoint-wss.d.ts +0 -34
- package/lib/endpoint-wss.d.ts.map +0 -1
- package/lib/endpoint-wss.js +0 -225
- package/lib/endpoint-wss.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/types.d.ts +0 -75
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -5
- package/lib/types.js.map +0 -1
- package/lib/utils.d.ts +0 -35
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js +0 -165
- package/lib/utils.js.map +0 -1
- package/plugin.yml +0 -3
- package/skills/milky/SKILL.md +0 -65
- package/src/adapter.ts +0 -103
- package/src/api.ts +0 -63
- package/src/endpoint-sse.ts +0 -228
- package/src/endpoint-webhook.ts +0 -221
- package/src/endpoint-ws.ts +0 -296
- package/src/endpoint-wss.ts +0 -268
- package/src/types.ts +0 -73
- package/src/utils.ts +0 -181
package/README.md
CHANGED
|
@@ -1,158 +1,101 @@
|
|
|
1
1
|
# @zhin.js/adapter-milky
|
|
2
2
|
|
|
3
|
-
Zhin.js [Milky](https://milky.ntqqrev.org/)
|
|
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
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
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
|
|
16
|
+
pnpm add @zhin.js/adapter-milky
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
|
|
19
|
+
## Plugin Runtime
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
- `@zhin.js/adapter` — 约定式 `adapters/milky/index.ts`(`defineAdapter`)
|
|
22
|
+
- `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
|
|
23
|
+
- `zhin.js` — `plugin.ts`(`definePlugin`)
|
|
24
|
+
- 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
|
|
25
|
+
|
|
26
|
+
`AdapterIndex` 会把实例默认值与 `endpoints[]` 的逐项覆盖合并;协议层只接收一个已经展开的 endpoint 配置,不再读取嵌套 endpoint 或从进程环境推断 endpoint 身份。
|
|
27
|
+
|
|
28
|
+
入站:`gateway.receive({ conversation: ConversationRef(kind: "private"|"group", id), message, content, sender, metadata })`
|
|
29
|
+
出站:`send({ conversation, payload })` → HTTP `send_private_message` / `send_group_message`(payload 已由 gateway/core 渲染;无 segment-mapper)
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
每个 Endpoint 的 `$client` 是 `@imhelper/milky-v1` 的 `MilkyV1Client`。插件可直接调用
|
|
32
|
+
`$client.call()`、`getGroupList()` 等公开能力;`defineHandler({ adapter: 'milky', event: ... })`
|
|
33
|
+
使用 imhelper 的精确事件名与 payload 类型。HTTP、纯事件 WS/WSS 和 `ingest()` 都汇入同一个
|
|
34
|
+
Client 事件流,Endpoint 仍独占账号连接、鉴权、重连和心跳。
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
## 前置条件
|
|
32
37
|
|
|
33
|
-
|
|
38
|
+
1. 启动兼容 Milky 的实现,并记录 HTTP API 与事件连接地址。
|
|
39
|
+
2. 正向 WS/SSE 需 Zhin 主动可达实现端;Webhook/反向 WS 需实现端可达 Zhin HTTP Host。
|
|
40
|
+
3. 两端配置相同的 `access_token`,生产环境不要暴露无鉴权接口。
|
|
41
|
+
|
|
42
|
+
## 最小配置
|
|
34
43
|
|
|
35
44
|
```yaml
|
|
45
|
+
# zhin.config.yml(Plugin Runtime)
|
|
36
46
|
plugins:
|
|
37
|
-
|
|
38
|
-
- "@zhin.js/adapter-milky"
|
|
39
|
-
|
|
40
|
-
endpoints:
|
|
41
|
-
- context: milky
|
|
47
|
+
milky:
|
|
42
48
|
connection: ws
|
|
43
|
-
name: milky-bot
|
|
44
|
-
baseUrl: "http://127.0.0.1:8080"
|
|
45
|
-
access_token: "${MILKY_ACCESS_TOKEN}"
|
|
46
49
|
reconnect_interval: 5000
|
|
47
50
|
heartbeat_interval: 30000
|
|
51
|
+
endpoints:
|
|
52
|
+
- id: milky-bot
|
|
53
|
+
baseUrl: "http://127.0.0.1:8080"
|
|
54
|
+
access_token: "${MILKY_ACCESS_TOKEN}"
|
|
48
55
|
```
|
|
49
56
|
|
|
50
|
-
|
|
57
|
+
根插件 `zhin.plugins`(或项目图)需引用 `@zhin.js/adapter-milky`(`instanceKey: milky`)。
|
|
51
58
|
|
|
52
|
-
|
|
53
|
-
endpoints:
|
|
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
|
-
```
|
|
59
|
+
## 连接方式
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
endpoints:
|
|
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
|
-
```
|
|
61
|
+
| connection | 状态 |
|
|
62
|
+
|------------|------|
|
|
63
|
+
| `ws` | 已实现(推荐) |
|
|
64
|
+
| `sse` | HTTP GET `/event`(`Accept: text/event-stream`) |
|
|
65
|
+
| `webhook` | 已实现:POST 入站 + baseUrl HTTP API 出站 |
|
|
66
|
+
| `wss` | 已实现:反向 WS(httpHostToken) |
|
|
85
67
|
|
|
86
68
|
## 鉴权
|
|
87
69
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
-
|
|
91
|
-
- **Query**:`access_token=xxx`
|
|
92
|
-
|
|
93
|
-
建议配置 `access_token`,并与协议端一致。
|
|
94
|
-
|
|
95
|
-
## 连接方式对比
|
|
70
|
+
- **Bearer**:`Authorization: Bearer <access_token>`
|
|
71
|
+
- 正向 WS 在 Upgrade 时附带请求头,并在 URL query 写入 `access_token`
|
|
72
|
+
- HTTP API 同样使用 Header / query 鉴权
|
|
96
73
|
|
|
97
|
-
|
|
98
|
-
|------------|--------------------------------|
|
|
99
|
-
| `ws` | 应用主动连协议端 `/event` |
|
|
100
|
-
| `sse` | 应用 GET `/event` 拉取事件流 |
|
|
101
|
-
| `webhook` | 协议端 POST 到应用配置的 path |
|
|
102
|
-
| `wss` | 协议端连应用提供的 WS path |
|
|
74
|
+
## 消息 ID
|
|
103
75
|
|
|
104
|
-
|
|
76
|
+
`{message_scene}:{peer_id}:{message_seq}`(如 `group:123456:10001`)。
|
|
105
77
|
|
|
106
|
-
|
|
78
|
+
## AI 工具
|
|
107
79
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
```
|
|
80
|
+
| 类别 | 路径 |
|
|
81
|
+
|------|------|
|
|
82
|
+
| Permit 词汇 | `PERMITS.md` |
|
|
83
|
+
| 技能说明 | `skills/milky/SKILL.md` |
|
|
130
84
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
## 消息 ID 格式
|
|
134
|
-
|
|
135
|
-
`{message_scene}:{peer_id}:{message_seq}`(如 `group:123456:10001`)。撤回时使用该 ID。
|
|
136
|
-
|
|
137
|
-
## 协议与 API 参考
|
|
85
|
+
## 文档链接
|
|
138
86
|
|
|
139
87
|
- [Milky 快速开始](https://milky.ntqqrev.org/)
|
|
140
88
|
- [Milky 通信](https://milky.ntqqrev.org/guide/communication)
|
|
141
|
-
- [
|
|
142
|
-
|
|
143
|
-
## 依赖项
|
|
89
|
+
- [适配器概览](https://zhin.js.org/essentials/adapters)
|
|
144
90
|
|
|
145
|
-
|
|
146
|
-
- `eventsource` - SSE 客户端
|
|
147
|
-
- `zhin.js` - Zhin 核心
|
|
148
|
-
- `@zhin.js/host-router` - 提供 router,适配器注册依赖
|
|
91
|
+
## 故障排查
|
|
149
92
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
93
|
+
| 现象 | 排查 |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| WS/SSE 无事件 | 核对 `baseUrl`、连接模式与实现端事件服务 |
|
|
96
|
+
| 401 或握手失败 | 确认 Bearer/query 中的 `access_token` 与实现端一致 |
|
|
97
|
+
| Webhook/WSS 无法连接 | 检查 HTTP Host、网络可达性与回调路径 |
|
|
98
|
+
| 能收不能发 | 检查 HTTP API 与发送动作支持情况 |
|
|
156
99
|
|
|
157
100
|
## 许可证
|
|
158
101
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* Convention entry: discover `adapters/milky/index.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/index.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 MilkyEndpointConfig,
|
|
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<MilkyEndpointConfig>({
|
|
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,19 @@
|
|
|
1
|
+
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
/**
|
|
3
|
+
* `milky endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
4
|
+
* commands/milky/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
5
|
+
*/
|
|
6
|
+
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
7
|
+
import { defineCommand } from 'zhin.js/command';
|
|
8
|
+
import { milkyRuntimeStateToken } from "../../../lib/milky-runtime-state.js";
|
|
9
|
+
export const milkyEndpointCommands = createEndpointCommands({
|
|
10
|
+
adapterKey: 'milky',
|
|
11
|
+
adapterDisplayName: 'Milky',
|
|
12
|
+
fields: [
|
|
13
|
+
{ key: 'baseUrl', required: true, description: 'Milky HTTP API base URL' },
|
|
14
|
+
{ key: 'path', description: 'webhook / reverse-wss 路径' },
|
|
15
|
+
{ key: 'access_token', env: true, description: 'Milky access token' },
|
|
16
|
+
],
|
|
17
|
+
running: (use) => use(milkyRuntimeStateToken).endpoints.values(),
|
|
18
|
+
describeEntry: (entry) => `baseUrl: ${String(entry.baseUrl)}`,
|
|
19
|
+
}, defineCommand);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `milky endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
|
|
3
|
+
* commands/milky/endpoint/ 下的 list / add / remove 直接默认导出这三项。
|
|
4
|
+
*/
|
|
5
|
+
import { createEndpointCommands } from 'zhin.js/adapter';
|
|
6
|
+
import { defineCommand } from 'zhin.js/command';
|
|
7
|
+
import { milkyRuntimeStateToken } from '../../../src/milky-runtime-state.js';
|
|
8
|
+
|
|
9
|
+
export const milkyEndpointCommands = createEndpointCommands({
|
|
10
|
+
adapterKey: 'milky',
|
|
11
|
+
adapterDisplayName: 'Milky',
|
|
12
|
+
fields: [
|
|
13
|
+
{ key: 'baseUrl', required: true, description: 'Milky HTTP API base URL' },
|
|
14
|
+
{ key: 'path', description: 'webhook / reverse-wss 路径' },
|
|
15
|
+
{ key: 'access_token', env: true, description: 'Milky access token' },
|
|
16
|
+
],
|
|
17
|
+
running: (use) => use(milkyRuntimeStateToken).endpoints.values(),
|
|
18
|
+
describeEntry: (entry) => `baseUrl: ${String(entry.baseUrl)}`,
|
|
19
|
+
}, defineCommand);
|
package/lib/client.d.ts
ADDED
|
@@ -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';
|
package/lib/endpoint.js
ADDED
|
@@ -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
|
-
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
4
|
-
export
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export { MilkyWebhookEndpoint } from './endpoint-webhook.js';
|
|
8
|
-
export { MilkyWssServer } from './endpoint-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 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,35 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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 './endpoint-ws.js';
|
|
10
|
-
export { MilkySseClient } from './endpoint-sse.js';
|
|
11
|
-
export { MilkyWebhookEndpoint } from './endpoint-webhook.js';
|
|
12
|
-
export { MilkyWssServer } from './endpoint-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 disposers = [];
|
|
30
|
-
disposers.push(registerDefaultGroupPlatformPermitChecker('milky'));
|
|
31
|
-
const groupTools = createGroupManagementTools(milky, 'milky');
|
|
32
|
-
disposers.push(...groupTools.map(t => toolService.addTool(t, plugin.name)));
|
|
33
|
-
return () => disposers.forEach(d => d());
|
|
34
|
-
});
|
|
35
|
-
//# 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';
|