@zhin.js/adapter-onebot11 6.0.1 → 6.0.3

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,29 @@
1
1
  # @zhin.js/adapter-onebot11
2
2
 
3
+ ## 6.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [afc0e66]
8
+ - Updated dependencies [2e41ad5]
9
+ - Updated dependencies [9f57124]
10
+ - @zhin.js/core@1.5.2
11
+ - @zhin.js/adapter@1.1.5
12
+ - @zhin.js/im-contract@1.0.1
13
+ - @zhin.js/plugin-runtime@1.1.3
14
+ - @zhin.js/command@1.0.7
15
+ - @zhin.js/host-http@1.0.6
16
+ - @zhin.js/agent@1.1.3
17
+ - zhin.js@6.0.2
18
+
19
+ ## 6.0.2
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependencies [696ab1b]
24
+ - @zhin.js/agent@1.1.2
25
+ - zhin.js@6.0.1
26
+
3
27
  ## 6.0.1
4
28
 
5
29
  ### Patch Changes
package/README.md CHANGED
@@ -8,7 +8,7 @@ Zhin.js [OneBot 11](https://github.com/botuniverse/onebot-11) 适配器(Plugin
8
8
  - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
9
9
  - **正向 WebSocket**(`connection: ws`):应用连 OneBot 实现的 WS 服务器
10
10
  - `access_token` 鉴权(Bearer + query)
11
- - 入站经 `messageGatewayToken`;出站 `send({ target, payload })`
11
+ - 入站经 `messageGatewayToken`;出站 `send({ conversation, payload })`
12
12
 
13
13
  ## 安装
14
14
 
@@ -23,8 +23,8 @@ pnpm add @zhin.js/adapter-onebot11
23
23
  - `@zhin.js/plugin-runtime` — `plugin.ts`(`definePlugin`)
24
24
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
25
25
 
26
- 入站:`gateway.receive({ adapter, target: "private:uid"|"group:gid", content, sender, metadata })`
27
- 出站:`send({ target, payload })` → WS `send_private_msg` / `send_group_msg`(payload 已由 gateway/core 渲染;无 segment-mapper)
26
+ 入站:`gateway.receive({ conversation, message, content, sender, metadata })`(`conversation.kind` 为 `private`/`group`,`id` 为 uid/gid)
27
+ 出站:`send({ conversation, payload })` → WS `send_private_msg` / `send_group_msg`(payload 已由 gateway/core 渲染;无 segment-mapper)
28
28
 
29
29
  ## 最小配置
30
30
 
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, parseSendTarget, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, type OneBot11ActionRequest, type OneBot11ActionResponse, type OneBot11AdapterConfig, type OneBot11ConfigBase, type OneBot11EndpointConfig, type OneBot11Event, type OneBot11Segment, type OneBot11Sender, type OneBot11WireSegment, type OneBot11WsConfig, type OneBot11WssConfig, type ParsedSendTarget, type ResolvedOneBot11Config, } from './protocol.js';
1
+ export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, onebot11InboundConversation, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, type OneBot11ActionRequest, type OneBot11ActionResponse, type OneBot11AdapterConfig, type OneBot11ConfigBase, type OneBot11EndpointConfig, type OneBot11Event, type OneBot11Segment, type OneBot11Sender, type OneBot11WireSegment, type OneBot11WsConfig, type OneBot11WssConfig, type ResolvedOneBot11Config, } from './protocol.js';
2
2
  export { OneBot11WsEndpoint, type OneBot11WsEndpointOptions, } from './ws-endpoint.js';
3
3
  export { OneBot11WssEndpoint, type OneBot11WssEndpointOptions, } from './wss-endpoint.js';
4
4
  export type { OneBot11WsSocket, OneBot11WsCreateOptions } from './ws-types.js';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatInboundTarget, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, parseSendTarget, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, } from './protocol.js';
1
+ export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, onebot11InboundConversation, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, } from './protocol.js';
2
2
  export { OneBot11WsEndpoint, } from './ws-endpoint.js';
3
3
  export { OneBot11WssEndpoint, } from './wss-endpoint.js';
4
4
  export { callOneBot11WsAction, decodeWsPayload, handleOneBot11WsMessage, rejectAllPending, startOneBot11Heartbeat, } from './ws-transport.js';
package/lib/protocol.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * Spec: https://github.com/botuniverse/onebot-11
5
5
  */
6
6
  import { type MediaRef } from '@zhin.js/core';
7
+ import type { ConversationRef } from '@zhin.js/im-contract';
7
8
  /** Transitional legacy endpoint row (`endpoints[]` with `context: onebot11`). */
8
9
  export interface OneBot11LegacyEndpointRow {
9
10
  readonly context?: string;
@@ -90,10 +91,6 @@ export interface OneBot11WireSegment {
90
91
  readonly type: string;
91
92
  readonly data?: Record<string, unknown>;
92
93
  }
93
- export interface ParsedSendTarget {
94
- readonly message_type: 'private' | 'group';
95
- readonly id: string;
96
- }
97
94
  export declare function resolveOneBot11Config(config?: OneBot11AdapterConfig): ResolvedOneBot11Config;
98
95
  /** 判断是否为消息事件(post_type=message) */
99
96
  export declare function isMessageEvent(ev: OneBot11Event): ev is OneBot11Event & {
@@ -102,10 +99,11 @@ export declare function isMessageEvent(ev: OneBot11Event): ev is OneBot11Event &
102
99
  /** 从事件得到场景 id:私聊 user_id,群 group_id */
103
100
  export declare function getChannelId(ev: OneBot11Event): string;
104
101
  /**
105
- * Gateway reply target:`private:uid` / `group:gid`,便于 send() 还原动作参数。
102
+ * 入站归一化 → ConversationRef:OneBot 11 `group` 消息 → kind 'group',
103
+ * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
104
+ * OneBot 11 无 guild/temp 容器概念,不填 parent。
106
105
  */
107
- export declare function formatInboundTarget(ev: OneBot11Event): string;
108
- export declare function parseSendTarget(target: string): ParsedSendTarget;
106
+ export declare function onebot11InboundConversation(endpointId: string, ev: OneBot11Event): ConversationRef;
109
107
  /** Build inbound text for MessageGateway.receive */
110
108
  export declare function formatInboundContent(ev: OneBot11Event): string;
111
109
  export declare function senderDisplayName(ev: OneBot11Event): string;
@@ -140,7 +138,7 @@ export declare function mediaRefToOneBotFile(media: MediaRef): string;
140
138
  * 其余 wire 形状段(at / 平台扩展段)原样透传。
141
139
  */
142
140
  export declare function formatOutboundSegments(payload: unknown): OneBot11Segment[];
143
- export declare function buildSendAction(target: string, message: OneBot11Segment[]): {
141
+ export declare function buildSendAction(conversation: ConversationRef, message: OneBot11Segment[]): {
144
142
  action: string;
145
143
  params: Record<string, unknown>;
146
144
  };
package/lib/protocol.js CHANGED
@@ -69,28 +69,19 @@ export function getChannelId(ev) {
69
69
  return '';
70
70
  }
71
71
  /**
72
- * Gateway reply target:`private:uid` / `group:gid`,便于 send() 还原动作参数。
72
+ * 入站归一化 → ConversationRef:OneBot 11 `group` 消息 → kind 'group',
73
+ * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
74
+ * OneBot 11 无 guild/temp 容器概念,不填 parent。
73
75
  */
74
- export function formatInboundTarget(ev) {
75
- const messageType = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
76
+ export function onebot11InboundConversation(endpointId, ev) {
77
+ const kind = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
76
78
  ? 'group'
77
79
  : 'private';
78
- return `${messageType}:${getChannelId(ev)}`;
79
- }
80
- export function parseSendTarget(target) {
81
- const sep = target.indexOf(':');
82
- if (sep <= 0) {
83
- return { message_type: 'private', id: target };
84
- }
85
- const head = target.slice(0, sep);
86
- const rest = target.slice(sep + 1);
87
- if (head === 'group') {
88
- return { message_type: 'group', id: rest };
89
- }
90
- if (head === 'private') {
91
- return { message_type: 'private', id: rest };
92
- }
93
- return { message_type: 'private', id: target };
80
+ return {
81
+ endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
82
+ kind,
83
+ id: getChannelId(ev),
84
+ };
94
85
  }
95
86
  /** Build inbound text for MessageGateway.receive */
96
87
  export function formatInboundContent(ev) {
@@ -289,13 +280,12 @@ export function formatOutboundSegments(payload) {
289
280
  }
290
281
  return segs.length ? segs : [{ type: 'text', data: { text: '' } }];
291
282
  }
292
- export function buildSendAction(target, message) {
293
- const parsed = parseSendTarget(target);
294
- if (parsed.message_type === 'group') {
283
+ export function buildSendAction(conversation, message) {
284
+ if (conversation.kind === 'group') {
295
285
  return {
296
286
  action: 'send_group_msg',
297
287
  params: {
298
- group_id: Number(parsed.id) || parsed.id,
288
+ group_id: Number(conversation.id) || conversation.id,
299
289
  message,
300
290
  },
301
291
  };
@@ -303,7 +293,7 @@ export function buildSendAction(target, message) {
303
293
  return {
304
294
  action: 'send_private_msg',
305
295
  params: {
306
- user_id: Number(parsed.id) || parsed.id,
296
+ user_id: Number(conversation.id) || conversation.id,
307
297
  message,
308
298
  },
309
299
  };
@@ -1,4 +1,4 @@
1
- import { type EndpointInstance, type EndpointManagement } from '@zhin.js/adapter';
1
+ import { type EndpointInstance, type EndpointManagement, type EndpointSendRequest } from '@zhin.js/adapter';
2
2
  import type { MessageGateway } from '@zhin.js/core/runtime';
3
3
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
4
4
  import { type OneBot11Event, type OneBot11WsConfig } from './protocol.js';
@@ -17,10 +17,7 @@ export declare class OneBot11WsEndpoint implements EndpointInstance {
17
17
  open(): void;
18
18
  close(): void;
19
19
  stop(): Promise<void>;
20
- send({ target, payload }: {
21
- readonly target: string;
22
- readonly payload: unknown;
23
- }): Promise<string>;
20
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
24
21
  recallMessage(messageId: string): Promise<void>;
25
22
  /** Public API for agent tools / callers. */
26
23
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
@@ -6,7 +6,7 @@ import { createEndpointLifecycle, } from '@zhin.js/adapter';
6
6
  import { formatCompact, getLogger } 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, formatInboundTarget, formatOutboundSegments, isMessageEvent, senderUserId, } from './protocol.js';
9
+ import { buildSendAction, buildWsConnectOptions, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderUserId, } from './protocol.js';
10
10
  import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
11
11
  const logger = getLogger('onebot11');
12
12
  export class OneBot11WsEndpoint {
@@ -72,15 +72,15 @@ export class OneBot11WsEndpoint {
72
72
  rejectAllPending(this.#pending);
73
73
  this.#ws = undefined;
74
74
  }
75
- async send({ target, payload }) {
75
+ async send({ conversation, payload }) {
76
76
  const message = formatOutboundSegments(payload);
77
- const { action, params } = buildSendAction(target, message);
77
+ const { action, params } = buildSendAction(conversation, message);
78
78
  const data = await this.callApi(action, params);
79
79
  const messageId = data?.message_id != null ? String(data.message_id) : '';
80
80
  logger.debug(formatCompact({
81
81
  op: 'onebot11_send',
82
82
  endpoint: this.#options.config.name,
83
- target,
83
+ target: `${conversation.kind}:${conversation.id}`,
84
84
  messageId,
85
85
  }));
86
86
  return messageId;
@@ -107,19 +107,18 @@ export class OneBot11WsEndpoint {
107
107
  admit(ev) {
108
108
  if (!this.#open || !isMessageEvent(ev))
109
109
  return;
110
- const target = formatInboundTarget(ev);
110
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
111
111
  const content = formatInboundContent(ev);
112
112
  void this.#options.gateway.receive({
113
- adapter: this.#options.id,
114
- target,
113
+ conversation,
114
+ message: { conversation, id: String(ev.message_id) },
115
115
  content,
116
116
  sender: senderUserId(ev),
117
- id: String(ev.message_id),
118
117
  metadata: formatInboundMetadata(ev, this.#options.config.name),
119
118
  }).catch((err) => {
120
119
  logger.warn(formatCompact({
121
120
  op: 'onebot11_gateway_receive_failed',
122
- target,
121
+ target: `${conversation.kind}:${conversation.id}`,
123
122
  error: err instanceof Error ? err.message : String(err),
124
123
  }));
125
124
  });
@@ -1,4 +1,4 @@
1
- import type { EndpointInstance, EndpointManagement } from '@zhin.js/adapter';
1
+ import type { EndpointInstance, EndpointManagement, EndpointSendRequest } from '@zhin.js/adapter';
2
2
  import type { MessageGateway } from '@zhin.js/core/runtime';
3
3
  import type { HttpHost } from '@zhin.js/host-http';
4
4
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
@@ -17,10 +17,7 @@ export declare class OneBot11WssEndpoint implements EndpointInstance {
17
17
  open(): void;
18
18
  close(): void;
19
19
  stop(): Promise<void>;
20
- send({ target, payload }: {
21
- readonly target: string;
22
- readonly payload: unknown;
23
- }): Promise<string>;
20
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
24
21
  recallMessage(messageId: string): Promise<void>;
25
22
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
26
23
  setTitle(groupId: number, userId: number, title: string, duration?: number): Promise<boolean>;
@@ -5,7 +5,7 @@ import { clearInterval } from 'node:timers';
5
5
  import { formatCompact, getLogger } 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, formatInboundTarget, formatOutboundSegments, isMessageEvent, senderUserId, } from './protocol.js';
8
+ import { buildSendAction, formatInboundContent, formatInboundMetadata, formatOutboundSegments, isMessageEvent, onebot11InboundConversation, senderUserId, } from './protocol.js';
9
9
  import { verifyOneBotAccessToken } from './wss-auth.js';
10
10
  import { callOneBot11WsAction, handleOneBot11WsMessage, rejectAllPending, startOneBot11Heartbeat, } from './ws-transport.js';
11
11
  const logger = getLogger('onebot11');
@@ -76,9 +76,9 @@ export class OneBot11WssEndpoint {
76
76
  }
77
77
  this.#started = false;
78
78
  }
79
- async send({ target, payload }) {
79
+ async send({ conversation, payload }) {
80
80
  const message = formatOutboundSegments(payload);
81
- const { action, params } = buildSendAction(target, message);
81
+ const { action, params } = buildSendAction(conversation, message);
82
82
  const data = await this.callApi(action, params);
83
83
  return data?.message_id != null ? String(data.message_id) : '';
84
84
  }
@@ -102,18 +102,17 @@ export class OneBot11WssEndpoint {
102
102
  admit(ev) {
103
103
  if (!this.#open || !isMessageEvent(ev))
104
104
  return;
105
- const target = formatInboundTarget(ev);
105
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
106
106
  void this.#options.gateway.receive({
107
- adapter: this.#options.id,
108
- target,
107
+ conversation,
108
+ message: { conversation, id: String(ev.message_id) },
109
109
  content: formatInboundContent(ev),
110
110
  sender: senderUserId(ev),
111
- id: String(ev.message_id),
112
111
  metadata: formatInboundMetadata(ev, this.#options.config.name),
113
112
  }).catch((err) => {
114
113
  logger.warn(formatCompact({
115
114
  op: 'onebot11_gateway_receive_failed',
116
- target,
115
+ target: `${conversation.kind}:${conversation.id}`,
117
116
  error: err instanceof Error ? err.message : String(err),
118
117
  }));
119
118
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-onebot11",
3
- "version": "6.0.1",
3
+ "version": "6.0.3",
4
4
  "description": "Zhin.js OneBot 11 adapter for Plugin Runtime (WebSocket client)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -41,12 +41,13 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "ws": "^8.21.1",
44
- "@zhin.js/adapter": "1.1.4",
45
- "@zhin.js/command": "1.0.6",
46
- "@zhin.js/core": "1.5.1",
47
- "@zhin.js/host-http": "1.0.5",
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",
48
49
  "@zhin.js/logger": "1.0.75",
49
- "@zhin.js/plugin-runtime": "1.1.2"
50
+ "@zhin.js/plugin-runtime": "1.1.3"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@types/node": "^26.1.2",
@@ -54,16 +55,16 @@
54
55
  "typescript": "^6.0.3",
55
56
  "vitest": "^4.1.10",
56
57
  "zod": "^4.4.3",
57
- "@zhin.js/agent": "1.1.1",
58
- "@zhin.js/host-http": "1.0.5"
58
+ "@zhin.js/agent": "1.1.3",
59
+ "@zhin.js/host-http": "1.0.6"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "zod": "^4.0.0",
62
- "@zhin.js/adapter": "1.1.4",
63
- "@zhin.js/agent": "1.1.1",
64
- "@zhin.js/core": "1.5.1",
65
- "@zhin.js/plugin-runtime": "1.1.2",
66
- "zhin.js": "6.0.1"
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"
67
68
  },
68
69
  "peerDependenciesMeta": {
69
70
  "zhin.js": {
package/src/index.ts CHANGED
@@ -4,13 +4,12 @@ export {
4
4
  extractQuoteId,
5
5
  formatInboundContent,
6
6
  formatInboundMetadata,
7
- formatInboundTarget,
8
7
  formatOutboundSegments,
9
8
  getChannelId,
10
9
  isMessageEvent,
11
10
  isOneBot11BotMentioned,
12
11
  mediaRefToOneBotFile,
13
- parseSendTarget,
12
+ onebot11InboundConversation,
14
13
  resolveOneBot11Config,
15
14
  senderDisplayName,
16
15
  senderNickname,
@@ -26,7 +25,6 @@ export {
26
25
  type OneBot11WireSegment,
27
26
  type OneBot11WsConfig,
28
27
  type OneBot11WssConfig,
29
- type ParsedSendTarget,
30
28
  type ResolvedOneBot11Config,
31
29
  } from './protocol.js';
32
30
 
package/src/protocol.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * Spec: https://github.com/botuniverse/onebot-11
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('onebot11');
@@ -106,11 +107,6 @@ export interface OneBot11WireSegment {
106
107
  readonly data?: Record<string, unknown>;
107
108
  }
108
109
 
109
- export interface ParsedSendTarget {
110
- readonly message_type: 'private' | 'group';
111
- readonly id: string;
112
- }
113
-
114
110
  function normalizeConnection(
115
111
  connection: string | undefined,
116
112
  legacyType: string | undefined,
@@ -185,29 +181,19 @@ export function getChannelId(ev: OneBot11Event): string {
185
181
  }
186
182
 
187
183
  /**
188
- * Gateway reply target:`private:uid` / `group:gid`,便于 send() 还原动作参数。
184
+ * 入站归一化 → ConversationRef:OneBot 11 `group` 消息 → kind 'group',
185
+ * 其余(private 及带 group_id 的非 private 事件按群处理)→ kind 'private'。
186
+ * OneBot 11 无 guild/temp 容器概念,不填 parent。
189
187
  */
190
- export function formatInboundTarget(ev: OneBot11Event): string {
191
- const messageType = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
192
- ? 'group'
193
- : 'private';
194
- return `${messageType}:${getChannelId(ev)}`;
195
- }
196
-
197
- export function parseSendTarget(target: string): ParsedSendTarget {
198
- const sep = target.indexOf(':');
199
- if (sep <= 0) {
200
- return { message_type: 'private', id: target };
201
- }
202
- const head = target.slice(0, sep);
203
- const rest = target.slice(sep + 1);
204
- if (head === 'group') {
205
- return { message_type: 'group', id: rest };
206
- }
207
- if (head === 'private') {
208
- return { message_type: 'private', id: rest };
209
- }
210
- return { message_type: 'private', id: target };
188
+ export function onebot11InboundConversation(endpointId: string, ev: OneBot11Event): ConversationRef {
189
+ const kind = ev.message_type === 'group' || (ev.group_id != null && ev.message_type !== 'private')
190
+ ? 'group' as const
191
+ : 'private' as const;
192
+ return {
193
+ endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
194
+ kind,
195
+ id: getChannelId(ev),
196
+ };
211
197
  }
212
198
 
213
199
  /** Build inbound text for MessageGateway.receive */
@@ -420,15 +406,14 @@ export function formatOutboundSegments(payload: unknown): OneBot11Segment[] {
420
406
  }
421
407
 
422
408
  export function buildSendAction(
423
- target: string,
409
+ conversation: ConversationRef,
424
410
  message: OneBot11Segment[],
425
411
  ): { action: string; params: Record<string, unknown> } {
426
- const parsed = parseSendTarget(target);
427
- if (parsed.message_type === 'group') {
412
+ if (conversation.kind === 'group') {
428
413
  return {
429
414
  action: 'send_group_msg',
430
415
  params: {
431
- group_id: Number(parsed.id) || parsed.id,
416
+ group_id: Number(conversation.id) || conversation.id,
432
417
  message,
433
418
  },
434
419
  };
@@ -436,7 +421,7 @@ export function buildSendAction(
436
421
  return {
437
422
  action: 'send_private_msg',
438
423
  params: {
439
- user_id: Number(parsed.id) || parsed.id,
424
+ user_id: Number(conversation.id) || conversation.id,
440
425
  message,
441
426
  },
442
427
  };
@@ -8,6 +8,7 @@ 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
14
  import { formatCompact, getLogger } from '@zhin.js/logger';
@@ -19,9 +20,9 @@ import {
19
20
  buildWsConnectOptions,
20
21
  formatInboundContent,
21
22
  formatInboundMetadata,
22
- formatInboundTarget,
23
23
  formatOutboundSegments,
24
24
  isMessageEvent,
25
+ onebot11InboundConversation,
25
26
  senderUserId,
26
27
  type OneBot11Event,
27
28
  type OneBot11WsConfig,
@@ -115,15 +116,15 @@ export class OneBot11WsEndpoint implements EndpointInstance {
115
116
  this.#ws = undefined;
116
117
  }
117
118
 
118
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
119
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
119
120
  const message = formatOutboundSegments(payload);
120
- const { action, params } = buildSendAction(target, message);
121
+ const { action, params } = buildSendAction(conversation, message);
121
122
  const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
122
123
  const messageId = data?.message_id != null ? String(data.message_id) : '';
123
124
  logger.debug(formatCompact({
124
125
  op: 'onebot11_send',
125
126
  endpoint: this.#options.config.name,
126
- target,
127
+ target: `${conversation.kind}:${conversation.id}`,
127
128
  messageId,
128
129
  }));
129
130
  return messageId;
@@ -157,19 +158,18 @@ export class OneBot11WsEndpoint implements EndpointInstance {
157
158
  /** Test / internal: admit a parsed event when the endpoint is open. */
158
159
  admit(ev: OneBot11Event): void {
159
160
  if (!this.#open || !isMessageEvent(ev)) return;
160
- const target = formatInboundTarget(ev);
161
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
161
162
  const content = formatInboundContent(ev);
162
163
  void this.#options.gateway.receive({
163
- adapter: this.#options.id,
164
- target,
164
+ conversation,
165
+ message: { conversation, id: String(ev.message_id) },
165
166
  content,
166
167
  sender: senderUserId(ev),
167
- id: String(ev.message_id),
168
168
  metadata: formatInboundMetadata(ev, this.#options.config.name),
169
169
  }).catch((err) => {
170
170
  logger.warn(formatCompact({
171
171
  op: 'onebot11_gateway_receive_failed',
172
- target,
172
+ target: `${conversation.kind}:${conversation.id}`,
173
173
  error: err instanceof Error ? err.message : String(err),
174
174
  }));
175
175
  });
@@ -2,7 +2,7 @@
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
8
  import { formatCompact, getLogger } from '@zhin.js/logger';
@@ -13,9 +13,9 @@ import {
13
13
  buildSendAction,
14
14
  formatInboundContent,
15
15
  formatInboundMetadata,
16
- formatInboundTarget,
17
16
  formatOutboundSegments,
18
17
  isMessageEvent,
18
+ onebot11InboundConversation,
19
19
  senderUserId,
20
20
  type OneBot11Event,
21
21
  type OneBot11WssConfig,
@@ -116,9 +116,9 @@ export class OneBot11WssEndpoint implements EndpointInstance {
116
116
  this.#started = false;
117
117
  }
118
118
 
119
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
119
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
120
120
  const message = formatOutboundSegments(payload);
121
- const { action, params } = buildSendAction(target, message);
121
+ const { action, params } = buildSendAction(conversation, message);
122
122
  const data = await this.callApi(action, params) as { message_id?: number | string } | undefined;
123
123
  return data?.message_id != null ? String(data.message_id) : '';
124
124
  }
@@ -144,18 +144,17 @@ export class OneBot11WssEndpoint implements EndpointInstance {
144
144
 
145
145
  admit(ev: OneBot11Event): void {
146
146
  if (!this.#open || !isMessageEvent(ev)) return;
147
- const target = formatInboundTarget(ev);
147
+ const conversation = onebot11InboundConversation(String(this.#options.id), ev);
148
148
  void this.#options.gateway.receive({
149
- adapter: this.#options.id,
150
- target,
149
+ conversation,
150
+ message: { conversation, id: String(ev.message_id) },
151
151
  content: formatInboundContent(ev),
152
152
  sender: senderUserId(ev),
153
- id: String(ev.message_id),
154
153
  metadata: formatInboundMetadata(ev, this.#options.config.name),
155
154
  }).catch((err) => {
156
155
  logger.warn(formatCompact({
157
156
  op: 'onebot11_gateway_receive_failed',
158
- target,
157
+ target: `${conversation.kind}:${conversation.id}`,
159
158
  error: err instanceof Error ? err.message : String(err),
160
159
  }));
161
160
  });