@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
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Milky WS client endpoint — outbound connect to Milky protocol server.
|
|
3
|
+
*/
|
|
4
|
+
import WebSocket from 'ws';
|
|
5
|
+
import {
|
|
6
|
+
ClientEndpoint,
|
|
7
|
+
createRecallEndpointControl,
|
|
8
|
+
createEndpointLifecycle,
|
|
9
|
+
type EndpointConnectHandle,
|
|
10
|
+
type EndpointControl,
|
|
11
|
+
type EndpointLifecycle,
|
|
12
|
+
type EndpointManagement,
|
|
13
|
+
type EndpointSendRequest,
|
|
14
|
+
} from 'zhin.js/adapter';
|
|
15
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
16
|
+
import type { CapabilityId } from 'zhin.js';
|
|
17
|
+
import { createMilkyEndpointManagement } from './endpoint-management.js';
|
|
18
|
+
import {
|
|
19
|
+
callMilkyClient,
|
|
20
|
+
createMilkyEndpointClient,
|
|
21
|
+
forwardMilkyClientEvents,
|
|
22
|
+
type MilkyClient,
|
|
23
|
+
} from './client.js';
|
|
24
|
+
import {
|
|
25
|
+
buildSendAction,
|
|
26
|
+
buildWsConnectOptions,
|
|
27
|
+
callApi,
|
|
28
|
+
extractInboundAudioUrl,
|
|
29
|
+
formatInboundContent,
|
|
30
|
+
formatInboundMessageId,
|
|
31
|
+
formatInboundSegments,
|
|
32
|
+
formatOutboundMessageId,
|
|
33
|
+
formatOutboundSegments,
|
|
34
|
+
isMentioned,
|
|
35
|
+
milkyInboundConversation,
|
|
36
|
+
parseMessageReceiveData,
|
|
37
|
+
parseMilkyMessageId,
|
|
38
|
+
senderNickname,
|
|
39
|
+
type MilkyEvent,
|
|
40
|
+
type MilkyIncomingMessage,
|
|
41
|
+
type MilkyWsConfig,
|
|
42
|
+
} from './protocol.js';
|
|
43
|
+
import type { MilkyWsCreateOptions, MilkyWsSocket } from './ws-types.js';
|
|
44
|
+
|
|
45
|
+
const WS_OPEN = 1;
|
|
46
|
+
|
|
47
|
+
export interface MilkyWsEndpointOptions {
|
|
48
|
+
readonly id: CapabilityId;
|
|
49
|
+
readonly config: MilkyWsConfig;
|
|
50
|
+
readonly createWebSocket?: (
|
|
51
|
+
url: string,
|
|
52
|
+
options: MilkyWsCreateOptions,
|
|
53
|
+
) => MilkyWsSocket;
|
|
54
|
+
readonly callApi?: typeof callApi;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class MilkyWsEndpoint extends ClientEndpoint<MilkyClient> {
|
|
58
|
+
readonly client: MilkyClient;
|
|
59
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
60
|
+
|
|
61
|
+
readonly #options: MilkyWsEndpointOptions;
|
|
62
|
+
readonly #callApi: typeof callApi;
|
|
63
|
+
readonly management: EndpointManagement;
|
|
64
|
+
readonly control: EndpointControl = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
65
|
+
readonly #lifecycle: EndpointLifecycle;
|
|
66
|
+
#ws?: MilkyWsSocket;
|
|
67
|
+
#clientSocketRelease?: () => void;
|
|
68
|
+
|
|
69
|
+
constructor(options: MilkyWsEndpointOptions) {
|
|
70
|
+
super();
|
|
71
|
+
this.#logger = getAdapterLogger('milky', options.config.id);
|
|
72
|
+
this.#options = options;
|
|
73
|
+
this.#callApi = options.callApi ?? callApi;
|
|
74
|
+
this.client = createMilkyEndpointClient(options.config, this.#callApi);
|
|
75
|
+
this.management = createMilkyEndpointManagement({
|
|
76
|
+
callApi: (action, params) => callMilkyClient(this.client, action, params),
|
|
77
|
+
});
|
|
78
|
+
this.bindClientEvents(
|
|
79
|
+
(receive) => forwardMilkyClientEvents(this.client, receive),
|
|
80
|
+
(name, payload) => {
|
|
81
|
+
if (name === 'event') this.#admitRaw(payload as MilkyEvent);
|
|
82
|
+
},
|
|
83
|
+
(_name, error) => this.#warnPlatformEvent(error),
|
|
84
|
+
);
|
|
85
|
+
this.#lifecycle = createEndpointLifecycle({
|
|
86
|
+
name: options.config.id,
|
|
87
|
+
// reconnect_interval 旧语义为固定间隔:multiplier 1 + 无 jitter + 不封顶
|
|
88
|
+
reconnect: {
|
|
89
|
+
initialIntervalMs: options.config.reconnect_interval,
|
|
90
|
+
multiplier: 1,
|
|
91
|
+
maxIntervalMs: Number.MAX_SAFE_INTEGER,
|
|
92
|
+
jitterMs: 0,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async start(): Promise<void> {
|
|
98
|
+
if (this.#lifecycle.started) return;
|
|
99
|
+
await this.#lifecycle.start((handle) => this.#connect(handle));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
close(): void {
|
|
103
|
+
super.close();
|
|
104
|
+
this.#clientSocketRelease?.();
|
|
105
|
+
this.#clientSocketRelease = undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async stop(): Promise<void> {
|
|
109
|
+
this.close();
|
|
110
|
+
await this.#lifecycle.stop();
|
|
111
|
+
if (this.#ws) {
|
|
112
|
+
try {
|
|
113
|
+
this.#ws.close();
|
|
114
|
+
} catch {
|
|
115
|
+
/* ignore */
|
|
116
|
+
}
|
|
117
|
+
this.#ws = undefined;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
122
|
+
const message = formatOutboundSegments(payload);
|
|
123
|
+
const { action, params } = buildSendAction(conversation, message);
|
|
124
|
+
const data = await callMilkyClient<{ message_seq?: number }>(this.client, action, params);
|
|
125
|
+
const messageId = formatOutboundMessageId(conversation, data?.message_seq);
|
|
126
|
+
this.#logger.debug(formatCompact({
|
|
127
|
+
op: 'milky_send',
|
|
128
|
+
endpoint: this.#options.config.id,
|
|
129
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
130
|
+
messageId,
|
|
131
|
+
}));
|
|
132
|
+
return messageId;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async recallMessage(id: string): Promise<void> {
|
|
136
|
+
const parsed = parseMilkyMessageId(id);
|
|
137
|
+
if (!parsed) throw new Error(`Invalid message id: ${id}`);
|
|
138
|
+
if (parsed.message_scene === 'group') {
|
|
139
|
+
await callMilkyClient(this.client, 'recall_group_message', {
|
|
140
|
+
group_id: parsed.peer_id,
|
|
141
|
+
message_seq: parsed.message_seq,
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
await callMilkyClient(this.client, 'recall_private_message', {
|
|
145
|
+
user_id: parsed.peer_id,
|
|
146
|
+
message_seq: parsed.message_seq,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#admitRaw(event: MilkyEvent): void {
|
|
152
|
+
const data = parseMessageReceiveData(event);
|
|
153
|
+
if (!data) return;
|
|
154
|
+
this.#admitMessage(data, event);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#warnPlatformEvent(error: unknown): void {
|
|
158
|
+
this.#logger.warn(formatCompact({
|
|
159
|
+
op: 'milky_platform_event_failed',
|
|
160
|
+
error: error instanceof Error ? error.message : String(error),
|
|
161
|
+
}));
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#admitMessage(data: MilkyIncomingMessage, event: MilkyEvent): void {
|
|
165
|
+
const conversation = milkyInboundConversation(String(this.#options.id), data);
|
|
166
|
+
const target = `${conversation.kind}:${conversation.id}`;
|
|
167
|
+
const content = formatInboundContent(data);
|
|
168
|
+
const segments = formatInboundSegments(data);
|
|
169
|
+
const audioUrl = extractInboundAudioUrl(data);
|
|
170
|
+
const nickname = senderNickname(data);
|
|
171
|
+
const mentioned = isMentioned(data, event.self_id);
|
|
172
|
+
void this.emit('message.receive', {
|
|
173
|
+
conversation,
|
|
174
|
+
message: { conversation, id: formatInboundMessageId(data) },
|
|
175
|
+
content,
|
|
176
|
+
segments,
|
|
177
|
+
sender: { id: String(data.sender_id), name: nickname },
|
|
178
|
+
endpointId: this.#options.config.id,
|
|
179
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
180
|
+
metadata: Object.freeze({
|
|
181
|
+
message_scene: data.message_scene,
|
|
182
|
+
peer_id: String(data.peer_id),
|
|
183
|
+
sender_id: String(data.sender_id),
|
|
184
|
+
message_seq: data.message_seq,
|
|
185
|
+
time: data.time ?? event.time,
|
|
186
|
+
self_id: event.self_id != null ? String(event.self_id) : undefined,
|
|
187
|
+
...(nickname ? { nickname } : {}),
|
|
188
|
+
}),
|
|
189
|
+
}).catch((err) => {
|
|
190
|
+
this.#logger.warn(formatCompact({
|
|
191
|
+
op: 'milky_gateway_receive_failed',
|
|
192
|
+
target,
|
|
193
|
+
error: err instanceof Error ? err.message : String(err),
|
|
194
|
+
}));
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async #connect(handle: EndpointConnectHandle): Promise<void> {
|
|
199
|
+
const { url, headers, safeUrl } = buildWsConnectOptions(this.#options.config);
|
|
200
|
+
const create = this.#options.createWebSocket
|
|
201
|
+
?? ((connectUrl: string, options: MilkyWsCreateOptions) =>
|
|
202
|
+
new WebSocket(connectUrl, { headers: options.headers }) as unknown as MilkyWsSocket);
|
|
203
|
+
|
|
204
|
+
await new Promise<void>((resolve, reject) => {
|
|
205
|
+
let settled = false;
|
|
206
|
+
const ws = create(url, { headers });
|
|
207
|
+
this.#ws = ws;
|
|
208
|
+
handle.onForceClose(() => {
|
|
209
|
+
try {
|
|
210
|
+
ws.close();
|
|
211
|
+
} catch {
|
|
212
|
+
/* ignore */
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
ws.on('open', () => {
|
|
217
|
+
if (settled) return;
|
|
218
|
+
settled = true;
|
|
219
|
+
if (!this.#options.config.access_token) {
|
|
220
|
+
this.#logger.warn(formatCompact({
|
|
221
|
+
endpoint: this.#options.config.id,
|
|
222
|
+
ok: false,
|
|
223
|
+
error: 'missing access_token',
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
this.#logger.debug(formatCompact({
|
|
227
|
+
endpoint: this.#options.config.id,
|
|
228
|
+
mode: 'ws',
|
|
229
|
+
url: safeUrl,
|
|
230
|
+
}));
|
|
231
|
+
// stop-during-connect 竞态:已停止则不再武装心跳(基座 stop 已清理定时器)
|
|
232
|
+
if (this.#lifecycle.started) {
|
|
233
|
+
this.#lifecycle.startHeartbeat(() => {
|
|
234
|
+
try {
|
|
235
|
+
if (ws.readyState === WS_OPEN) ws.ping?.();
|
|
236
|
+
} catch {
|
|
237
|
+
/* ignore */
|
|
238
|
+
}
|
|
239
|
+
}, this.#options.config.heartbeat_interval);
|
|
240
|
+
}
|
|
241
|
+
resolve();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
this.#clientSocketRelease?.();
|
|
245
|
+
this.#clientSocketRelease = this.client.acceptWebSocket(ws);
|
|
246
|
+
|
|
247
|
+
ws.on('close', (code, reason) => {
|
|
248
|
+
this.#clientSocketRelease?.();
|
|
249
|
+
this.#clientSocketRelease = undefined;
|
|
250
|
+
const reasonStr = typeof reason === 'string'
|
|
251
|
+
? reason
|
|
252
|
+
: Buffer.isBuffer(reason)
|
|
253
|
+
? reason.toString()
|
|
254
|
+
: String(reason ?? '');
|
|
255
|
+
const codeNum = typeof code === 'number' ? code : Number(code ?? 0);
|
|
256
|
+
const codeHint = codeNum === 1005
|
|
257
|
+
? ' [无状态,多为服务端/代理未发 close 帧即断开]'
|
|
258
|
+
: codeNum === 1006
|
|
259
|
+
? ' [异常关闭]'
|
|
260
|
+
: '';
|
|
261
|
+
this.#logger.warn(formatCompact({
|
|
262
|
+
op: 'disconnect',
|
|
263
|
+
code: codeNum,
|
|
264
|
+
error: `${reasonStr || 'closed'}${codeHint}`,
|
|
265
|
+
reconnect_ms: this.#options.config.reconnect_interval,
|
|
266
|
+
}));
|
|
267
|
+
// 基座语义:仅曾 open 的连接才武装重连;初始连接失败由 start() 的 catch 复位
|
|
268
|
+
handle.notifyClosed(new Error(`Milky WS 关闭: ${codeNum} ${reasonStr}`));
|
|
269
|
+
if (!settled) {
|
|
270
|
+
settled = true;
|
|
271
|
+
reject(new Error(`Milky WS 关闭: ${codeNum} ${reasonStr}`));
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
ws.on('error', (err) => {
|
|
276
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
277
|
+
this.#logger.warn(formatCompact({
|
|
278
|
+
op: 'ws_error',
|
|
279
|
+
endpoint: this.#options.config.id,
|
|
280
|
+
ok: false,
|
|
281
|
+
error: error.message,
|
|
282
|
+
}));
|
|
283
|
+
if (!settled) {
|
|
284
|
+
settled = true;
|
|
285
|
+
reject(error);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
}
|
package/src/ws-types.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Minimal WS surface used by the endpoint (real `ws` or test mock). */
|
|
2
|
+
export interface MilkyWsSocket {
|
|
3
|
+
readonly readyState: number;
|
|
4
|
+
send?(data: string): void;
|
|
5
|
+
close(code?: number, reason?: string): void;
|
|
6
|
+
ping?(): void;
|
|
7
|
+
on(event: 'open' | 'message' | 'close' | 'error', listener: (...args: unknown[]) => void): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MilkyWsCreateOptions {
|
|
11
|
+
readonly headers?: Record<string, string>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Milky reverse WSS endpoint — httpHostToken WS upgrade inbound + baseUrl HTTP API outbound.
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
ClientEndpoint,
|
|
6
|
+
createEndpointLifecycle,
|
|
7
|
+
createRecallEndpointControl,
|
|
8
|
+
type EndpointLifecycle,
|
|
9
|
+
type EndpointControl,
|
|
10
|
+
type EndpointManagement,
|
|
11
|
+
type EndpointSendRequest,
|
|
12
|
+
} from 'zhin.js/adapter';
|
|
13
|
+
import type { HttpHost, WsConnection } from '@zhin.js/host-http';
|
|
14
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
15
|
+
import type { CapabilityId } from 'zhin.js';
|
|
16
|
+
import { verifyMilkyAccessToken } from './milky-auth.js';
|
|
17
|
+
import { createMilkyEndpointManagement } from './endpoint-management.js';
|
|
18
|
+
import { callMilkyClient, createMilkyEndpointClient, forwardMilkyClientEvents, type MilkyClient } from './client.js';
|
|
19
|
+
import {
|
|
20
|
+
buildSendAction,
|
|
21
|
+
callApi,
|
|
22
|
+
extractInboundAudioUrl,
|
|
23
|
+
formatInboundContent,
|
|
24
|
+
formatInboundMessageId,
|
|
25
|
+
formatInboundSegments,
|
|
26
|
+
formatOutboundMessageId,
|
|
27
|
+
formatOutboundSegments,
|
|
28
|
+
isMentioned,
|
|
29
|
+
milkyInboundConversation,
|
|
30
|
+
parseMessageReceiveData,
|
|
31
|
+
parseMilkyMessageId,
|
|
32
|
+
senderNickname,
|
|
33
|
+
type MilkyEvent,
|
|
34
|
+
type MilkyIncomingMessage,
|
|
35
|
+
type MilkyWssConfig,
|
|
36
|
+
} from './protocol.js';
|
|
37
|
+
import type { MilkyWsSocket } from './ws-types.js';
|
|
38
|
+
|
|
39
|
+
const WS_OPEN = 1;
|
|
40
|
+
|
|
41
|
+
export interface MilkyWssEndpointOptions {
|
|
42
|
+
readonly id: CapabilityId;
|
|
43
|
+
readonly http: HttpHost;
|
|
44
|
+
readonly config: MilkyWssConfig;
|
|
45
|
+
readonly callApi?: typeof callApi;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class MilkyWssEndpoint extends ClientEndpoint<MilkyClient> {
|
|
49
|
+
readonly client: MilkyClient;
|
|
50
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
51
|
+
|
|
52
|
+
readonly #options: MilkyWssEndpointOptions;
|
|
53
|
+
readonly #callApi: typeof callApi;
|
|
54
|
+
readonly management: EndpointManagement;
|
|
55
|
+
readonly control: EndpointControl = createRecallEndpointControl((id) => this.recallMessage(id));
|
|
56
|
+
#ws?: MilkyWsSocket;
|
|
57
|
+
#wsRelease?: () => void;
|
|
58
|
+
#clientSocketRelease?: () => void;
|
|
59
|
+
readonly #connectionLifecycle: EndpointLifecycle;
|
|
60
|
+
#connectionTask = Promise.resolve();
|
|
61
|
+
#started = false;
|
|
62
|
+
|
|
63
|
+
constructor(options: MilkyWssEndpointOptions) {
|
|
64
|
+
super();
|
|
65
|
+
this.#logger = getAdapterLogger('milky', options.config.id);
|
|
66
|
+
this.#options = options;
|
|
67
|
+
this.#callApi = options.callApi ?? callApi;
|
|
68
|
+
this.#connectionLifecycle = createEndpointLifecycle({
|
|
69
|
+
name: `${options.config.id}:inbound`,
|
|
70
|
+
reconnect: false,
|
|
71
|
+
});
|
|
72
|
+
this.client = createMilkyEndpointClient(options.config, this.#callApi);
|
|
73
|
+
this.management = createMilkyEndpointManagement({
|
|
74
|
+
callApi: (action, params) => callMilkyClient(this.client, action, params),
|
|
75
|
+
});
|
|
76
|
+
this.bindClientEvents(
|
|
77
|
+
(receive) => forwardMilkyClientEvents(this.client, receive),
|
|
78
|
+
(name, payload) => {
|
|
79
|
+
if (name === 'event') this.#admitRaw(payload as MilkyEvent);
|
|
80
|
+
},
|
|
81
|
+
(_name, error) => this.#warnPlatformEvent(error),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async start(): Promise<void> {
|
|
86
|
+
if (this.#started) return;
|
|
87
|
+
this.#started = true;
|
|
88
|
+
const handle = this.#options.http.ws(this.#options.config.path);
|
|
89
|
+
this.#wsRelease = handle.onConnection((connection) => {
|
|
90
|
+
this.#connectionTask = this.#connectionTask
|
|
91
|
+
.then(() => this.#acceptConnection(connection))
|
|
92
|
+
.catch((error) => {
|
|
93
|
+
this.#logger.warn(formatCompact({
|
|
94
|
+
op: 'wss_connection_failed',
|
|
95
|
+
endpoint: this.#options.config.id,
|
|
96
|
+
error: error instanceof Error ? error.message : String(error),
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
this.#logger.info(formatCompact({
|
|
101
|
+
op: 'listen',
|
|
102
|
+
endpoint: this.#options.config.id,
|
|
103
|
+
mode: 'wss',
|
|
104
|
+
path: this.#options.config.path,
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async stop(): Promise<void> {
|
|
109
|
+
this.close();
|
|
110
|
+
this.#wsRelease?.();
|
|
111
|
+
this.#wsRelease = undefined;
|
|
112
|
+
await this.#connectionTask;
|
|
113
|
+
await this.#connectionLifecycle.stop();
|
|
114
|
+
this.#ws = undefined;
|
|
115
|
+
this.#started = false;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
119
|
+
const message = formatOutboundSegments(payload);
|
|
120
|
+
const { action, params } = buildSendAction(conversation, message);
|
|
121
|
+
const data = await callMilkyClient<{ message_seq?: number }>(this.client, action, params);
|
|
122
|
+
const messageId = formatOutboundMessageId(conversation, data?.message_seq);
|
|
123
|
+
this.#logger.debug(formatCompact({
|
|
124
|
+
op: 'milky_send',
|
|
125
|
+
endpoint: this.#options.config.id,
|
|
126
|
+
target: `${conversation.kind}:${conversation.id}`,
|
|
127
|
+
messageId,
|
|
128
|
+
}));
|
|
129
|
+
return messageId;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async recallMessage(id: string): Promise<void> {
|
|
133
|
+
const parsed = parseMilkyMessageId(id);
|
|
134
|
+
if (!parsed) throw new Error(`Invalid message id: ${id}`);
|
|
135
|
+
if (parsed.message_scene === 'group') {
|
|
136
|
+
await callMilkyClient(this.client, 'recall_group_message', {
|
|
137
|
+
group_id: parsed.peer_id,
|
|
138
|
+
message_seq: parsed.message_seq,
|
|
139
|
+
});
|
|
140
|
+
} else {
|
|
141
|
+
await callMilkyClient(this.client, 'recall_private_message', {
|
|
142
|
+
user_id: parsed.peer_id,
|
|
143
|
+
message_seq: parsed.message_seq,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
#admitRaw(event: MilkyEvent): void {
|
|
149
|
+
const data = parseMessageReceiveData(event);
|
|
150
|
+
if (!data) return;
|
|
151
|
+
this.#admitMessage(data, event);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
#warnPlatformEvent(error: unknown): void {
|
|
155
|
+
this.#logger.warn(formatCompact({ op: 'milky_platform_event_failed', error: error instanceof Error ? error.message : String(error) }));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
#admitMessage(data: MilkyIncomingMessage, event: MilkyEvent): void {
|
|
159
|
+
const conversation = milkyInboundConversation(String(this.#options.id), data);
|
|
160
|
+
const target = `${conversation.kind}:${conversation.id}`;
|
|
161
|
+
const content = formatInboundContent(data);
|
|
162
|
+
const segments = formatInboundSegments(data);
|
|
163
|
+
const audioUrl = extractInboundAudioUrl(data);
|
|
164
|
+
const nickname = senderNickname(data);
|
|
165
|
+
const mentioned = isMentioned(data, event.self_id);
|
|
166
|
+
void this.emit('message.receive', {
|
|
167
|
+
conversation,
|
|
168
|
+
message: { conversation, id: formatInboundMessageId(data) },
|
|
169
|
+
content,
|
|
170
|
+
segments,
|
|
171
|
+
sender: { id: String(data.sender_id) },
|
|
172
|
+
endpointId: this.#options.config.id,
|
|
173
|
+
...(mentioned ? { mentioned: true } : {}),
|
|
174
|
+
metadata: Object.freeze({
|
|
175
|
+
message_scene: data.message_scene,
|
|
176
|
+
peer_id: String(data.peer_id),
|
|
177
|
+
sender_id: String(data.sender_id),
|
|
178
|
+
message_seq: data.message_seq,
|
|
179
|
+
time: data.time ?? event.time,
|
|
180
|
+
self_id: event.self_id != null ? String(event.self_id) : undefined,
|
|
181
|
+
...(nickname ? { nickname } : {}),
|
|
182
|
+
}),
|
|
183
|
+
}).catch((err) => {
|
|
184
|
+
this.#logger.warn(formatCompact({
|
|
185
|
+
op: 'milky_gateway_receive_failed',
|
|
186
|
+
target,
|
|
187
|
+
error: err instanceof Error ? err.message : String(err),
|
|
188
|
+
}));
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async #acceptConnection(connection: WsConnection): Promise<void> {
|
|
193
|
+
if (!verifyMilkyAccessToken(this.#options.config.access_token, connection.request)) {
|
|
194
|
+
connection.socket.close(4003, 'Unauthorized');
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const socket = connection.socket as unknown as MilkyWsSocket;
|
|
198
|
+
await this.#connectionLifecycle.stop();
|
|
199
|
+
await this.#connectionLifecycle.start(async (lifecycleHandle) => {
|
|
200
|
+
this.#ws = socket;
|
|
201
|
+
const releaseClientSocket = this.client.acceptWebSocket(socket);
|
|
202
|
+
this.#clientSocketRelease = releaseClientSocket;
|
|
203
|
+
lifecycleHandle.onForceClose(() => {
|
|
204
|
+
if (this.#clientSocketRelease === releaseClientSocket) {
|
|
205
|
+
releaseClientSocket();
|
|
206
|
+
this.#clientSocketRelease = undefined;
|
|
207
|
+
}
|
|
208
|
+
try {
|
|
209
|
+
socket.close();
|
|
210
|
+
} catch {
|
|
211
|
+
/* ignore */
|
|
212
|
+
}
|
|
213
|
+
if (this.#ws === socket) this.#ws = undefined;
|
|
214
|
+
});
|
|
215
|
+
this.#connectionLifecycle.startHeartbeat(() => {
|
|
216
|
+
try {
|
|
217
|
+
if (socket.readyState === WS_OPEN) socket.ping?.();
|
|
218
|
+
} catch {
|
|
219
|
+
/* ignore */
|
|
220
|
+
}
|
|
221
|
+
}, this.#options.config.heartbeat_interval);
|
|
222
|
+
socket.on('message', () => {
|
|
223
|
+
this.#connectionLifecycle.notifyHeartbeatAck();
|
|
224
|
+
});
|
|
225
|
+
socket.on('close', () => {
|
|
226
|
+
if (this.#clientSocketRelease === releaseClientSocket) {
|
|
227
|
+
releaseClientSocket();
|
|
228
|
+
this.#clientSocketRelease = undefined;
|
|
229
|
+
}
|
|
230
|
+
if (this.#ws === socket) this.#ws = undefined;
|
|
231
|
+
lifecycleHandle.notifyClosed(new Error('Milky reverse WebSocket closed'));
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
this.#logger.debug(formatCompact({
|
|
235
|
+
endpoint: this.#options.config.id,
|
|
236
|
+
mode: 'wss',
|
|
237
|
+
peer: connection.request.socket.remoteAddress,
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
}
|
package/lib/adapter.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Milky 适配器:单一适配器支持 WS 正向 / SSE / Webhook / 反向 WS,由 config.connection 区分
|
|
3
|
-
*/
|
|
4
|
-
import { Adapter, Plugin } from 'zhin.js';
|
|
5
|
-
import { MilkyWsClient } from './endpoint-ws.js';
|
|
6
|
-
import { MilkySseClient } from './endpoint-sse.js';
|
|
7
|
-
import { MilkyWebhookEndpoint } from './endpoint-webhook.js';
|
|
8
|
-
import { MilkyWssServer } from './endpoint-wss.js';
|
|
9
|
-
import type { MilkyEndpointConfig } from './types.js';
|
|
10
|
-
export type MilkyBot = MilkyWsClient | MilkySseClient | MilkyWebhookEndpoint | MilkyWssServer;
|
|
11
|
-
export declare class MilkyAdapter extends Adapter<MilkyBot> {
|
|
12
|
-
#private;
|
|
13
|
-
static readonly capabilities: readonly ["inbound", "outbound"];
|
|
14
|
-
constructor(plugin: Plugin);
|
|
15
|
-
createEndpoint(config: MilkyEndpointConfig): MilkyBot;
|
|
16
|
-
kickMember(endpointId: string, sceneId: string, userId: string): Promise<boolean>;
|
|
17
|
-
muteMember(endpointId: string, sceneId: string, userId: string, duration?: number): Promise<boolean>;
|
|
18
|
-
muteAll(endpointId: string, sceneId: string, enable?: boolean): Promise<boolean>;
|
|
19
|
-
setAdmin(endpointId: string, sceneId: string, userId: string, enable?: boolean): Promise<boolean>;
|
|
20
|
-
setMemberNickname(endpointId: string, sceneId: string, userId: string, nickname: string): Promise<boolean>;
|
|
21
|
-
setGroupName(endpointId: string, sceneId: string, name: string): Promise<boolean>;
|
|
22
|
-
listMembers(endpointId: string, sceneId: string): Promise<{
|
|
23
|
-
members: unknown[];
|
|
24
|
-
count: number;
|
|
25
|
-
}>;
|
|
26
|
-
getGroupInfo(endpointId: string, sceneId: string): Promise<unknown>;
|
|
27
|
-
start(): Promise<void>;
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=adapter.d.ts.map
|
package/lib/adapter.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAiB,OAAO,EAAE,MAAM,EAAyB,MAAM,SAAS,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EACV,mBAAmB,EAKpB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,cAAc,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAE9F,qBAAa,YAAa,SAAQ,OAAO,CAAC,QAAQ,CAAC;;IACjD,gBAAyB,YAAY,mCAAoC;gBAI7D,MAAM,EAAE,MAAM;IAI1B,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,QAAQ;IAiB/C,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAM9D,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAM;IAM9E,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAO;IAM1D,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,UAAO;IAM3E,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAMvF,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAM9D,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;IAO/C,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAMhD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
|
package/lib/adapter.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Milky 适配器:单一适配器支持 WS 正向 / SSE / Webhook / 反向 WS,由 config.connection 区分
|
|
3
|
-
*/
|
|
4
|
-
import { Adapter } from 'zhin.js';
|
|
5
|
-
import { MilkyWsClient } from './endpoint-ws.js';
|
|
6
|
-
import { MilkySseClient } from './endpoint-sse.js';
|
|
7
|
-
import { MilkyWebhookEndpoint } from './endpoint-webhook.js';
|
|
8
|
-
import { MilkyWssServer } from './endpoint-wss.js';
|
|
9
|
-
export class MilkyAdapter extends Adapter {
|
|
10
|
-
static capabilities = ['inbound', 'outbound'];
|
|
11
|
-
#router;
|
|
12
|
-
constructor(plugin) {
|
|
13
|
-
super(plugin, 'milky', []);
|
|
14
|
-
}
|
|
15
|
-
createEndpoint(config) {
|
|
16
|
-
switch (config.connection) {
|
|
17
|
-
case 'ws':
|
|
18
|
-
return new MilkyWsClient(this, config);
|
|
19
|
-
case 'sse':
|
|
20
|
-
return new MilkySseClient(this, config);
|
|
21
|
-
case 'webhook':
|
|
22
|
-
if (!this.#router)
|
|
23
|
-
throw new Error('Milky connection: webhook 需要 router,请安装并在配置中启用 @zhin.js/host-router');
|
|
24
|
-
return new MilkyWebhookEndpoint(this, this.#router, config);
|
|
25
|
-
case 'wss':
|
|
26
|
-
if (!this.#router)
|
|
27
|
-
throw new Error('Milky connection: wss 需要 router,请安装并在配置中启用 @zhin.js/host-router');
|
|
28
|
-
return new MilkyWssServer(this, this.#router, config);
|
|
29
|
-
default:
|
|
30
|
-
throw new Error(`Unknown Milky connection: ${config.connection}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
async kickMember(endpointId, sceneId, userId) {
|
|
34
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
35
|
-
if (!endpoint)
|
|
36
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
37
|
-
return endpoint.kickMember(Number(sceneId), Number(userId), false);
|
|
38
|
-
}
|
|
39
|
-
async muteMember(endpointId, sceneId, userId, duration = 600) {
|
|
40
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
41
|
-
if (!endpoint)
|
|
42
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
43
|
-
return endpoint.muteMember(Number(sceneId), Number(userId), duration);
|
|
44
|
-
}
|
|
45
|
-
async muteAll(endpointId, sceneId, enable = true) {
|
|
46
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
47
|
-
if (!endpoint)
|
|
48
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
49
|
-
return endpoint.muteAll(Number(sceneId), enable);
|
|
50
|
-
}
|
|
51
|
-
async setAdmin(endpointId, sceneId, userId, enable = true) {
|
|
52
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
53
|
-
if (!endpoint)
|
|
54
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
55
|
-
return endpoint.setAdmin(Number(sceneId), Number(userId), enable);
|
|
56
|
-
}
|
|
57
|
-
async setMemberNickname(endpointId, sceneId, userId, nickname) {
|
|
58
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
59
|
-
if (!endpoint)
|
|
60
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
61
|
-
return endpoint.setCard(Number(sceneId), Number(userId), nickname);
|
|
62
|
-
}
|
|
63
|
-
async setGroupName(endpointId, sceneId, name) {
|
|
64
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
65
|
-
if (!endpoint)
|
|
66
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
67
|
-
return endpoint.setGroupName(Number(sceneId), name);
|
|
68
|
-
}
|
|
69
|
-
async listMembers(endpointId, sceneId) {
|
|
70
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
71
|
-
if (!endpoint)
|
|
72
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
73
|
-
const members = await endpoint.getMemberList(Number(sceneId));
|
|
74
|
-
return { members: Array.isArray(members) ? members : [], count: Array.isArray(members) ? members.length : 0 };
|
|
75
|
-
}
|
|
76
|
-
async getGroupInfo(endpointId, sceneId) {
|
|
77
|
-
const endpoint = this.endpoints.get(endpointId);
|
|
78
|
-
if (!endpoint)
|
|
79
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
80
|
-
return endpoint.getGroupInfo(Number(sceneId));
|
|
81
|
-
}
|
|
82
|
-
async start() {
|
|
83
|
-
// 同步获取已就绪的 router,或通过 useContext 在 router 挂载后赋值
|
|
84
|
-
this.#router = this.plugin.inject('router');
|
|
85
|
-
this.plugin.useContext('router', (router) => {
|
|
86
|
-
this.#router = router;
|
|
87
|
-
});
|
|
88
|
-
await super.start();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=adapter.js.map
|
package/lib/adapter.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/lib/api.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export interface MilkyApiClientOptions {
|
|
2
|
-
baseUrl: string;
|
|
3
|
-
access_token?: string;
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* 调用协议端 API:POST {baseUrl}/api/{apiName},Body JSON,鉴权。
|
|
7
|
-
* 非 200 或 retcode !== 0 时抛错。
|
|
8
|
-
*/
|
|
9
|
-
export declare function callApi<T = unknown>(options: MilkyApiClientOptions, apiName: string, params?: Record<string, unknown>): Promise<T>;
|
|
10
|
-
//# sourceMappingURL=api.d.ts.map
|