@zhin.js/adapter-kook 7.0.2 → 7.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,21 @@
1
1
  # @zhin.js/adapter-kook
2
2
 
3
+ ## 7.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
+
3
19
  ## 7.0.2
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -7,7 +7,7 @@ Zhin.js KOOK(开黑啦)适配器(Plugin Runtime),默认通过 **WebSoc
7
7
  - WebSocket Gateway 入站(默认;无需公网 HTTPS / host)
8
8
  - Webhook 入站(`connection: webhook` + `httpHostToken` + `verify_token`)
9
9
  - 解析频道与私聊文本消息
10
- - 出站 `send({ target, payload })` → KOOK KMarkdown(`channel:id` / `private:id`)
10
+ - 出站 `send({ conversation, payload })` → KOOK KMarkdown(`kind: 'channel' | 'private'`)
11
11
  - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
12
12
 
13
13
  ## 安装
@@ -25,8 +25,8 @@ pnpm add @zhin.js/adapter-kook
25
25
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
26
26
  - **WebSocket 路径无需** `@zhin.js/host-http` / `@zhin.js/host-router`
27
27
 
28
- 入站:`gateway.receive({ adapter, target: 'channel:…'|'private:…', content, sender, metadata })`
29
- 出站:`send({ target, payload })` → `sendChannelMsg` / `sendPrivateMsg`
28
+ 入站:`gateway.receive({ conversation, message, content, sender, metadata })`(ConversationRef:`channel` 频道消息带 guild `parent`,`private` 私聊)
29
+ 出站:`send({ conversation, payload })` → `sendChannelMsg` / `sendPrivateMsg`
30
30
 
31
31
  ## 前置条件
32
32
 
package/lib/endpoint.d.ts CHANGED
@@ -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';
@@ -18,10 +18,7 @@ export declare class KookWebsocketEndpoint implements EndpointInstance {
18
18
  open(): void;
19
19
  close(): void;
20
20
  stop(): Promise<void>;
21
- send({ target, payload }: {
22
- readonly target: string;
23
- readonly payload: unknown;
24
- }): Promise<string>;
21
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
25
22
  /** Test / internal: admit a message when open. */
26
23
  admit(msg: KookInboundMessage): void;
27
24
  recallMessage(messageId: string): Promise<void>;
@@ -61,10 +58,7 @@ export declare class KookWebhookEndpoint implements EndpointInstance {
61
58
  open(): void;
62
59
  close(): void;
63
60
  stop(): Promise<void>;
64
- send({ target, payload }: {
65
- readonly target: string;
66
- readonly payload: unknown;
67
- }): Promise<string>;
61
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
68
62
  /** Test / internal: admit a message when open. */
69
63
  admit(msg: KookInboundMessage): void;
70
64
  recallMessage(messageId: string): Promise<void>;
package/lib/endpoint.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { formatCompact, getLogger } from '@zhin.js/logger';
2
2
  import { registerKookAgentEndpoint } from './kook-agent-deps.js';
3
- import { formatInboundContent, formatInboundTarget, formatOutboundKmarkdown, isKookBotMentioned, parseSendTarget, senderDisplayName, } from './protocol.js';
3
+ import { formatInboundContent, formatOutboundKmarkdown, isKookBotMentioned, kookInboundConversation, senderDisplayName, } from './protocol.js';
4
4
  import { registerKookWebhookRoutes } from './webhook.js';
5
5
  import { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, } from './ws.js';
6
6
  const logger = getLogger('kook');
@@ -61,18 +61,17 @@ export class KookWebsocketEndpoint {
61
61
  this.#started = false;
62
62
  logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
63
63
  }
64
- async send({ target, payload }) {
64
+ async send({ conversation, payload }) {
65
65
  const body = formatOutboundKmarkdown(payload);
66
- const parsed = parseSendTarget(target);
67
66
  const client = this.#requireClient();
68
- const result = parsed.kind === 'private'
69
- ? await client.sendPrivateMsg(parsed.id, body)
70
- : await client.sendChannelMsg(parsed.id, body);
67
+ const result = conversation.kind === 'private'
68
+ ? await client.sendPrivateMsg(conversation.id, body)
69
+ : await client.sendChannelMsg(conversation.id, body);
71
70
  const messageId = result?.msg_id != null ? String(result.msg_id) : '';
72
71
  logger.debug(formatCompact({
73
72
  op: 'kook_send',
74
73
  endpoint: this.#options.config.name,
75
- target,
74
+ target: `${conversation.kind}:${conversation.id}`,
76
75
  messageId,
77
76
  }));
78
77
  return messageId;
@@ -83,14 +82,13 @@ export class KookWebsocketEndpoint {
83
82
  return;
84
83
  if (msg.authorBot)
85
84
  return;
86
- const target = formatInboundTarget(msg);
85
+ const conversation = kookInboundConversation(String(this.#options.id), msg);
87
86
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
88
87
  void this.#options.gateway.receive({
89
- adapter: this.#options.id,
90
- target,
88
+ conversation,
89
+ message: { conversation, id: msg.id },
91
90
  content: formatInboundContent(msg),
92
91
  sender: senderDisplayName(msg),
93
- id: msg.id,
94
92
  metadata: Object.freeze({
95
93
  endpoint: this.#options.config.name,
96
94
  channelKind: msg.channelKind,
@@ -102,7 +100,7 @@ export class KookWebsocketEndpoint {
102
100
  }).catch((err) => {
103
101
  logger.warn(formatCompact({
104
102
  op: 'kook_gateway_receive_failed',
105
- target,
103
+ target: `${conversation.kind}:${conversation.id}`,
106
104
  error: err instanceof Error ? err.message : String(err),
107
105
  }));
108
106
  });
@@ -220,18 +218,17 @@ export class KookWebhookEndpoint {
220
218
  this.#started = false;
221
219
  logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
222
220
  }
223
- async send({ target, payload }) {
221
+ async send({ conversation, payload }) {
224
222
  const body = formatOutboundKmarkdown(payload);
225
- const parsed = parseSendTarget(target);
226
223
  const client = this.#requireClient();
227
- const result = parsed.kind === 'private'
228
- ? await client.sendPrivateMsg(parsed.id, body)
229
- : await client.sendChannelMsg(parsed.id, body);
224
+ const result = conversation.kind === 'private'
225
+ ? await client.sendPrivateMsg(conversation.id, body)
226
+ : await client.sendChannelMsg(conversation.id, body);
230
227
  const messageId = result?.msg_id != null ? String(result.msg_id) : '';
231
228
  logger.debug(formatCompact({
232
229
  op: 'kook_send',
233
230
  endpoint: this.#options.config.name,
234
- target,
231
+ target: `${conversation.kind}:${conversation.id}`,
235
232
  messageId,
236
233
  }));
237
234
  return messageId;
@@ -242,14 +239,13 @@ export class KookWebhookEndpoint {
242
239
  return;
243
240
  if (msg.authorBot)
244
241
  return;
245
- const target = formatInboundTarget(msg);
242
+ const conversation = kookInboundConversation(String(this.#options.id), msg);
246
243
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
247
244
  void this.#options.gateway.receive({
248
- adapter: this.#options.id,
249
- target,
245
+ conversation,
246
+ message: { conversation, id: msg.id },
250
247
  content: formatInboundContent(msg),
251
248
  sender: senderDisplayName(msg),
252
- id: msg.id,
253
249
  metadata: Object.freeze({
254
250
  endpoint: this.#options.config.name,
255
251
  channelKind: msg.channelKind,
@@ -261,7 +257,7 @@ export class KookWebhookEndpoint {
261
257
  }).catch((err) => {
262
258
  logger.warn(formatCompact({
263
259
  op: 'kook_gateway_receive_failed',
264
- target,
260
+ target: `${conversation.kind}:${conversation.id}`,
265
261
  error: err instanceof Error ? err.message : String(err),
266
262
  }));
267
263
  });
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { formatInboundContent, formatInboundTarget, formatOutboundKmarkdown, parseSendTarget, resolveKookConfig, senderDisplayName, KookPermission, type KookAdapterConfig, type KookInboundMessage, type KookWireSegment, type LogLevel, type ParsedSendTarget, type ResolvedKookConfig, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig, } from './protocol.js';
1
+ export { formatInboundContent, formatOutboundKmarkdown, resolveKookConfig, senderDisplayName, KookPermission, type KookAdapterConfig, type KookInboundMessage, type KookWireSegment, type LogLevel, type ResolvedKookConfig, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig, } from './protocol.js';
2
2
  export { KookWebhookEndpoint, KookWebsocketEndpoint, type KookEndpointOptions, type KookWebhookEndpointOptions, } from './endpoint.js';
3
3
  export { registerKookWebhookRoutes, handleKookWebhookRequest, type KookWebhookHandler, } from './webhook.js';
4
4
  export { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, type CreateKookClient, type KookClientTransport, } from './ws.js';
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { formatInboundContent, formatInboundTarget, formatOutboundKmarkdown, parseSendTarget, resolveKookConfig, senderDisplayName, KookPermission, } from './protocol.js';
1
+ export { formatInboundContent, formatOutboundKmarkdown, resolveKookConfig, senderDisplayName, KookPermission, } from './protocol.js';
2
2
  export { KookWebhookEndpoint, KookWebsocketEndpoint, } from './endpoint.js';
3
3
  export { registerKookWebhookRoutes, handleKookWebhookRequest, } from './webhook.js';
4
4
  export { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, } from './ws.js';
package/lib/protocol.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  * Canonicalization is owned by gateway/core before endpoint.send.
4
4
  */
5
5
  import type { IncomingMessage } from 'node:http';
6
+ import type { ConversationRef } from '@zhin.js/im-contract';
6
7
  export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'mark' | 'off';
7
8
  export declare enum KookPermission {
8
9
  Normal = 1,
@@ -106,16 +107,12 @@ export interface KookWireSegment {
106
107
  readonly type: string;
107
108
  readonly data?: Record<string, unknown>;
108
109
  }
109
- export interface ParsedSendTarget {
110
- readonly kind: 'private' | 'channel';
111
- readonly id: string;
112
- }
113
110
  export declare function resolveKookConfig(config?: KookAdapterConfig): ResolvedKookConfig;
114
111
  /**
115
- * Gateway reply target:`private:uid` / `channel:cid`,便于 send() 还原 API。
112
+ * 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
113
+ * 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
116
114
  */
117
- export declare function formatInboundTarget(msg: KookInboundMessage): string;
118
- export declare function parseSendTarget(target: string): ParsedSendTarget;
115
+ export declare function kookInboundConversation(endpointId: string, msg: KookInboundMessage): ConversationRef;
119
116
  export declare function senderDisplayName(msg: KookInboundMessage): string;
120
117
  /** Build inbound text for MessageGateway.receive */
121
118
  export declare function formatInboundContent(msg: KookInboundMessage): string;
package/lib/protocol.js CHANGED
@@ -62,23 +62,18 @@ export function resolveKookConfig(config = {}) {
62
62
  };
63
63
  }
64
64
  /**
65
- * Gateway reply target:`private:uid` / `channel:cid`,便于 send() 还原 API。
65
+ * 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
66
+ * 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
66
67
  */
67
- export function formatInboundTarget(msg) {
68
- return `${msg.channelKind}:${msg.channelId}`;
69
- }
70
- export function parseSendTarget(target) {
71
- const sep = target.indexOf(':');
72
- if (sep <= 0) {
73
- return { kind: 'channel', id: target };
74
- }
75
- const head = target.slice(0, sep);
76
- const rest = target.slice(sep + 1);
77
- if (head === 'private')
78
- return { kind: 'private', id: rest };
79
- if (head === 'channel' || head === 'group')
80
- return { kind: 'channel', id: rest };
81
- return { kind: 'channel', id: target };
68
+ export function kookInboundConversation(endpointId, msg) {
69
+ return {
70
+ endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
71
+ kind: msg.channelKind,
72
+ id: msg.channelId,
73
+ ...(msg.guildId && msg.channelKind === 'channel'
74
+ ? { parent: { kind: 'channel', id: msg.guildId } }
75
+ : {}),
76
+ };
82
77
  }
83
78
  export function senderDisplayName(msg) {
84
79
  return msg.authorName || msg.authorId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-kook",
3
- "version": "7.0.2",
3
+ "version": "7.0.3",
4
4
  "description": "Zhin.js KOOK adapter for Plugin Runtime (WebSocket gateway or Webhook)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -34,20 +34,21 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "kook-client": "^1.0.4",
37
- "@zhin.js/adapter": "1.1.4",
38
- "@zhin.js/command": "1.0.6",
39
- "@zhin.js/core": "1.5.1",
40
- "@zhin.js/host-http": "1.0.5",
37
+ "@zhin.js/adapter": "1.1.5",
38
+ "@zhin.js/command": "1.0.7",
39
+ "@zhin.js/core": "1.5.2",
40
+ "@zhin.js/host-http": "1.0.6",
41
+ "@zhin.js/im-contract": "1.0.1",
41
42
  "@zhin.js/logger": "1.0.75",
42
- "@zhin.js/plugin-runtime": "1.1.2"
43
+ "@zhin.js/plugin-runtime": "1.1.3"
43
44
  },
44
45
  "peerDependencies": {
45
46
  "zod": "^4.0.0",
46
- "@zhin.js/adapter": "1.1.4",
47
- "@zhin.js/agent": "1.1.2",
48
- "@zhin.js/core": "1.5.1",
49
- "@zhin.js/plugin-runtime": "1.1.2",
50
- "zhin.js": "6.0.1"
47
+ "@zhin.js/adapter": "1.1.5",
48
+ "@zhin.js/agent": "1.1.3",
49
+ "@zhin.js/core": "1.5.2",
50
+ "@zhin.js/plugin-runtime": "1.1.3",
51
+ "zhin.js": "6.0.2"
51
52
  },
52
53
  "peerDependenciesMeta": {
53
54
  "zhin.js": {
@@ -65,9 +66,9 @@
65
66
  "typescript": "^6.0.3",
66
67
  "vitest": "^4.1.10",
67
68
  "zod": "^4.4.3",
68
- "@zhin.js/agent": "1.1.2",
69
- "@zhin.js/host-http": "1.0.5",
70
- "zhin.js": "6.0.1"
69
+ "@zhin.js/agent": "1.1.3",
70
+ "@zhin.js/host-http": "1.0.6",
71
+ "zhin.js": "6.0.2"
71
72
  },
72
73
  "files": [
73
74
  "adapters",
package/src/endpoint.ts CHANGED
@@ -7,6 +7,7 @@ import type {
7
7
  EndpointGroup,
8
8
  EndpointInstance,
9
9
  EndpointManagement,
10
+ EndpointSendRequest,
10
11
  } from '@zhin.js/adapter';
11
12
  import type { MessageGateway } from '@zhin.js/core/runtime';
12
13
  import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
@@ -15,10 +16,9 @@ import type { CapabilityId } from '@zhin.js/plugin-runtime';
15
16
  import { registerKookAgentEndpoint } from './kook-agent-deps.js';
16
17
  import {
17
18
  formatInboundContent,
18
- formatInboundTarget,
19
19
  formatOutboundKmarkdown,
20
20
  isKookBotMentioned,
21
- parseSendTarget,
21
+ kookInboundConversation,
22
22
  senderDisplayName,
23
23
  type KookInboundMessage,
24
24
  type ResolvedKookWebhookConfig,
@@ -102,18 +102,17 @@ export class KookWebsocketEndpoint implements EndpointInstance {
102
102
  logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
103
103
  }
104
104
 
105
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
105
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
106
106
  const body = formatOutboundKmarkdown(payload);
107
- const parsed = parseSendTarget(target);
108
107
  const client = this.#requireClient();
109
- const result = parsed.kind === 'private'
110
- ? await client.sendPrivateMsg(parsed.id, body)
111
- : await client.sendChannelMsg(parsed.id, body);
108
+ const result = conversation.kind === 'private'
109
+ ? await client.sendPrivateMsg(conversation.id, body)
110
+ : await client.sendChannelMsg(conversation.id, body);
112
111
  const messageId = result?.msg_id != null ? String(result.msg_id) : '';
113
112
  logger.debug(formatCompact({
114
113
  op: 'kook_send',
115
114
  endpoint: this.#options.config.name,
116
- target,
115
+ target: `${conversation.kind}:${conversation.id}`,
117
116
  messageId,
118
117
  }));
119
118
  return messageId;
@@ -123,14 +122,13 @@ export class KookWebsocketEndpoint implements EndpointInstance {
123
122
  admit(msg: KookInboundMessage): void {
124
123
  if (!this.#open) return;
125
124
  if (msg.authorBot) return;
126
- const target = formatInboundTarget(msg);
125
+ const conversation = kookInboundConversation(String(this.#options.id), msg);
127
126
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
128
127
  void this.#options.gateway.receive({
129
- adapter: this.#options.id,
130
- target,
128
+ conversation,
129
+ message: { conversation, id: msg.id },
131
130
  content: formatInboundContent(msg),
132
131
  sender: senderDisplayName(msg),
133
- id: msg.id,
134
132
  metadata: Object.freeze({
135
133
  endpoint: this.#options.config.name,
136
134
  channelKind: msg.channelKind,
@@ -142,7 +140,7 @@ export class KookWebsocketEndpoint implements EndpointInstance {
142
140
  }).catch((err) => {
143
141
  logger.warn(formatCompact({
144
142
  op: 'kook_gateway_receive_failed',
145
- target,
143
+ target: `${conversation.kind}:${conversation.id}`,
146
144
  error: err instanceof Error ? err.message : String(err),
147
145
  }));
148
146
  });
@@ -282,18 +280,17 @@ export class KookWebhookEndpoint implements EndpointInstance {
282
280
  logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
283
281
  }
284
282
 
285
- async send({ target, payload }: { readonly target: string; readonly payload: unknown }): Promise<string> {
283
+ async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
286
284
  const body = formatOutboundKmarkdown(payload);
287
- const parsed = parseSendTarget(target);
288
285
  const client = this.#requireClient();
289
- const result = parsed.kind === 'private'
290
- ? await client.sendPrivateMsg(parsed.id, body)
291
- : await client.sendChannelMsg(parsed.id, body);
286
+ const result = conversation.kind === 'private'
287
+ ? await client.sendPrivateMsg(conversation.id, body)
288
+ : await client.sendChannelMsg(conversation.id, body);
292
289
  const messageId = result?.msg_id != null ? String(result.msg_id) : '';
293
290
  logger.debug(formatCompact({
294
291
  op: 'kook_send',
295
292
  endpoint: this.#options.config.name,
296
- target,
293
+ target: `${conversation.kind}:${conversation.id}`,
297
294
  messageId,
298
295
  }));
299
296
  return messageId;
@@ -303,14 +300,13 @@ export class KookWebhookEndpoint implements EndpointInstance {
303
300
  admit(msg: KookInboundMessage): void {
304
301
  if (!this.#open) return;
305
302
  if (msg.authorBot) return;
306
- const target = formatInboundTarget(msg);
303
+ const conversation = kookInboundConversation(String(this.#options.id), msg);
307
304
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
308
305
  void this.#options.gateway.receive({
309
- adapter: this.#options.id,
310
- target,
306
+ conversation,
307
+ message: { conversation, id: msg.id },
311
308
  content: formatInboundContent(msg),
312
309
  sender: senderDisplayName(msg),
313
- id: msg.id,
314
310
  metadata: Object.freeze({
315
311
  endpoint: this.#options.config.name,
316
312
  channelKind: msg.channelKind,
@@ -322,7 +318,7 @@ export class KookWebhookEndpoint implements EndpointInstance {
322
318
  }).catch((err) => {
323
319
  logger.warn(formatCompact({
324
320
  op: 'kook_gateway_receive_failed',
325
- target,
321
+ target: `${conversation.kind}:${conversation.id}`,
326
322
  error: err instanceof Error ? err.message : String(err),
327
323
  }));
328
324
  });
package/src/index.ts CHANGED
@@ -1,8 +1,6 @@
1
1
  export {
2
2
  formatInboundContent,
3
- formatInboundTarget,
4
3
  formatOutboundKmarkdown,
5
- parseSendTarget,
6
4
  resolveKookConfig,
7
5
  senderDisplayName,
8
6
  KookPermission,
@@ -10,7 +8,6 @@ export {
10
8
  type KookInboundMessage,
11
9
  type KookWireSegment,
12
10
  type LogLevel,
13
- type ParsedSendTarget,
14
11
  type ResolvedKookConfig,
15
12
  type ResolvedKookWebhookConfig,
16
13
  type ResolvedKookWebsocketConfig,
package/src/protocol.ts CHANGED
@@ -8,6 +8,7 @@ import { inflateSync } from 'node:zlib';
8
8
  import type { IncomingMessage } from 'node:http';
9
9
  import { pickCredential } from '@zhin.js/adapter';
10
10
  import { isMediaRef } from '@zhin.js/core';
11
+ import type { ConversationRef } from '@zhin.js/im-contract';
11
12
  import { formatCompact, getLogger } from '@zhin.js/logger';
12
13
 
13
14
  const logger = getLogger('kook');
@@ -133,11 +134,6 @@ export interface KookWireSegment {
133
134
  readonly data?: Record<string, unknown>;
134
135
  }
135
136
 
136
- export interface ParsedSendTarget {
137
- readonly kind: 'private' | 'channel';
138
- readonly id: string;
139
- }
140
-
141
137
  export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookConfig {
142
138
  const entry = config.endpoints?.find((item) => item.context === 'kook' || !item.context);
143
139
  const token = pickCredential(config.token, entry?.token, process.env.KOOK_TOKEN, process.env.KOOK_BOT_TOKEN);
@@ -194,22 +190,18 @@ export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookC
194
190
  }
195
191
 
196
192
  /**
197
- * Gateway reply target:`private:uid` / `channel:cid`,便于 send() 还原 API。
193
+ * 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
194
+ * 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
198
195
  */
199
- export function formatInboundTarget(msg: KookInboundMessage): string {
200
- return `${msg.channelKind}:${msg.channelId}`;
201
- }
202
-
203
- export function parseSendTarget(target: string): ParsedSendTarget {
204
- const sep = target.indexOf(':');
205
- if (sep <= 0) {
206
- return { kind: 'channel', id: target };
207
- }
208
- const head = target.slice(0, sep);
209
- const rest = target.slice(sep + 1);
210
- if (head === 'private') return { kind: 'private', id: rest };
211
- if (head === 'channel' || head === 'group') return { kind: 'channel', id: rest };
212
- return { kind: 'channel', id: target };
196
+ export function kookInboundConversation(endpointId: string, msg: KookInboundMessage): ConversationRef {
197
+ return {
198
+ endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
199
+ kind: msg.channelKind,
200
+ id: msg.channelId,
201
+ ...(msg.guildId && msg.channelKind === 'channel'
202
+ ? { parent: { kind: 'channel' as const, id: msg.guildId } }
203
+ : {}),
204
+ };
213
205
  }
214
206
 
215
207
  export function senderDisplayName(msg: KookInboundMessage): string {