@zhin.js/adapter-onebot12 5.0.1 → 5.0.4

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.
@@ -2,13 +2,13 @@
2
2
  * OneBot12 reverse WSS endpoint — accepts inbound WebSocket from OneBot implementation.
3
3
  */
4
4
  import { clearInterval } from 'node:timers';
5
- import { formatCompact, getLogger } from '@zhin.js/logger';
5
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
6
6
  import { createOneBot12EndpointManagement } from './endpoint-management.js';
7
- import { buildSendMessageParams, formatInboundContent, formatInboundTarget, formatOutboundSegments, isBotMentioned, isMessageEvent, senderNickname, senderUserId, uploadOneBot12MediaSegments, } from './protocol.js';
7
+ import { buildSendMessageParams, formatInboundContent, formatOutboundSegments, isBotMentioned, isMessageEvent, onebot12InboundConversation, senderNickname, senderUserId, uploadOneBot12MediaSegments, } from './protocol.js';
8
8
  import { verifyOneBotAccessToken } from './wss-auth.js';
9
9
  import { WS_OPEN } from './ws-types.js';
10
- const logger = getLogger('onebot12');
11
10
  export class OneBot12WssEndpoint {
11
+ #logger;
12
12
  #options;
13
13
  management = createOneBot12EndpointManagement(this);
14
14
  #ws;
@@ -19,6 +19,7 @@ export class OneBot12WssEndpoint {
19
19
  #open = false;
20
20
  #started = false;
21
21
  constructor(options) {
22
+ this.#logger = getAdapterLogger('onebot12', options.config.id);
22
23
  this.#options = options;
23
24
  }
24
25
  async start() {
@@ -27,8 +28,8 @@ export class OneBot12WssEndpoint {
27
28
  this.#started = true;
28
29
  if (!this.#options.config.access_token) {
29
30
  // wss 模式未配 access_token 时任何连接都会被放行(verifyOneBotAccessToken 直接 return true)
30
- logger.warn(formatCompact({
31
- endpoint: this.#options.config.name,
31
+ this.#logger.warn(formatCompact({
32
+ endpoint: this.#options.config.id,
32
33
  mode: 'wss',
33
34
  ok: false,
34
35
  error: 'missing access_token',
@@ -38,9 +39,9 @@ export class OneBot12WssEndpoint {
38
39
  this.#wsRelease = handle.onConnection((connection) => {
39
40
  this.#acceptConnection(connection);
40
41
  });
41
- logger.info(formatCompact({
42
+ this.#logger.info(formatCompact({
42
43
  op: 'listen',
43
- endpoint: this.#options.config.name,
44
+ endpoint: this.#options.config.id,
44
45
  mode: 'wss',
45
46
  path: this.#options.config.path,
46
47
  }));
@@ -75,16 +76,16 @@ export class OneBot12WssEndpoint {
75
76
  }
76
77
  this.#started = false;
77
78
  }
78
- async send({ target, payload }) {
79
+ async send({ conversation, payload }) {
79
80
  const materialized = await uploadOneBot12MediaSegments(payload, (action, params) => this.callApi(action, params), (error) => {
80
- logger.warn(formatCompact({
81
+ this.#logger.warn(formatCompact({
81
82
  op: 'onebot12_upload_failed',
82
- endpoint: this.#options.config.name,
83
+ endpoint: this.#options.config.id,
83
84
  error: error instanceof Error ? error.message : String(error),
84
85
  }));
85
86
  });
86
87
  const message = formatOutboundSegments(materialized);
87
- const params = buildSendMessageParams(target, message);
88
+ const params = buildSendMessageParams(conversation, message);
88
89
  const data = await this.#callAction('send_message', params);
89
90
  return data?.message_id ?? '';
90
91
  }
@@ -100,30 +101,30 @@ export class OneBot12WssEndpoint {
100
101
  admit(ev) {
101
102
  if (!this.#open || !isMessageEvent(ev))
102
103
  return;
103
- const target = formatInboundTarget(ev);
104
+ const conversation = onebot12InboundConversation(String(this.#options.id), ev);
104
105
  const nickname = senderNickname(ev);
105
106
  const mentioned = isBotMentioned(ev);
106
107
  void this.#options.gateway.receive({
107
- adapter: this.#options.id,
108
- target,
108
+ conversation,
109
+ message: { conversation, id: ev.message_id },
109
110
  content: formatInboundContent(ev),
110
- sender: senderUserId(ev),
111
- id: ev.message_id,
111
+ sender: { id: senderUserId(ev), name: senderNickname(ev) },
112
+ endpointId: this.#options.config.id,
113
+ ...(mentioned ? { mentioned: true } : {}),
112
114
  metadata: Object.freeze({
113
115
  detail_type: ev.detail_type,
114
116
  user_id: ev.user_id,
115
117
  group_id: ev.group_id,
116
118
  channel_id: ev.channel_id,
117
119
  guild_id: ev.guild_id,
118
- endpoint: this.#options.config.name,
119
120
  time: ev.time,
120
121
  ...(nickname ? { nickname } : {}),
121
- ...(mentioned ? { mentioned: true } : {}),
122
122
  }),
123
123
  }).catch((err) => {
124
- logger.warn(formatCompact({
124
+ this.#logger.warn(formatCompact({
125
125
  op: 'onebot12_gateway_receive_failed',
126
- target,
126
+ kind: conversation.kind,
127
+ conversationId: conversation.id,
127
128
  error: err instanceof Error ? err.message : String(err),
128
129
  }));
129
130
  });
@@ -156,8 +157,8 @@ export class OneBot12WssEndpoint {
156
157
  }
157
158
  }
158
159
  });
159
- logger.debug(formatCompact({
160
- endpoint: this.#options.config.name,
160
+ this.#logger.debug(formatCompact({
161
+ endpoint: this.#options.config.id,
161
162
  mode: 'wss',
162
163
  peer: connection.request.socket.remoteAddress,
163
164
  }));
@@ -188,9 +189,9 @@ export class OneBot12WssEndpoint {
188
189
  this.admit(msg);
189
190
  }
190
191
  catch (error) {
191
- logger.warn(formatCompact({
192
+ this.#logger.warn(formatCompact({
192
193
  op: 'onebot12_parse_failed',
193
- endpoint: this.#options.config.name,
194
+ endpoint: this.#options.config.id,
194
195
  error: error instanceof Error ? error.message : String(error),
195
196
  }));
196
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-onebot12",
3
- "version": "5.0.1",
3
+ "version": "5.0.4",
4
4
  "description": "Zhin.js OneBot 12 adapter for Plugin Runtime (WebSocket client)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -40,25 +40,26 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "ws": "^8.21.1",
43
- "@zhin.js/adapter": "1.1.4",
44
- "@zhin.js/command": "1.0.6",
45
- "@zhin.js/core": "1.5.1",
46
- "@zhin.js/host-http": "1.0.5",
47
- "@zhin.js/logger": "1.0.75",
48
- "@zhin.js/plugin-runtime": "1.1.2"
43
+ "@zhin.js/adapter": "1.1.7",
44
+ "@zhin.js/command": "1.0.9",
45
+ "@zhin.js/core": "1.5.4",
46
+ "@zhin.js/host-http": "1.0.8",
47
+ "@zhin.js/im-contract": "1.0.3",
48
+ "@zhin.js/logger": "1.0.76",
49
+ "@zhin.js/plugin-runtime": "1.1.5"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@types/node": "^26.1.2",
52
53
  "@types/ws": "^8.18.1",
53
54
  "typescript": "^6.0.3",
54
55
  "vitest": "^4.1.10",
55
- "@zhin.js/host-http": "1.0.5"
56
+ "@zhin.js/host-http": "1.0.8"
56
57
  },
57
58
  "peerDependencies": {
58
- "@zhin.js/adapter": "1.1.4",
59
- "@zhin.js/core": "1.5.1",
60
- "@zhin.js/plugin-runtime": "1.1.2",
61
- "zhin.js": "6.0.1"
59
+ "@zhin.js/adapter": "1.1.7",
60
+ "@zhin.js/core": "1.5.4",
61
+ "@zhin.js/plugin-runtime": "1.1.5",
62
+ "zhin.js": "6.0.4"
62
63
  },
63
64
  "peerDependenciesMeta": {
64
65
  "zhin.js": {
package/schema.json CHANGED
@@ -21,16 +21,48 @@
21
21
  "type": "number",
22
22
  "default": 30000
23
23
  },
24
+ "master": {
25
+ "type": [
26
+ "string",
27
+ "number"
28
+ ],
29
+ "description": "框架 master(platform user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
30
+ },
31
+ "trusted": {
32
+ "type": "array",
33
+ "items": {
34
+ "type": [
35
+ "string",
36
+ "number"
37
+ ],
38
+ "description": "Trusted platform user id"
39
+ },
40
+ "description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
41
+ },
24
42
  "endpoints": {
25
43
  "type": "array",
26
- "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(name 必填,其余覆盖顶层)",
44
+ "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
27
45
  "items": {
28
46
  "type": "object",
29
47
  "additionalProperties": true,
30
48
  "properties": {
31
- "name": {
32
- "type": "string",
33
- "description": "OneBot12 bot name"
49
+ "master": {
50
+ "type": [
51
+ "string",
52
+ "number"
53
+ ],
54
+ "description": "本 endpoint 的框架 master(platform user id);覆盖顶层 master"
55
+ },
56
+ "trusted": {
57
+ "type": "array",
58
+ "items": {
59
+ "type": [
60
+ "string",
61
+ "number"
62
+ ],
63
+ "description": "Trusted platform user id"
64
+ },
65
+ "description": "本 endpoint 的 trusted 列表"
34
66
  },
35
67
  "url": {
36
68
  "type": "string",
@@ -47,10 +79,14 @@
47
79
  "access_token": {
48
80
  "type": "string",
49
81
  "description": "OneBot access token"
82
+ },
83
+ "id": {
84
+ "type": "string",
85
+ "description": "OneBot12 bot name"
50
86
  }
51
87
  },
52
88
  "required": [
53
- "name"
89
+ "id"
54
90
  ]
55
91
  }
56
92
  },
package/src/index.ts CHANGED
@@ -3,14 +3,13 @@ export {
3
3
  buildWsConnectOptions,
4
4
  callOneBot12Action,
5
5
  formatInboundContent,
6
- formatInboundTarget,
7
6
  formatOutboundSegments,
8
7
  getChannelId,
9
8
  isBotMentioned,
10
9
  isMessageEvent,
11
10
  mediaRefToOneBot12Fields,
12
11
  mediaRefToOneBot12UploadParams,
13
- parseSendTarget,
12
+ onebot12InboundConversation,
14
13
  resolveOneBot12Config,
15
14
  senderNickname,
16
15
  senderUserId,
@@ -29,7 +28,6 @@ export {
29
28
  type OneBot12WireSegment,
30
29
  type OneBot12WsConfig,
31
30
  type OneBot12WssConfig,
32
- type ParsedSendTarget,
33
31
  type ResolvedOneBot12Config,
34
32
  } from './protocol.js';
35
33
 
package/src/protocol.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * Spec: https://12.onebot.dev/
5
5
  */
6
6
  import { isMediaRef, type MediaRef } from '@zhin.js/core';
7
+ import type { ConversationRef } from '@zhin.js/im-contract';
7
8
  import { formatCompact, getLogger } from '@zhin.js/logger';
8
9
 
9
10
  const logger = getLogger('onebot12');
@@ -12,7 +13,7 @@ const logger = getLogger('onebot12');
12
13
  export interface OneBot12LegacyEndpointRow {
13
14
  readonly context?: string;
14
15
  readonly connection?: 'ws' | 'webhook' | 'wss';
15
- readonly name?: string;
16
+ readonly id?: string;
16
17
  readonly access_token?: string;
17
18
  readonly url?: string;
18
19
  readonly path?: string;
@@ -24,7 +25,7 @@ export interface OneBot12LegacyEndpointRow {
24
25
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
25
26
  export interface OneBot12AdapterConfig {
26
27
  readonly connection?: 'ws' | 'webhook' | 'wss';
27
- readonly name?: string;
28
+ readonly id?: string;
28
29
  readonly access_token?: string;
29
30
  readonly url?: string;
30
31
  readonly path?: string;
@@ -37,7 +38,7 @@ export interface OneBot12AdapterConfig {
37
38
 
38
39
  export interface OneBot12ConfigBase {
39
40
  readonly context: 'onebot12';
40
- readonly name: string;
41
+ readonly id: string;
41
42
  readonly access_token?: string;
42
43
  }
43
44
 
@@ -118,19 +119,13 @@ export interface OneBot12WireSegment {
118
119
  readonly data?: Record<string, unknown>;
119
120
  }
120
121
 
121
- export interface ParsedSendTarget {
122
- readonly detail_type: 'private' | 'group' | 'channel';
123
- readonly id: string;
124
- readonly guild_id?: string;
125
- }
126
-
127
122
  export function resolveOneBot12Config(config: OneBot12AdapterConfig = {}): ResolvedOneBot12Config {
128
123
  const entry = config.endpoints?.find((item) => item.context === 'onebot12');
129
124
  const connection = config.connection
130
125
  ?? entry?.connection
131
126
  ?? 'ws';
132
- const name = (typeof config.name === 'string' && config.name)
133
- || (typeof entry?.name === 'string' && entry.name)
127
+ const id = (typeof config.id === 'string' && config.id)
128
+ || (typeof entry?.id === 'string' && entry.id)
134
129
  || process.env.ONEBOT12_BOT_NAME
135
130
  || 'onebot12-bot';
136
131
  const access_token = config.access_token ?? entry?.access_token;
@@ -145,7 +140,7 @@ export function resolveOneBot12Config(config: OneBot12AdapterConfig = {}): Resol
145
140
  return {
146
141
  context: 'onebot12',
147
142
  connection: 'ws',
148
- name,
143
+ id,
149
144
  access_token,
150
145
  url,
151
146
  reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
@@ -161,7 +156,7 @@ export function resolveOneBot12Config(config: OneBot12AdapterConfig = {}): Resol
161
156
  return {
162
157
  context: 'onebot12',
163
158
  connection: 'webhook',
164
- name,
159
+ id,
165
160
  access_token,
166
161
  path,
167
162
  api_url: config.api_url ?? entry?.api_url,
@@ -176,7 +171,7 @@ export function resolveOneBot12Config(config: OneBot12AdapterConfig = {}): Resol
176
171
  return {
177
172
  context: 'onebot12',
178
173
  connection: 'wss',
179
- name,
174
+ id,
180
175
  access_token,
181
176
  path,
182
177
  heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
@@ -204,37 +199,31 @@ export function getChannelId(ev: OneBot12Event): string {
204
199
  }
205
200
 
206
201
  /**
207
- * Gateway reply target:`detail_type:channelId`,便于 send() 还原动作参数。
202
+ * 入站归一化 → ConversationRef:`detail_type` 直映射 kind;channel 的 guild 容器
203
+ * 进 `parent`(kind 'channel');私聊临时会话(private 事件携带 group_id)映射为
204
+ * group 容器内的 private 会话。
208
205
  */
209
- export function formatInboundTarget(ev: OneBot12Event): string {
210
- const detail = ev.detail_type === 'private' || ev.detail_type === 'group' || ev.detail_type === 'channel'
211
- ? ev.detail_type
212
- : 'private';
213
- return `${detail}:${getChannelId(ev)}`;
214
- }
215
-
216
- export function parseSendTarget(target: string): ParsedSendTarget {
217
- const sep = target.indexOf(':');
218
- if (sep <= 0) {
219
- return { detail_type: 'private', id: target };
220
- }
221
- const head = target.slice(0, sep);
222
- const rest = target.slice(sep + 1);
223
- if (head === 'private' || head === 'group') {
224
- return { detail_type: head, id: rest };
206
+ export function onebot12InboundConversation(endpointKey: string, ev: OneBot12Event): ConversationRef {
207
+ const endpoint = { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey };
208
+ if (ev.detail_type === 'group' && ev.group_id) {
209
+ return { endpoint, kind: 'group', id: ev.group_id };
225
210
  }
226
- if (head === 'channel') {
227
- const guildSep = rest.indexOf(':');
228
- if (guildSep > 0) {
229
- return {
230
- detail_type: 'channel',
231
- guild_id: rest.slice(0, guildSep),
232
- id: rest.slice(guildSep + 1),
233
- };
234
- }
235
- return { detail_type: 'channel', id: rest };
211
+ if (ev.detail_type === 'channel' && ev.channel_id) {
212
+ return {
213
+ endpoint,
214
+ kind: 'channel',
215
+ id: ev.channel_id,
216
+ ...(ev.guild_id ? { parent: { kind: 'channel' as const, id: ev.guild_id } } : {}),
217
+ };
236
218
  }
237
- return { detail_type: 'private', id: target };
219
+ return {
220
+ endpoint,
221
+ kind: 'private',
222
+ id: ev.user_id ?? ev.group_id ?? '',
223
+ ...(ev.detail_type === 'private' && ev.group_id
224
+ ? { parent: { kind: 'group' as const, id: ev.group_id } }
225
+ : {}),
226
+ };
238
227
  }
239
228
 
240
229
  /** Build inbound text for MessageGateway.receive */
@@ -501,22 +490,25 @@ export async function uploadOneBot12MediaSegments(
501
490
  return uploadOneMediaSegment(payload, callAction, onUploadFailed);
502
491
  }
503
492
 
493
+ /**
494
+ * 结构化会话 → OB12 `send_message` 动作参数:kind 直映射 detail_type;
495
+ * channel 的 guild 容器取自 `conversation.parent`(kind 'channel')。
496
+ */
504
497
  export function buildSendMessageParams(
505
- target: string,
498
+ conversation: ConversationRef,
506
499
  message: OneBot12Segment[],
507
500
  ): Record<string, unknown> {
508
- const parsed = parseSendTarget(target);
509
501
  const params: Record<string, unknown> = {
510
502
  message,
511
- detail_type: parsed.detail_type,
503
+ detail_type: conversation.kind,
512
504
  };
513
- if (parsed.detail_type === 'private') {
514
- params.user_id = parsed.id;
515
- } else if (parsed.detail_type === 'group') {
516
- params.group_id = parsed.id;
505
+ if (conversation.kind === 'private') {
506
+ params.user_id = conversation.id;
507
+ } else if (conversation.kind === 'group') {
508
+ params.group_id = conversation.id;
517
509
  } else {
518
- params.channel_id = parsed.id;
519
- if (parsed.guild_id) params.guild_id = parsed.guild_id;
510
+ params.channel_id = conversation.id;
511
+ if (conversation.parent?.kind === 'channel') params.guild_id = conversation.parent.id;
520
512
  }
521
513
  return params;
522
514
  }
package/src/webhook.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * OneBot12 HTTP webhook endpoint — POST inbound + api_url outbound.
3
3
  */
4
4
  import type { IncomingMessage, ServerResponse } from 'node:http';
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, HttpRouteRegistration } from '@zhin.js/host-http';
8
8
  import { formatCompact, getLogger } from '@zhin.js/logger';
@@ -12,10 +12,10 @@ import {
12
12
  buildSendMessageParams,
13
13
  callOneBot12Action,
14
14
  formatInboundContent,
15
- formatInboundTarget,
16
15
  formatOutboundSegments,
17
16
  isBotMentioned,
18
17
  isMessageEvent,
18
+ onebot12InboundConversation,
19
19
  senderNickname,
20
20
  senderUserId,
21
21
  uploadOneBot12MediaSegments,
@@ -53,7 +53,7 @@ export class OneBot12WebhookEndpoint implements EndpointInstance {
53
53
  if (!this.#options.config.access_token) {
54
54
  // webhook 模式未配 access_token 时任何 POST 都会被放行(verifyOneBotAccessToken 直接 return true)
55
55
  logger.warn(formatCompact({
56
- endpoint: this.#options.config.name,
56
+ endpoint: this.#options.config.id,
57
57
  mode: 'webhook',
58
58
  ok: false,
59
59
  error: 'missing access_token',
@@ -62,7 +62,7 @@ export class OneBot12WebhookEndpoint implements EndpointInstance {
62
62
  this.#setupRoutes();
63
63
  logger.info(formatCompact({
64
64
  op: 'listen',
65
- endpoint: this.#options.config.name,
65
+ endpoint: this.#options.config.id,
66
66
  mode: 'webhook',
67
67
  path: this.#options.config.path,
68
68
  }));
@@ -80,29 +80,30 @@ export class OneBot12WebhookEndpoint implements EndpointInstance {
80
80
  this.#open = false;
81
81
  for (const release of this.#routeReleases.splice(0)) release();
82
82
  this.#started = false;
83
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
83
+ logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.id }));
84
84
  }
85
85
 
86
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
86
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
87
87
  const materialized = await uploadOneBot12MediaSegments(
88
88
  payload,
89
89
  (action, params) => this.callApi(action, params),
90
90
  (error) => {
91
91
  logger.warn(formatCompact({
92
92
  op: 'onebot12_upload_failed',
93
- endpoint: this.#options.config.name,
93
+ endpoint: this.#options.config.id,
94
94
  error: error instanceof Error ? error.message : String(error),
95
95
  }));
96
96
  },
97
97
  );
98
98
  const message = formatOutboundSegments(materialized);
99
- const params = buildSendMessageParams(target, message);
99
+ const params = buildSendMessageParams(conversation, message);
100
100
  const data = await this.callApi('send_message', params) as { message_id?: string } | undefined;
101
101
  const messageId = data?.message_id ?? '';
102
102
  logger.debug(formatCompact({
103
103
  op: 'onebot12_send',
104
- endpoint: this.#options.config.name,
105
- target,
104
+ endpoint: this.#options.config.id,
105
+ kind: conversation.kind,
106
+ conversationId: conversation.id,
106
107
  messageId,
107
108
  }));
108
109
  return messageId;
@@ -124,31 +125,31 @@ export class OneBot12WebhookEndpoint implements EndpointInstance {
124
125
 
125
126
  admit(ev: OneBot12Event): void {
126
127
  if (!this.#open || !isMessageEvent(ev)) return;
127
- const target = formatInboundTarget(ev);
128
+ const conversation = onebot12InboundConversation(String(this.#options.id), ev);
128
129
  const content = formatInboundContent(ev);
129
130
  const nickname = senderNickname(ev);
130
131
  const mentioned = isBotMentioned(ev);
131
132
  void this.#options.gateway.receive({
132
- adapter: this.#options.id,
133
- target,
133
+ conversation,
134
+ message: { conversation, id: ev.message_id },
134
135
  content,
135
- sender: senderUserId(ev),
136
- id: ev.message_id,
136
+ sender: { id: senderUserId(ev), ...(nickname ? { name: nickname } : {}) },
137
+ endpointId: this.#options.config.id,
138
+ ...(mentioned ? { mentioned: true } : {}),
137
139
  metadata: Object.freeze({
138
140
  detail_type: ev.detail_type,
139
141
  user_id: ev.user_id,
140
142
  group_id: ev.group_id,
141
143
  channel_id: ev.channel_id,
142
144
  guild_id: ev.guild_id,
143
- endpoint: this.#options.config.name,
144
145
  time: ev.time,
145
146
  ...(nickname ? { nickname } : {}),
146
- ...(mentioned ? { mentioned: true } : {}),
147
147
  }),
148
148
  }).catch((err) => {
149
149
  logger.warn(formatCompact({
150
150
  op: 'onebot12_gateway_receive_failed',
151
- target,
151
+ kind: conversation.kind,
152
+ conversationId: conversation.id,
152
153
  error: err instanceof Error ? err.message : String(err),
153
154
  }));
154
155
  });