@zhin.js/adapter-onebot11 6.0.2 → 6.0.5

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.
@@ -8,9 +8,10 @@ import {
8
8
  type EndpointInstance,
9
9
  type EndpointLifecycle,
10
10
  type EndpointManagement,
11
+ type EndpointSendRequest,
11
12
  } from '@zhin.js/adapter';
12
13
  import type { MessageGateway } from '@zhin.js/core/runtime';
13
- import { formatCompact, getLogger } from '@zhin.js/logger';
14
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
14
15
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
15
16
  import { createOneBot11EndpointManagement } from './endpoint-management.js';
16
17
  import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
@@ -19,9 +20,10 @@ import {
19
20
  buildWsConnectOptions,
20
21
  formatInboundContent,
21
22
  formatInboundMetadata,
22
- formatInboundTarget,
23
23
  formatOutboundSegments,
24
24
  isMessageEvent,
25
+ onebot11InboundConversation,
26
+ senderDisplayName,
25
27
  senderUserId,
26
28
  type OneBot11Event,
27
29
  type OneBot11WsConfig,
@@ -37,8 +39,6 @@ import {
37
39
  type OneBot11WsSocket,
38
40
  } from './ws-types.js';
39
41
 
40
- const logger = getLogger('onebot11');
41
-
42
42
  export interface OneBot11WsEndpointOptions {
43
43
  readonly id: CapabilityId;
44
44
  readonly gateway: MessageGateway;
@@ -50,6 +50,8 @@ export interface OneBot11WsEndpointOptions {
50
50
  }
51
51
 
52
52
  export class OneBot11WsEndpoint implements EndpointInstance {
53
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
54
+
53
55
  readonly #options: OneBot11WsEndpointOptions;
54
56
  readonly management: EndpointManagement = createOneBot11EndpointManagement(this);
55
57
  readonly #lifecycle: EndpointLifecycle;
@@ -60,10 +62,11 @@ export class OneBot11WsEndpoint implements EndpointInstance {
60
62
  #unregisterAgent?: () => void;
61
63
 
62
64
  constructor(options: OneBot11WsEndpointOptions) {
65
+ this.#logger = getAdapterLogger('onebot11', options.config.id);
63
66
  this.#options = options;
64
67
  const { config } = options;
65
68
  this.#lifecycle = createEndpointLifecycle({
66
- name: config.name,
69
+ name: config.id,
67
70
  reconnect: {
68
71
  initialIntervalMs: config.reconnect_interval,
69
72
  // 固定间隔(multiplier 1、无抖动),对齐旧 reconnect_interval 语义
@@ -78,7 +81,7 @@ export class OneBot11WsEndpoint implements EndpointInstance {
78
81
  async start(): Promise<void> {
79
82
  if (this.#lifecycle.started) return;
80
83
  // agent 注册/反注册是适配器专有依赖,留在适配器侧(见 endpoint-lifecycle 迁移指引)
81
- this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.name, this);
84
+ this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
82
85
  try {
83
86
  await this.#lifecycle.start((handle) => this.#connect(handle));
84
87
  } catch (err) {
@@ -115,15 +118,15 @@ export class OneBot11WsEndpoint implements EndpointInstance {
115
118
  this.#ws = undefined;
116
119
  }
117
120
 
118
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
121
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
119
122
  const message = formatOutboundSegments(payload);
120
- const { action, params } = buildSendAction(target, message);
123
+ const { action, params } = buildSendAction(conversation, message);
121
124
  const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
122
125
  const messageId = data?.message_id != null ? String(data.message_id) : '';
123
- logger.debug(formatCompact({
126
+ this.#logger.debug(formatCompact({
124
127
  op: 'onebot11_send',
125
- endpoint: this.#options.config.name,
126
- target,
128
+ endpoint: this.#options.config.id,
129
+ target: `${conversation.kind}:${conversation.id}`,
127
130
  messageId,
128
131
  }));
129
132
  return messageId;
@@ -157,19 +160,26 @@ export class OneBot11WsEndpoint implements EndpointInstance {
157
160
  /** Test / internal: admit a parsed event when the endpoint is open. */
158
161
  admit(ev: OneBot11Event): void {
159
162
  if (!this.#open || !isMessageEvent(ev)) return;
160
- const target = formatInboundTarget(ev);
163
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
161
164
  const content = formatInboundContent(ev);
165
+ const inbound = formatInboundMetadata(ev, this.#options.config.id);
162
166
  void this.#options.gateway.receive({
163
- adapter: this.#options.id,
164
- target,
167
+ conversation,
168
+ message: { conversation, id: String(ev.message_id) },
165
169
  content,
166
- sender: senderUserId(ev),
167
- id: String(ev.message_id),
168
- metadata: formatInboundMetadata(ev, this.#options.config.name),
170
+ sender: {
171
+ id: senderUserId(ev),
172
+ name: senderDisplayName(ev) || undefined,
173
+ ...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
174
+ },
175
+ endpointId: inbound.endpointId,
176
+ ...(inbound.mentioned ? { mentioned: true } : {}),
177
+ ...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
178
+ metadata: inbound.metadata,
169
179
  }).catch((err) => {
170
- logger.warn(formatCompact({
180
+ this.#logger.warn(formatCompact({
171
181
  op: 'onebot11_gateway_receive_failed',
172
- target,
182
+ target: `${conversation.kind}:${conversation.id}`,
173
183
  error: err instanceof Error ? err.message : String(err),
174
184
  }));
175
185
  });
@@ -197,14 +207,14 @@ export class OneBot11WsEndpoint implements EndpointInstance {
197
207
  if (settled) return;
198
208
  settled = true;
199
209
  if (!this.#options.config.access_token) {
200
- logger.warn(formatCompact({
201
- endpoint: this.#options.config.name,
210
+ this.#logger.warn(formatCompact({
211
+ endpoint: this.#options.config.id,
202
212
  ok: false,
203
213
  error: 'missing access_token',
204
214
  }));
205
215
  }
206
- logger.debug(formatCompact({
207
- endpoint: this.#options.config.name,
216
+ this.#logger.debug(formatCompact({
217
+ endpoint: this.#options.config.id,
208
218
  mode: 'ws',
209
219
  url: safeUrl,
210
220
  }));
@@ -214,7 +224,7 @@ export class OneBot11WsEndpoint implements EndpointInstance {
214
224
 
215
225
  ws.on('message', (data) => {
216
226
  handleOneBot11WsMessage(data, {
217
- endpointName: this.#options.config.name,
227
+ endpointId: this.#options.config.id,
218
228
  pending: this.#pending,
219
229
  admit: (ev) => this.admit(ev),
220
230
  });
@@ -243,9 +253,9 @@ export class OneBot11WsEndpoint implements EndpointInstance {
243
253
 
244
254
  ws.on('error', (err) => {
245
255
  const error = err instanceof Error ? err : new Error(String(err));
246
- logger.warn(formatCompact({
256
+ this.#logger.warn(formatCompact({
247
257
  op: 'ws_error',
248
- endpoint: this.#options.config.name,
258
+ endpoint: this.#options.config.id,
249
259
  ok: false,
250
260
  error: error.message,
251
261
  }));
@@ -23,7 +23,7 @@ export function decodeWsPayload(data: unknown): string {
23
23
  export function handleOneBot11WsMessage(
24
24
  data: unknown,
25
25
  options: {
26
- readonly endpointName: string;
26
+ readonly endpointId: string;
27
27
  readonly pending: Map<string, OneBot11PendingAction>;
28
28
  readonly admit: (ev: OneBot11Event) => void;
29
29
  },
@@ -46,7 +46,7 @@ export function handleOneBot11WsMessage(
46
46
  } catch (error) {
47
47
  logger.warn(formatCompact({
48
48
  op: 'onebot11_parse_failed',
49
- endpoint: options.endpointName,
49
+ endpoint: options.endpointId,
50
50
  error: error instanceof Error ? error.message : String(error),
51
51
  }));
52
52
  }
@@ -2,10 +2,10 @@
2
2
  * OneBot11 reverse WSS endpoint — accepts inbound WebSocket from OneBot implementation.
3
3
  */
4
4
  import { clearInterval } from 'node:timers';
5
- import type { EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
5
+ import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
6
6
  import type { MessageGateway } from '@zhin.js/core/runtime';
7
7
  import type { HttpHost, WsConnection } from '@zhin.js/host-http';
8
- import { formatCompact, getLogger } from '@zhin.js/logger';
8
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
9
9
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
10
10
  import { createOneBot11EndpointManagement } from './endpoint-management.js';
11
11
  import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
@@ -13,9 +13,10 @@ import {
13
13
  buildSendAction,
14
14
  formatInboundContent,
15
15
  formatInboundMetadata,
16
- formatInboundTarget,
17
16
  formatOutboundSegments,
18
17
  isMessageEvent,
18
+ onebot11InboundConversation,
19
+ senderDisplayName,
19
20
  senderUserId,
20
21
  type OneBot11Event,
21
22
  type OneBot11WssConfig,
@@ -33,8 +34,6 @@ import {
33
34
  type OneBot11WsSocket,
34
35
  } from './ws-types.js';
35
36
 
36
- const logger = getLogger('onebot11');
37
-
38
37
  export interface OneBot11WssEndpointOptions {
39
38
  readonly id: CapabilityId;
40
39
  readonly gateway: MessageGateway;
@@ -43,6 +42,8 @@ export interface OneBot11WssEndpointOptions {
43
42
  }
44
43
 
45
44
  export class OneBot11WssEndpoint implements EndpointInstance {
45
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
46
+
46
47
  readonly #options: OneBot11WssEndpointOptions;
47
48
  readonly management: EndpointManagement = createOneBot11EndpointManagement(this);
48
49
  #ws?: OneBot11WsSocket;
@@ -55,6 +56,7 @@ export class OneBot11WssEndpoint implements EndpointInstance {
55
56
  #unregisterAgent?: () => void;
56
57
 
57
58
  constructor(options: OneBot11WssEndpointOptions) {
59
+ this.#logger = getAdapterLogger('onebot11', options.config.id);
58
60
  this.#options = options;
59
61
  }
60
62
 
@@ -63,24 +65,24 @@ export class OneBot11WssEndpoint implements EndpointInstance {
63
65
  this.#started = true;
64
66
  if (!this.#options.config.access_token) {
65
67
  // wss 模式未配 access_token 时任何连接都会被放行(verifyOneBotAccessToken 直接 return true)
66
- logger.warn(formatCompact({
67
- endpoint: this.#options.config.name,
68
+ this.#logger.warn(formatCompact({
69
+ endpoint: this.#options.config.id,
68
70
  mode: 'wss',
69
71
  ok: false,
70
72
  error: 'missing access_token',
71
73
  }));
72
74
  }
73
75
  this.#unregisterAgent = registerOnebot11AgentEndpoint(
74
- this.#options.config.name,
76
+ this.#options.config.id,
75
77
  this as unknown as OneBot11WsEndpoint,
76
78
  );
77
79
  const handle = this.#options.http.ws(this.#options.config.path);
78
80
  this.#wsRelease = handle.onConnection((connection) => {
79
81
  this.#acceptConnection(connection);
80
82
  });
81
- logger.info(formatCompact({
83
+ this.#logger.info(formatCompact({
82
84
  op: 'listen',
83
- endpoint: this.#options.config.name,
85
+ endpoint: this.#options.config.id,
84
86
  mode: 'wss',
85
87
  path: this.#options.config.path,
86
88
  }));
@@ -116,9 +118,9 @@ export class OneBot11WssEndpoint implements EndpointInstance {
116
118
  this.#started = false;
117
119
  }
118
120
 
119
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
121
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
120
122
  const message = formatOutboundSegments(payload);
121
- const { action, params } = buildSendAction(target, message);
123
+ const { action, params } = buildSendAction(conversation, message);
122
124
  const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
123
125
  return data?.message_id != null ? String(data.message_id) : '';
124
126
  }
@@ -144,18 +146,25 @@ export class OneBot11WssEndpoint implements EndpointInstance {
144
146
 
145
147
  admit(ev: OneBot11Event): void {
146
148
  if (!this.#open || !isMessageEvent(ev)) return;
147
- const target = formatInboundTarget(ev);
149
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
150
+ const inbound = formatInboundMetadata(ev, this.#options.config.id);
148
151
  void this.#options.gateway.receive({
149
- adapter: this.#options.id,
150
- target,
152
+ conversation,
153
+ message: { conversation, id: String(ev.message_id) },
151
154
  content: formatInboundContent(ev),
152
- sender: senderUserId(ev),
153
- id: String(ev.message_id),
154
- metadata: formatInboundMetadata(ev, this.#options.config.name),
155
+ sender: {
156
+ id: senderUserId(ev),
157
+ name: senderDisplayName(ev) || undefined,
158
+ ...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
159
+ },
160
+ endpointId: inbound.endpointId,
161
+ ...(inbound.mentioned ? { mentioned: true } : {}),
162
+ ...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
163
+ metadata: inbound.metadata,
155
164
  }).catch((err) => {
156
- logger.warn(formatCompact({
165
+ this.#logger.warn(formatCompact({
157
166
  op: 'onebot11_gateway_receive_failed',
158
- target,
167
+ target: `${conversation.kind}:${conversation.id}`,
159
168
  error: err instanceof Error ? err.message : String(err),
160
169
  }));
161
170
  });
@@ -182,7 +191,7 @@ export class OneBot11WssEndpoint implements EndpointInstance {
182
191
  );
183
192
  socket.on('message', (data) => {
184
193
  handleOneBot11WsMessage(data, {
185
- endpointName: this.#options.config.name,
194
+ endpointId: this.#options.config.id,
186
195
  pending: this.#pending,
187
196
  admit: (ev) => this.admit(ev),
188
197
  });
@@ -196,8 +205,8 @@ export class OneBot11WssEndpoint implements EndpointInstance {
196
205
  }
197
206
  }
198
207
  });
199
- logger.debug(formatCompact({
200
- endpoint: this.#options.config.name,
208
+ this.#logger.debug(formatCompact({
209
+ endpoint: this.#options.config.id,
201
210
  mode: 'wss',
202
211
  peer: connection.request.socket.remoteAddress,
203
212
  }));