@zhin.js/adapter-onebot11 6.0.3 → 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,84 @@
1
1
  # @zhin.js/adapter-onebot11
2
2
 
3
+ ## 6.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
8
+
9
+ All adapter platform-permit checkers now accept PermissionSubject
10
+ (duck-typed from Message/CommandSession) instead of Message directly.
11
+ registerPlatformPermitChecker is replaced by host.registerPlatform in
12
+ the adapter plugin setup. activity-feedback service updated for new
13
+ PermissionHost integration.
14
+
15
+ - Updated dependencies [6f9c366]
16
+ - Updated dependencies [373a56b]
17
+ - Updated dependencies [0de46a8]
18
+ - Updated dependencies [c106ecc]
19
+ - Updated dependencies [ca92e03]
20
+ - Updated dependencies [b0f37ae]
21
+ - Updated dependencies [ba08a2f]
22
+ - Updated dependencies [b08f7fe]
23
+ - Updated dependencies [daffd4c]
24
+ - Updated dependencies [36c7400]
25
+ - Updated dependencies [a9fa72e]
26
+ - Updated dependencies [c8de3ef]
27
+ - Updated dependencies [60f0fc8]
28
+ - Updated dependencies [574c990]
29
+ - Updated dependencies [d096f16]
30
+ - Updated dependencies [3f29623]
31
+ - Updated dependencies [2916852]
32
+ - Updated dependencies [d047869]
33
+ - Updated dependencies [162fa34]
34
+ - Updated dependencies [e62561e]
35
+ - Updated dependencies [3eeeb46]
36
+ - Updated dependencies [85d0f82]
37
+ - Updated dependencies [61bfc1c]
38
+ - Updated dependencies [04bad47]
39
+ - Updated dependencies [e40b048]
40
+ - Updated dependencies [5a5b1bb]
41
+ - Updated dependencies [f1708c3]
42
+ - Updated dependencies [d254a81]
43
+ - Updated dependencies [7123c47]
44
+ - Updated dependencies [05befc1]
45
+ - Updated dependencies [0663b6a]
46
+ - Updated dependencies [f28f9b3]
47
+ - Updated dependencies [9f340f7]
48
+ - Updated dependencies [e53444f]
49
+ - Updated dependencies [5eedd26]
50
+ - Updated dependencies [92b0dd7]
51
+ - Updated dependencies [f919b6f]
52
+ - Updated dependencies [098e411]
53
+ - Updated dependencies [e1b7c01]
54
+ - Updated dependencies [9b94f87]
55
+ - Updated dependencies [a7df753]
56
+ - @zhin.js/agent@1.1.5
57
+ - @zhin.js/host-http@1.0.8
58
+ - @zhin.js/permission@1.0.1
59
+ - @zhin.js/im-contract@1.0.3
60
+ - @zhin.js/adapter@1.1.7
61
+ - @zhin.js/plugin-runtime@1.1.5
62
+ - @zhin.js/command@1.0.9
63
+ - @zhin.js/core@1.5.4
64
+ - zhin.js@6.0.4
65
+
66
+ ## 6.0.4
67
+
68
+ ### Patch Changes
69
+
70
+ - f8c7a54: fix: im
71
+ - Updated dependencies [f8c7a54]
72
+ - @zhin.js/logger@1.0.76
73
+ - @zhin.js/host-http@1.0.7
74
+ - @zhin.js/adapter@1.1.6
75
+ - @zhin.js/agent@1.1.4
76
+ - @zhin.js/command@1.0.8
77
+ - @zhin.js/core@1.5.3
78
+ - @zhin.js/im-contract@1.0.2
79
+ - @zhin.js/plugin-runtime@1.1.4
80
+ - zhin.js@6.0.3
81
+
3
82
  ## 6.0.3
4
83
 
5
84
  ### Patch Changes
@@ -22,8 +22,8 @@ export default defineAdapter({
22
22
  const config = resolveOneBot11Config(context.config);
23
23
  const gateway = context.use(messageGatewayToken);
24
24
  // 注册到插件运行时状态(onebot11.endpoint list 的"运行中"数据源)
25
- context.use(onebot11RuntimeStateToken).endpoints.set(config.name, {
26
- name: config.name,
25
+ context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
26
+ id: config.id,
27
27
  mode: config.connection,
28
28
  });
29
29
  if (config.connection === 'wss') {
@@ -29,8 +29,8 @@ export default defineAdapter<OneBot11AdapterConfig>({
29
29
  const config = resolveOneBot11Config(context.config);
30
30
  const gateway = context.use(messageGatewayToken);
31
31
  // 注册到插件运行时状态(onebot11.endpoint list 的"运行中"数据源)
32
- context.use(onebot11RuntimeStateToken).endpoints.set(config.name, {
33
- name: config.name,
32
+ context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
33
+ id: config.id,
34
34
  mode: config.connection,
35
35
  });
36
36
  if (config.connection === 'wss') {
@@ -7,9 +7,9 @@ export interface Onebot11AgentEndpoint {
7
7
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
8
8
  }
9
9
  export interface Onebot11AgentDeps {
10
- getEndpoint: (endpointId: string) => Onebot11AgentEndpoint;
10
+ getEndpoint: (endpointKey: string) => Onebot11AgentEndpoint;
11
11
  }
12
- export declare function registerOnebot11AgentEndpoint(endpointId: string, endpoint: Onebot11AgentEndpoint): () => void;
12
+ export declare function registerOnebot11AgentEndpoint(endpointKey: string, endpoint: Onebot11AgentEndpoint): () => void;
13
13
  /** Optional override used by tests / transitional callers. */
14
14
  export declare function setOnebot11AgentDeps(deps: Onebot11AgentDeps): void;
15
15
  export declare function getOnebot11AgentDeps(): Onebot11AgentDeps;
@@ -4,11 +4,11 @@
4
4
  */
5
5
  const endpoints = new Map();
6
6
  let override = null;
7
- export function registerOnebot11AgentEndpoint(endpointId, endpoint) {
8
- endpoints.set(endpointId, endpoint);
7
+ export function registerOnebot11AgentEndpoint(endpointKey, endpoint) {
8
+ endpoints.set(endpointKey, endpoint);
9
9
  return () => {
10
- if (endpoints.get(endpointId) === endpoint) {
11
- endpoints.delete(endpointId);
10
+ if (endpoints.get(endpointKey) === endpoint) {
11
+ endpoints.delete(endpointKey);
12
12
  }
13
13
  };
14
14
  }
@@ -20,10 +20,10 @@ export function getOnebot11AgentDeps() {
20
20
  if (override)
21
21
  return override;
22
22
  return {
23
- getEndpoint(endpointId) {
24
- const registered = endpoints.get(endpointId);
23
+ getEndpoint(endpointKey) {
24
+ const registered = endpoints.get(endpointKey);
25
25
  if (!registered)
26
- throw new Error(`Endpoint ${endpointId} 不存在`);
26
+ throw new Error(`Endpoint ${endpointKey} 不存在`);
27
27
  return registered;
28
28
  },
29
29
  };
package/lib/protocol.d.ts CHANGED
@@ -11,7 +11,7 @@ export interface OneBot11LegacyEndpointRow {
11
11
  readonly connection?: 'ws' | 'wss';
12
12
  /** Legacy alias: `type: 'ws' | 'ws_reverse'` */
13
13
  readonly type?: string;
14
- readonly name?: string;
14
+ readonly id?: string;
15
15
  readonly access_token?: string;
16
16
  readonly url?: string;
17
17
  readonly path?: string;
@@ -21,7 +21,7 @@ export interface OneBot11LegacyEndpointRow {
21
21
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
22
22
  export interface OneBot11AdapterConfig {
23
23
  readonly connection?: 'ws' | 'wss';
24
- readonly name?: string;
24
+ readonly id?: string;
25
25
  readonly access_token?: string;
26
26
  readonly url?: string;
27
27
  readonly path?: string;
@@ -32,7 +32,7 @@ export interface OneBot11AdapterConfig {
32
32
  }
33
33
  export interface OneBot11ConfigBase {
34
34
  readonly context: 'onebot11';
35
- readonly name: string;
35
+ readonly id: string;
36
36
  readonly access_token?: string;
37
37
  }
38
38
  /** 正向 WebSocket:应用连 OneBot 实现的 WS 服务器 */
@@ -103,7 +103,7 @@ export declare function getChannelId(ev: OneBot11Event): string;
103
103
  * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
104
104
  * OneBot 11 无 guild/temp 容器概念,不填 parent。
105
105
  */
106
- export declare function onebot11InboundConversation(endpointId: string, ev: OneBot11Event): ConversationRef;
106
+ export declare function onebot11InboundConversation(endpointKey: string, ev: OneBot11Event): ConversationRef;
107
107
  /** Build inbound text for MessageGateway.receive */
108
108
  export declare function formatInboundContent(ev: OneBot11Event): string;
109
109
  export declare function senderDisplayName(ev: OneBot11Event): string;
@@ -124,8 +124,17 @@ export declare function isOneBot11BotMentioned(input: {
124
124
  readonly selfId: string | undefined;
125
125
  readonly message?: readonly OneBot11Segment[];
126
126
  }): boolean;
127
- /** 构造 gateway.receive 的 metadata(ws / wss 两个 endpoint 共用)。 */
128
- export declare function formatInboundMetadata(ev: OneBot11Event, endpoint: string): Readonly<Record<string, unknown>>;
127
+ /** Inbound fields extracted from an event for gateway.receive (ws / wss 两个 endpoint 共用). */
128
+ export interface OneBot11InboundFields {
129
+ readonly metadata: Readonly<Record<string, unknown>>;
130
+ readonly endpointId: string;
131
+ readonly mentioned: boolean;
132
+ readonly replyTo: {
133
+ readonly id: string;
134
+ } | undefined;
135
+ }
136
+ /** 构造 gateway.receive 的 metadata 与提升字段(ws / wss 两个 endpoint 共用)。 */
137
+ export declare function formatInboundMetadata(ev: OneBot11Event, endpoint: string): OneBot11InboundFields;
129
138
  /**
130
139
  * canonical MediaRef → OneBot `file` 参数:url 直传、base64 → `base64://`、
131
140
  * 本地路径 → `file://`(路径在 OneBot 实现侧解析)、kind=file 不透明引用原样透传。
package/lib/protocol.js CHANGED
@@ -18,8 +18,8 @@ function normalizeConnection(connection, legacyType) {
18
18
  export function resolveOneBot11Config(config = {}) {
19
19
  const entry = config.endpoints?.find((item) => item.context === 'onebot11');
20
20
  const connection = normalizeConnection(config.connection ?? entry?.connection, entry?.type);
21
- const name = (typeof config.name === 'string' && config.name)
22
- || (typeof entry?.name === 'string' && entry.name)
21
+ const id = (typeof config.id === 'string' && config.id)
22
+ || (typeof entry?.id === 'string' && entry.id)
23
23
  || process.env.ONEBOT11_BOT_NAME
24
24
  || 'onebot11-bot';
25
25
  const access_token = config.access_token ?? entry?.access_token;
@@ -31,7 +31,7 @@ export function resolveOneBot11Config(config = {}) {
31
31
  return {
32
32
  context: 'onebot11',
33
33
  connection: 'ws',
34
- name,
34
+ id,
35
35
  access_token,
36
36
  url,
37
37
  reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
@@ -46,7 +46,7 @@ export function resolveOneBot11Config(config = {}) {
46
46
  return {
47
47
  context: 'onebot11',
48
48
  connection: 'wss',
49
- name,
49
+ id,
50
50
  access_token,
51
51
  path,
52
52
  heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
@@ -73,12 +73,12 @@ export function getChannelId(ev) {
73
73
  * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
74
74
  * OneBot 11 无 guild/temp 容器概念,不填 parent。
75
75
  */
76
- export function onebot11InboundConversation(endpointId, ev) {
76
+ export function onebot11InboundConversation(endpointKey, ev) {
77
77
  const kind = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
78
78
  ? 'group'
79
79
  : 'private';
80
80
  return {
81
- endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
81
+ endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
82
82
  kind,
83
83
  id: getChannelId(ev),
84
84
  };
@@ -144,24 +144,26 @@ export function isOneBot11BotMentioned(input) {
144
144
  return qq !== 'all' && qq === input.selfId;
145
145
  });
146
146
  }
147
- /** 构造 gateway.receive 的 metadata(ws / wss 两个 endpoint 共用)。 */
147
+ /** 构造 gateway.receive 的 metadata 与提升字段(ws / wss 两个 endpoint 共用)。 */
148
148
  export function formatInboundMetadata(ev, endpoint) {
149
149
  const selfId = ev.self_id != null ? String(ev.self_id) : undefined;
150
150
  const nickname = senderNickname(ev);
151
151
  const quoteId = extractQuoteId(ev);
152
152
  const mentioned = isOneBot11BotMentioned({ selfId, message: ev.message });
153
- return Object.freeze({
154
- message_type: ev.message_type,
155
- user_id: ev.user_id != null ? String(ev.user_id) : undefined,
156
- group_id: ev.group_id != null ? String(ev.group_id) : undefined,
157
- endpoint,
158
- time: ev.time,
159
- self_id: selfId,
160
- role: ev.sender?.role,
161
- ...(nickname ? { nickname } : {}),
162
- ...(quoteId ? { quote_id: quoteId } : {}),
163
- ...(mentioned ? { mentioned: true } : {}),
164
- });
153
+ return {
154
+ metadata: Object.freeze({
155
+ message_type: ev.message_type,
156
+ user_id: ev.user_id != null ? String(ev.user_id) : undefined,
157
+ group_id: ev.group_id != null ? String(ev.group_id) : undefined,
158
+ time: ev.time,
159
+ self_id: selfId,
160
+ role: ev.sender?.role,
161
+ ...(nickname ? { nickname } : {}),
162
+ }),
163
+ endpointId: endpoint,
164
+ mentioned,
165
+ replyTo: quoteId ? { id: quoteId } : undefined,
166
+ };
165
167
  }
166
168
  /**
167
169
  * canonical MediaRef → OneBot `file` 参数:url 直传、base64 → `base64://`、
@@ -3,13 +3,13 @@
3
3
  */
4
4
  import WebSocket from 'ws';
5
5
  import { createEndpointLifecycle, } from '@zhin.js/adapter';
6
- import { formatCompact, getLogger } from '@zhin.js/logger';
6
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
7
7
  import { createOneBot11EndpointManagement } from './endpoint-management.js';
8
8
  import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
9
- import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderUserId, } from './protocol.js';
9
+ import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderDisplayName, senderUserId, } from './protocol.js';
10
10
  import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
11
- const logger = getLogger('onebot11');
12
11
  export class OneBot11WsEndpoint {
12
+ #logger;
13
13
  #options;
14
14
  management = createOneBot11EndpointManagement(this);
15
15
  #lifecycle;
@@ -19,10 +19,11 @@ export class OneBot11WsEndpoint {
19
19
  #open = false;
20
20
  #unregisterAgent;
21
21
  constructor(options) {
22
+ this.#logger = getAdapterLogger('onebot11', options.config.id);
22
23
  this.#options = options;
23
24
  const { config } = options;
24
25
  this.#lifecycle = createEndpointLifecycle({
25
- name: config.name,
26
+ name: config.id,
26
27
  reconnect: {
27
28
  initialIntervalMs: config.reconnect_interval,
28
29
  // 固定间隔(multiplier 1、无抖动),对齐旧 reconnect_interval 语义
@@ -37,7 +38,7 @@ export class OneBot11WsEndpoint {
37
38
  if (this.#lifecycle.started)
38
39
  return;
39
40
  // agent 注册/反注册是适配器专有依赖,留在适配器侧(见 endpoint-lifecycle 迁移指引)
40
- this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.name, this);
41
+ this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
41
42
  try {
42
43
  await this.#lifecycle.start((handle) => this.#connect(handle));
43
44
  }
@@ -77,9 +78,9 @@ export class OneBot11WsEndpoint {
77
78
  const { action, params } = buildSendAction(conversation, message);
78
79
  const data = await this.callApi(action, params);
79
80
  const messageId = data?.message_id != null ? String(data.message_id) : '';
80
- logger.debug(formatCompact({
81
+ this.#logger.debug(formatCompact({
81
82
  op: 'onebot11_send',
82
- endpoint: this.#options.config.name,
83
+ endpoint: this.#options.config.id,
83
84
  target: `${conversation.kind}:${conversation.id}`,
84
85
  messageId,
85
86
  }));
@@ -109,14 +110,22 @@ export class OneBot11WsEndpoint {
109
110
  return;
110
111
  const conversation = onebot11InboundConversation(String(this.#options.id), ev);
111
112
  const content = formatInboundContent(ev);
113
+ const inbound = formatInboundMetadata(ev, this.#options.config.id);
112
114
  void this.#options.gateway.receive({
113
115
  conversation,
114
116
  message: { conversation, id: String(ev.message_id) },
115
117
  content,
116
- sender: senderUserId(ev),
117
- metadata: formatInboundMetadata(ev, this.#options.config.name),
118
+ sender: {
119
+ id: senderUserId(ev),
120
+ name: senderDisplayName(ev) || undefined,
121
+ ...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
122
+ },
123
+ endpointId: inbound.endpointId,
124
+ ...(inbound.mentioned ? { mentioned: true } : {}),
125
+ ...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
126
+ metadata: inbound.metadata,
118
127
  }).catch((err) => {
119
- logger.warn(formatCompact({
128
+ this.#logger.warn(formatCompact({
120
129
  op: 'onebot11_gateway_receive_failed',
121
130
  target: `${conversation.kind}:${conversation.id}`,
122
131
  error: err instanceof Error ? err.message : String(err),
@@ -144,14 +153,14 @@ export class OneBot11WsEndpoint {
144
153
  return;
145
154
  settled = true;
146
155
  if (!this.#options.config.access_token) {
147
- logger.warn(formatCompact({
148
- endpoint: this.#options.config.name,
156
+ this.#logger.warn(formatCompact({
157
+ endpoint: this.#options.config.id,
149
158
  ok: false,
150
159
  error: 'missing access_token',
151
160
  }));
152
161
  }
153
- logger.debug(formatCompact({
154
- endpoint: this.#options.config.name,
162
+ this.#logger.debug(formatCompact({
163
+ endpoint: this.#options.config.id,
155
164
  mode: 'ws',
156
165
  url: safeUrl,
157
166
  }));
@@ -160,7 +169,7 @@ export class OneBot11WsEndpoint {
160
169
  });
161
170
  ws.on('message', (data) => {
162
171
  handleOneBot11WsMessage(data, {
163
- endpointName: this.#options.config.name,
172
+ endpointId: this.#options.config.id,
164
173
  pending: this.#pending,
165
174
  admit: (ev) => this.admit(ev),
166
175
  });
@@ -187,9 +196,9 @@ export class OneBot11WsEndpoint {
187
196
  });
188
197
  ws.on('error', (err) => {
189
198
  const error = err instanceof Error ? err : new Error(String(err));
190
- logger.warn(formatCompact({
199
+ this.#logger.warn(formatCompact({
191
200
  op: 'ws_error',
192
- endpoint: this.#options.config.name,
201
+ endpoint: this.#options.config.id,
193
202
  ok: false,
194
203
  error: error.message,
195
204
  }));
@@ -2,7 +2,7 @@ import { type OneBot11Event } from './protocol.js';
2
2
  import { type OneBot11PendingAction, type OneBot11WsSocket } from './ws-types.js';
3
3
  export declare function decodeWsPayload(data: unknown): string;
4
4
  export declare function handleOneBot11WsMessage(data: unknown, options: {
5
- readonly endpointName: string;
5
+ readonly endpointId: string;
6
6
  readonly pending: Map<string, OneBot11PendingAction>;
7
7
  readonly admit: (ev: OneBot11Event) => void;
8
8
  }): void;
@@ -33,7 +33,7 @@ export function handleOneBot11WsMessage(data, options) {
33
33
  catch (error) {
34
34
  logger.warn(formatCompact({
35
35
  op: 'onebot11_parse_failed',
36
- endpoint: options.endpointName,
36
+ endpoint: options.endpointId,
37
37
  error: error instanceof Error ? error.message : String(error),
38
38
  }));
39
39
  }
@@ -2,14 +2,14 @@
2
2
  * OneBot11 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 { createOneBot11EndpointManagement } from './endpoint-management.js';
7
7
  import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
8
- import { buildSendAction, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderUserId, } from './protocol.js';
8
+ import { buildSendAction, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderDisplayName, senderUserId, } from './protocol.js';
9
9
  import { verifyOneBotAccessToken } from './wss-auth.js';
10
10
  import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, startOneBot11Heartbeat, } from './ws-transport.js';
11
- const logger = getLogger('onebot11');
12
11
  export class OneBot11WssEndpoint {
12
+ #logger;
13
13
  #options;
14
14
  management = createOneBot11EndpointManagement(this);
15
15
  #ws;
@@ -21,6 +21,7 @@ export class OneBot11WssEndpoint {
21
21
  #started = false;
22
22
  #unregisterAgent;
23
23
  constructor(options) {
24
+ this.#logger = getAdapterLogger('onebot11', options.config.id);
24
25
  this.#options = options;
25
26
  }
26
27
  async start() {
@@ -29,21 +30,21 @@ export class OneBot11WssEndpoint {
29
30
  this.#started = true;
30
31
  if (!this.#options.config.access_token) {
31
32
  // wss 模式未配 access_token 时任何连接都会被放行(verifyOneBotAccessToken 直接 return true)
32
- logger.warn(formatCompact({
33
- endpoint: this.#options.config.name,
33
+ this.#logger.warn(formatCompact({
34
+ endpoint: this.#options.config.id,
34
35
  mode: 'wss',
35
36
  ok: false,
36
37
  error: 'missing access_token',
37
38
  }));
38
39
  }
39
- this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.name, this);
40
+ this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
40
41
  const handle = this.#options.http.ws(this.#options.config.path);
41
42
  this.#wsRelease = handle.onConnection((connection) => {
42
43
  this.#acceptConnection(connection);
43
44
  });
44
- logger.info(formatCompact({
45
+ this.#logger.info(formatCompact({
45
46
  op: 'listen',
46
- endpoint: this.#options.config.name,
47
+ endpoint: this.#options.config.id,
47
48
  mode: 'wss',
48
49
  path: this.#options.config.path,
49
50
  }));
@@ -103,14 +104,22 @@ export class OneBot11WssEndpoint {
103
104
  if (!this.#open || !isMessageEvent(ev))
104
105
  return;
105
106
  const conversation = onebot11InboundConversation(String(this.#options.id), ev);
107
+ const inbound = formatInboundMetadata(ev, this.#options.config.id);
106
108
  void this.#options.gateway.receive({
107
109
  conversation,
108
110
  message: { conversation, id: String(ev.message_id) },
109
111
  content: formatInboundContent(ev),
110
- sender: senderUserId(ev),
111
- metadata: formatInboundMetadata(ev, this.#options.config.name),
112
+ sender: {
113
+ id: senderUserId(ev),
114
+ name: senderDisplayName(ev) || undefined,
115
+ ...(ev.sender?.role ? { roles: [ev.sender.role] } : {}),
116
+ },
117
+ endpointId: inbound.endpointId,
118
+ ...(inbound.mentioned ? { mentioned: true } : {}),
119
+ ...(inbound.replyTo ? { replyTo: inbound.replyTo } : {}),
120
+ metadata: inbound.metadata,
112
121
  }).catch((err) => {
113
- logger.warn(formatCompact({
122
+ this.#logger.warn(formatCompact({
114
123
  op: 'onebot11_gateway_receive_failed',
115
124
  target: `${conversation.kind}:${conversation.id}`,
116
125
  error: err instanceof Error ? err.message : String(err),
@@ -135,7 +144,7 @@ export class OneBot11WssEndpoint {
135
144
  this.#heartbeatTimer = startOneBot11Heartbeat(this.#ws, this.#options.config.heartbeat_interval, this.#heartbeatTimer);
136
145
  socket.on('message', (data) => {
137
146
  handleOneBot11WsMessage(data, {
138
- endpointName: this.#options.config.name,
147
+ endpointId: this.#options.config.id,
139
148
  pending: this.#pending,
140
149
  admit: (ev) => this.admit(ev),
141
150
  });
@@ -149,8 +158,8 @@ export class OneBot11WssEndpoint {
149
158
  }
150
159
  }
151
160
  });
152
- logger.debug(formatCompact({
153
- endpoint: this.#options.config.name,
161
+ this.#logger.debug(formatCompact({
162
+ endpoint: this.#options.config.id,
154
163
  mode: 'wss',
155
164
  peer: connection.request.socket.remoteAddress,
156
165
  }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-onebot11",
3
- "version": "6.0.3",
3
+ "version": "6.0.5",
4
4
  "description": "Zhin.js OneBot 11 adapter for Plugin Runtime (WebSocket client)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -41,13 +41,14 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "ws": "^8.21.1",
44
- "@zhin.js/adapter": "1.1.5",
45
- "@zhin.js/command": "1.0.7",
46
- "@zhin.js/core": "1.5.2",
47
- "@zhin.js/host-http": "1.0.6",
48
- "@zhin.js/im-contract": "1.0.1",
49
- "@zhin.js/logger": "1.0.75",
50
- "@zhin.js/plugin-runtime": "1.1.3"
44
+ "@zhin.js/adapter": "1.1.7",
45
+ "@zhin.js/command": "1.0.9",
46
+ "@zhin.js/core": "1.5.4",
47
+ "@zhin.js/host-http": "1.0.8",
48
+ "@zhin.js/im-contract": "1.0.3",
49
+ "@zhin.js/logger": "1.0.76",
50
+ "@zhin.js/permission": "1.0.1",
51
+ "@zhin.js/plugin-runtime": "1.1.5"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@types/node": "^26.1.2",
@@ -55,16 +56,16 @@
55
56
  "typescript": "^6.0.3",
56
57
  "vitest": "^4.1.10",
57
58
  "zod": "^4.4.3",
58
- "@zhin.js/agent": "1.1.3",
59
- "@zhin.js/host-http": "1.0.6"
59
+ "@zhin.js/agent": "1.1.5",
60
+ "@zhin.js/host-http": "1.0.8"
60
61
  },
61
62
  "peerDependencies": {
62
63
  "zod": "^4.0.0",
63
- "@zhin.js/adapter": "1.1.5",
64
- "@zhin.js/agent": "1.1.3",
65
- "@zhin.js/core": "1.5.2",
66
- "@zhin.js/plugin-runtime": "1.1.3",
67
- "zhin.js": "6.0.2"
64
+ "@zhin.js/adapter": "1.1.7",
65
+ "@zhin.js/agent": "1.1.5",
66
+ "@zhin.js/core": "1.5.4",
67
+ "@zhin.js/plugin-runtime": "1.1.5",
68
+ "zhin.js": "6.0.4"
68
69
  },
69
70
  "peerDependenciesMeta": {
70
71
  "zhin.js": {
package/plugin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { createEndpointRuntimeState } from '@zhin.js/adapter';
3
3
  import { definePlugin } from '@zhin.js/plugin-runtime';
4
- import { registerDefaultScenePlatformPermitChecker } from '@zhin.js/core';
4
+ import { permissionHostToken, createSceneRolePlatformChecker } from '@zhin.js/permission';
5
5
  import { onebot11RuntimeStateToken } from "./lib/onebot11-runtime-state.js";
6
6
  export default definePlugin({
7
7
  name: 'onebot11',
@@ -9,9 +9,10 @@ export default definePlugin({
9
9
  displayName: 'OneBot 11 Adapter',
10
10
  },
11
11
  setup(context) {
12
- // 运行中 endpoint 注册表(onebot11.endpoint list 的"运行中"数据源)
13
12
  context.resources.provide(onebot11RuntimeStateToken, createEndpointRuntimeState());
14
- // 平台权限门禁:scene_admin / scene_owner 由 sender role 判定(见 ws/wss-endpoint admit metadata)
15
- return registerDefaultScenePlatformPermitChecker('onebot11');
13
+ if (context.resources.has(permissionHostToken)) {
14
+ const host = context.resources.use(permissionHostToken);
15
+ return host.registerPlatform('onebot11', createSceneRolePlatformChecker());
16
+ }
16
17
  },
17
18
  });
package/schema.json CHANGED
@@ -20,16 +20,48 @@
20
20
  "type": "number",
21
21
  "default": 30000
22
22
  },
23
+ "master": {
24
+ "type": [
25
+ "string",
26
+ "number"
27
+ ],
28
+ "description": "框架 master(platform user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
29
+ },
30
+ "trusted": {
31
+ "type": "array",
32
+ "items": {
33
+ "type": [
34
+ "string",
35
+ "number"
36
+ ],
37
+ "description": "Trusted platform user id"
38
+ },
39
+ "description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
40
+ },
23
41
  "endpoints": {
24
42
  "type": "array",
25
- "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(name 必填,其余覆盖顶层)",
43
+ "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
26
44
  "items": {
27
45
  "type": "object",
28
46
  "additionalProperties": true,
29
47
  "properties": {
30
- "name": {
31
- "type": "string",
32
- "description": "OneBot11 bot name"
48
+ "master": {
49
+ "type": [
50
+ "string",
51
+ "number"
52
+ ],
53
+ "description": "本 endpoint 的框架 master(platform user id);覆盖顶层 master"
54
+ },
55
+ "trusted": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": [
59
+ "string",
60
+ "number"
61
+ ],
62
+ "description": "Trusted platform user id"
63
+ },
64
+ "description": "本 endpoint 的 trusted 列表"
33
65
  },
34
66
  "url": {
35
67
  "type": "string",
@@ -42,10 +74,14 @@
42
74
  "access_token": {
43
75
  "type": "string",
44
76
  "description": "OneBot access token"
77
+ },
78
+ "id": {
79
+ "type": "string",
80
+ "description": "OneBot11 bot name"
45
81
  }
46
82
  },
47
83
  "required": [
48
- "name"
84
+ "id"
49
85
  ]
50
86
  }
51
87
  },
@@ -14,20 +14,20 @@ export interface Onebot11AgentEndpoint {
14
14
  }
15
15
 
16
16
  export interface Onebot11AgentDeps {
17
- getEndpoint: (endpointId: string) => Onebot11AgentEndpoint;
17
+ getEndpoint: (endpointKey: string) => Onebot11AgentEndpoint;
18
18
  }
19
19
 
20
20
  const endpoints = new Map<string, Onebot11AgentEndpoint>();
21
21
  let override: Onebot11AgentDeps | null = null;
22
22
 
23
23
  export function registerOnebot11AgentEndpoint(
24
- endpointId: string,
24
+ endpointKey: string,
25
25
  endpoint: Onebot11AgentEndpoint,
26
26
  ): () => void {
27
- endpoints.set(endpointId, endpoint);
27
+ endpoints.set(endpointKey, endpoint);
28
28
  return () => {
29
- if (endpoints.get(endpointId) === endpoint) {
30
- endpoints.delete(endpointId);
29
+ if (endpoints.get(endpointKey) === endpoint) {
30
+ endpoints.delete(endpointKey);
31
31
  }
32
32
  };
33
33
  }
@@ -40,9 +40,9 @@ export function setOnebot11AgentDeps(deps: Onebot11AgentDeps): void {
40
40
  export function getOnebot11AgentDeps(): Onebot11AgentDeps {
41
41
  if (override) return override;
42
42
  return {
43
- getEndpoint(endpointId: string): Onebot11AgentEndpoint {
44
- const registered = endpoints.get(endpointId);
45
- if (!registered) throw new Error(`Endpoint ${endpointId} 不存在`);
43
+ getEndpoint(endpointKey: string): Onebot11AgentEndpoint {
44
+ const registered = endpoints.get(endpointKey);
45
+ if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
46
46
  return registered;
47
47
  },
48
48
  };
package/src/protocol.ts CHANGED
@@ -15,7 +15,7 @@ export interface OneBot11LegacyEndpointRow {
15
15
  readonly connection?: 'ws' | 'wss';
16
16
  /** Legacy alias: `type: 'ws' | 'ws_reverse'` */
17
17
  readonly type?: string;
18
- readonly name?: string;
18
+ readonly id?: string;
19
19
  readonly access_token?: string;
20
20
  readonly url?: string;
21
21
  readonly path?: string;
@@ -26,7 +26,7 @@ export interface OneBot11LegacyEndpointRow {
26
26
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
27
27
  export interface OneBot11AdapterConfig {
28
28
  readonly connection?: 'ws' | 'wss';
29
- readonly name?: string;
29
+ readonly id?: string;
30
30
  readonly access_token?: string;
31
31
  readonly url?: string;
32
32
  readonly path?: string;
@@ -38,7 +38,7 @@ export interface OneBot11AdapterConfig {
38
38
 
39
39
  export interface OneBot11ConfigBase {
40
40
  readonly context: 'onebot11';
41
- readonly name: string;
41
+ readonly id: string;
42
42
  readonly access_token?: string;
43
43
  }
44
44
 
@@ -123,8 +123,8 @@ export function resolveOneBot11Config(config: OneBot11AdapterConfig = {}): Resol
123
123
  config.connection ?? entry?.connection,
124
124
  entry?.type,
125
125
  );
126
- const name = (typeof config.name === 'string' && config.name)
127
- || (typeof entry?.name === 'string' && entry.name)
126
+ const id = (typeof config.id === 'string' && config.id)
127
+ || (typeof entry?.id === 'string' && entry.id)
128
128
  || process.env.ONEBOT11_BOT_NAME
129
129
  || 'onebot11-bot';
130
130
  const access_token = config.access_token ?? entry?.access_token;
@@ -139,7 +139,7 @@ export function resolveOneBot11Config(config: OneBot11AdapterConfig = {}): Resol
139
139
  return {
140
140
  context: 'onebot11',
141
141
  connection: 'ws',
142
- name,
142
+ id,
143
143
  access_token,
144
144
  url,
145
145
  reconnect_interval: config.reconnect_interval ?? entry?.reconnect_interval ?? 5000,
@@ -155,7 +155,7 @@ export function resolveOneBot11Config(config: OneBot11AdapterConfig = {}): Resol
155
155
  return {
156
156
  context: 'onebot11',
157
157
  connection: 'wss',
158
- name,
158
+ id,
159
159
  access_token,
160
160
  path,
161
161
  heartbeat_interval: config.heartbeat_interval ?? entry?.heartbeat_interval ?? 30_000,
@@ -185,12 +185,12 @@ export function getChannelId(ev: OneBot11Event): string {
185
185
  * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
186
186
  * OneBot 11 无 guild/temp 容器概念,不填 parent。
187
187
  */
188
- export function onebot11InboundConversation(endpointId: string, ev: OneBot11Event): ConversationRef {
188
+ export function onebot11InboundConversation(endpointKey: string, ev: OneBot11Event): ConversationRef {
189
189
  const kind = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
190
190
  ? 'group' as const
191
191
  : 'private' as const;
192
192
  return {
193
- endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
193
+ endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
194
194
  kind,
195
195
  id: getChannelId(ev),
196
196
  };
@@ -259,27 +259,37 @@ export function isOneBot11BotMentioned(input: {
259
259
  });
260
260
  }
261
261
 
262
- /** 构造 gateway.receive 的 metadata(ws / wss 两个 endpoint 共用)。 */
262
+ /** Inbound fields extracted from an event for gateway.receive (ws / wss 两个 endpoint 共用). */
263
+ export interface OneBot11InboundFields {
264
+ readonly metadata: Readonly<Record<string, unknown>>;
265
+ readonly endpointId: string;
266
+ readonly mentioned: boolean;
267
+ readonly replyTo: { readonly id: string } | undefined;
268
+ }
269
+
270
+ /** 构造 gateway.receive 的 metadata 与提升字段(ws / wss 两个 endpoint 共用)。 */
263
271
  export function formatInboundMetadata(
264
272
  ev: OneBot11Event,
265
273
  endpoint: string,
266
- ): Readonly<Record<string, unknown>> {
274
+ ): OneBot11InboundFields {
267
275
  const selfId = ev.self_id != null ? String(ev.self_id) : undefined;
268
276
  const nickname = senderNickname(ev);
269
277
  const quoteId = extractQuoteId(ev);
270
278
  const mentioned = isOneBot11BotMentioned({ selfId, message: ev.message });
271
- return Object.freeze({
272
- message_type: ev.message_type,
273
- user_id: ev.user_id != null ? String(ev.user_id) : undefined,
274
- group_id: ev.group_id != null ? String(ev.group_id) : undefined,
275
- endpoint,
276
- time: ev.time,
277
- self_id: selfId,
278
- role: ev.sender?.role,
279
- ...(nickname ? { nickname } : {}),
280
- ...(quoteId ? { quote_id: quoteId } : {}),
281
- ...(mentioned ? { mentioned: true } : {}),
282
- });
279
+ return {
280
+ metadata: Object.freeze({
281
+ message_type: ev.message_type,
282
+ user_id: ev.user_id != null ? String(ev.user_id) : undefined,
283
+ group_id: ev.group_id != null ? String(ev.group_id) : undefined,
284
+ time: ev.time,
285
+ self_id: selfId,
286
+ role: ev.sender?.role,
287
+ ...(nickname ? { nickname } : {}),
288
+ }),
289
+ endpointId: endpoint,
290
+ mentioned,
291
+ replyTo: quoteId ? { id: quoteId } : undefined,
292
+ };
283
293
  }
284
294
 
285
295
  /**
@@ -11,7 +11,7 @@ import {
11
11
  type EndpointSendRequest,
12
12
  } from '@zhin.js/adapter';
13
13
  import type { MessageGateway } from '@zhin.js/core/runtime';
14
- import { formatCompact, getLogger } from '@zhin.js/logger';
14
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
15
15
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
16
16
  import { createOneBot11EndpointManagement } from './endpoint-management.js';
17
17
  import { registerOnebot11AgentEndpoint } from './onebot11-agent-deps.js';
@@ -23,6 +23,7 @@ import {
23
23
  formatOutboundSegments,
24
24
  isMessageEvent,
25
25
  onebot11InboundConversation,
26
+ senderDisplayName,
26
27
  senderUserId,
27
28
  type OneBot11Event,
28
29
  type OneBot11WsConfig,
@@ -38,8 +39,6 @@ import {
38
39
  type OneBot11WsSocket,
39
40
  } from './ws-types.js';
40
41
 
41
- const logger = getLogger('onebot11');
42
-
43
42
  export interface OneBot11WsEndpointOptions {
44
43
  readonly id: CapabilityId;
45
44
  readonly gateway: MessageGateway;
@@ -51,6 +50,8 @@ export interface OneBot11WsEndpointOptions {
51
50
  }
52
51
 
53
52
  export class OneBot11WsEndpoint implements EndpointInstance {
53
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
54
+
54
55
  readonly #options: OneBot11WsEndpointOptions;
55
56
  readonly management: EndpointManagement = createOneBot11EndpointManagement(this);
56
57
  readonly #lifecycle: EndpointLifecycle;
@@ -61,10 +62,11 @@ export class OneBot11WsEndpoint implements EndpointInstance {
61
62
  #unregisterAgent?: () => void;
62
63
 
63
64
  constructor(options: OneBot11WsEndpointOptions) {
65
+ this.#logger = getAdapterLogger('onebot11', options.config.id);
64
66
  this.#options = options;
65
67
  const { config } = options;
66
68
  this.#lifecycle = createEndpointLifecycle({
67
- name: config.name,
69
+ name: config.id,
68
70
  reconnect: {
69
71
  initialIntervalMs: config.reconnect_interval,
70
72
  // 固定间隔(multiplier 1、无抖动),对齐旧 reconnect_interval 语义
@@ -79,7 +81,7 @@ export class OneBot11WsEndpoint implements EndpointInstance {
79
81
  async start(): Promise<void> {
80
82
  if (this.#lifecycle.started) return;
81
83
  // agent 注册/反注册是适配器专有依赖,留在适配器侧(见 endpoint-lifecycle 迁移指引)
82
- this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.name, this);
84
+ this.#unregisterAgent = registerOnebot11AgentEndpoint(this.#options.config.id, this);
83
85
  try {
84
86
  await this.#lifecycle.start((handle) => this.#connect(handle));
85
87
  } catch (err) {
@@ -121,9 +123,9 @@ export class OneBot11WsEndpoint implements EndpointInstance {
121
123
  const { action, params } = buildSendAction(conversation, message);
122
124
  const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
123
125
  const messageId = data?.message_id != null ? String(data.message_id) : '';
124
- logger.debug(formatCompact({
126
+ this.#logger.debug(formatCompact({
125
127
  op: 'onebot11_send',
126
- endpoint: this.#options.config.name,
128
+ endpoint: this.#options.config.id,
127
129
  target: `${conversation.kind}:${conversation.id}`,
128
130
  messageId,
129
131
  }));
@@ -160,14 +162,22 @@ export class OneBot11WsEndpoint implements EndpointInstance {
160
162
  if (!this.#open || !isMessageEvent(ev)) return;
161
163
  const conversation = onebot11InboundConversation(String(this.#options.id), ev);
162
164
  const content = formatInboundContent(ev);
165
+ const inbound = formatInboundMetadata(ev, this.#options.config.id);
163
166
  void this.#options.gateway.receive({
164
167
  conversation,
165
168
  message: { conversation, id: String(ev.message_id) },
166
169
  content,
167
- sender: senderUserId(ev),
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
182
  target: `${conversation.kind}:${conversation.id}`,
173
183
  error: err instanceof Error ? err.message : String(err),
@@ -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
  }
@@ -5,7 +5,7 @@ import { clearInterval } from 'node:timers';
5
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';
@@ -16,6 +16,7 @@ import {
16
16
  formatOutboundSegments,
17
17
  isMessageEvent,
18
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
  }));
@@ -145,14 +147,22 @@ export class OneBot11WssEndpoint implements EndpointInstance {
145
147
  admit(ev: OneBot11Event): void {
146
148
  if (!this.#open || !isMessageEvent(ev)) return;
147
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
152
  conversation,
150
153
  message: { conversation, id: String(ev.message_id) },
151
154
  content: formatInboundContent(ev),
152
- sender: senderUserId(ev),
153
- 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,
154
164
  }).catch((err) => {
155
- logger.warn(formatCompact({
165
+ this.#logger.warn(formatCompact({
156
166
  op: 'onebot11_gateway_receive_failed',
157
167
  target: `${conversation.kind}:${conversation.id}`,
158
168
  error: err instanceof Error ? err.message : String(err),
@@ -181,7 +191,7 @@ export class OneBot11WssEndpoint implements EndpointInstance {
181
191
  );
182
192
  socket.on('message', (data) => {
183
193
  handleOneBot11WsMessage(data, {
184
- endpointName: this.#options.config.name,
194
+ endpointId: this.#options.config.id,
185
195
  pending: this.#pending,
186
196
  admit: (ev) => this.admit(ev),
187
197
  });
@@ -195,8 +205,8 @@ export class OneBot11WssEndpoint implements EndpointInstance {
195
205
  }
196
206
  }
197
207
  });
198
- logger.debug(formatCompact({
199
- endpoint: this.#options.config.name,
208
+ this.#logger.debug(formatCompact({
209
+ endpoint: this.#options.config.id,
200
210
  mode: 'wss',
201
211
  peer: connection.request.socket.remoteAddress,
202
212
  }));
File without changes
File without changes
File without changes
File without changes