@zhin.js/adapter-kook 8.0.0 → 8.0.2

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,35 @@
1
1
  # @zhin.js/adapter-kook
2
2
 
3
+ ## 8.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [736fa04]
8
+ - @zhin.js/agent@1.1.17
9
+ - zhin.js@6.0.14
10
+
11
+ ## 8.0.1
12
+
13
+ ### Patch Changes
14
+
15
+ - 1fc78bc: Unify native platform Client access behind the literal `adapter` discriminant. Handlers infer both native events and Clients, while command, inbound/outbound middleware, and both Agent tool authoring surfaces expose the exact operation-scoped Client through a lazy `$client` getter. Definitions without `adapter` keep `$client` typed as `unknown`, and runtime dispatch rejects adapter mismatches before resolving the Client. Bundled platform tools now use this single path instead of model-provided endpoint ids and adapter-specific dependency wrappers. Every adapter registers one Client/EventMap contract, and protocol adapters including NapCat, Milky, OneBot and Satori now produce transport-independent Client objects rather than letting Endpoint instances impersonate Clients.
16
+ - Updated dependencies [e9c6a73]
17
+ - Updated dependencies [4e8117c]
18
+ - Updated dependencies [902fa35]
19
+ - Updated dependencies [54bfd6b]
20
+ - Updated dependencies [12025ee]
21
+ - Updated dependencies [09b14d6]
22
+ - Updated dependencies [1fc78bc]
23
+ - @zhin.js/agent@1.1.16
24
+ - @zhin.js/adapter@1.2.1
25
+ - @zhin.js/core@1.5.14
26
+ - @zhin.js/host-http@1.0.13
27
+ - @zhin.js/command@1.0.16
28
+ - @zhin.js/logger@1.0.77
29
+ - zhin.js@6.0.14
30
+ - @zhin.js/feature-kit@1.0.13
31
+ - @zhin.js/permission@1.0.4
32
+
3
33
  ## 8.0.0
4
34
 
5
35
  ### Patch Changes
package/README.md CHANGED
@@ -20,7 +20,7 @@ pnpm add @zhin.js/adapter-kook
20
20
  ## Plugin Runtime
21
21
 
22
22
  - `@zhin.js/adapter` — 约定式 `adapters/kook.ts`(`defineAdapter`)
23
- - `@zhin.js/core` — `messageGatewayToken` 入站/出站
23
+ - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
24
24
  - `@zhin.js/host-http` — Webhook 模式 POST 路由(WebSocket 不需要)
25
25
  - `zhin.js` — `plugin.ts`(`definePlugin`)
26
26
  - 配置经插件 `schema.json` 落到 `plugins.<instanceKey>`
@@ -97,7 +97,16 @@ platform permit checker 由 `plugin.ts` 的 generation 生命周期注册;Capa
97
97
 
98
98
  ## 迁移后出站能力变化
99
99
 
100
- 迁移到 Plugin Runtime 后,出站统一经 `messageGatewayToken` 渲染并由 endpoint 编码为 KMarkdown(`sendChannelMsg` / `sendPrivateMsg`)。canonical `markdown` 保留格式;图片、视频、音频和文件仅有远程 URL 时可表示为 KMarkdown 链接。卡片消息与附件上传仍未接入统一出站通道。
100
+ 迁移到 Plugin Runtime 后,出站统一经 `outboundMessageToken` 渲染并由 endpoint 编码为 KMarkdown(`sendChannelMsg` / `sendPrivateMsg`)。canonical `markdown` 保留格式;图片、视频、音频和文件仅有远程 URL 时可表示为 KMarkdown 链接。卡片消息与附件上传仍未接入统一出站通道。
101
+
102
+ ## 故障排查
103
+
104
+ | 现象 | 排查 |
105
+ | --- | --- |
106
+ | WebSocket 无法上线 | 检查 Bot Token、网络与机器人能力开关 |
107
+ | Webhook challenge 失败 | 检查公网路径、`verify_token` 与 HTTP Host |
108
+ | 频道消息未触发 | 检查应用订阅、频道权限与机器人是否已加入服务器 |
109
+ | 附件表现为链接 | 当前统一出站不上传附件;使用远程 URL 或按能力降级 |
101
110
 
102
111
  ## 许可证
103
112
 
package/adapters/kook.js CHANGED
@@ -4,7 +4,6 @@
4
4
  * Implementation lives under `src/` (endpoint / webhook / ws / protocol).
5
5
  */
6
6
  import { defineAdapter } from 'zhin.js/adapter';
7
- import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
8
7
  import { httpHostToken } from '@zhin.js/host-http';
9
8
  import { KookWebhookEndpoint, KookWebsocketEndpoint, } from "../lib/endpoint.js";
10
9
  import { resolveKookConfig, } from "../lib/protocol.js";
@@ -22,8 +21,6 @@ export default defineAdapter({
22
21
  },
23
22
  create(context) {
24
23
  const config = resolveKookConfig(context.config);
25
- const gateway = context.use(messageGatewayToken);
26
- const sideEvents = context.use(sideEventGatewayToken);
27
24
  // 注册到插件运行时状态(kook.endpoint list 的"运行中"数据源)
28
25
  context.use(kookRuntimeStateToken).endpoints.set(config.id, {
29
26
  id: config.id,
@@ -32,16 +29,12 @@ export default defineAdapter({
32
29
  if (config.connection === 'webhook') {
33
30
  return new KookWebhookEndpoint({
34
31
  id: context.id,
35
- gateway,
36
- sideEvents,
37
32
  http: context.use(httpHostToken),
38
33
  config,
39
34
  });
40
35
  }
41
36
  return new KookWebsocketEndpoint({
42
37
  id: context.id,
43
- gateway,
44
- sideEvents,
45
38
  config,
46
39
  });
47
40
  },
package/adapters/kook.ts CHANGED
@@ -3,7 +3,6 @@
3
3
  * Implementation lives under `src/` (endpoint / webhook / ws / protocol).
4
4
  */
5
5
  import { defineAdapter } from 'zhin.js/adapter';
6
- import { messageGatewayToken, sideEventGatewayToken } from '@zhin.js/core/runtime';
7
6
  import { httpHostToken } from '@zhin.js/host-http';
8
7
  import {
9
8
  KookWebhookEndpoint,
@@ -37,8 +36,6 @@ export default defineAdapter<KookAdapterConfig>({
37
36
  },
38
37
  create(context) {
39
38
  const config = resolveKookConfig(context.config);
40
- const gateway = context.use(messageGatewayToken);
41
- const sideEvents = context.use(sideEventGatewayToken);
42
39
  // 注册到插件运行时状态(kook.endpoint list 的"运行中"数据源)
43
40
  context.use(kookRuntimeStateToken).endpoints.set(config.id, {
44
41
  id: config.id,
@@ -47,16 +44,12 @@ export default defineAdapter<KookAdapterConfig>({
47
44
  if (config.connection === 'webhook') {
48
45
  return new KookWebhookEndpoint({
49
46
  id: context.id,
50
- gateway,
51
- sideEvents,
52
47
  http: context.use(httpHostToken),
53
48
  config,
54
49
  });
55
50
  }
56
51
  return new KookWebsocketEndpoint({
57
52
  id: context.id,
58
- gateway,
59
- sideEvents,
60
53
  config,
61
54
  });
62
55
  },
@@ -1,29 +1,27 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }>({
5
+ export default defineAgentTool<{ guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }>({
7
6
  description: 'KOOK 服务器黑名单管理:添加/移除',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  guild_id: z.string().describe('服务器 ID'),
11
9
  action: z.enum(['add', 'remove']).describe('add|remove'),
12
10
  user_id: z.string().describe('用户 ID'),
13
11
  remark: z.string().optional().describe('备注(add 可选)'),
14
12
  }),
15
- platforms: ['kook'],
13
+ adapter: 'kook',
16
14
  tags: ['kook'],
17
15
  permissions: [platformPermit('guild_admin')],
18
- async execute({ endpoint_id, guild_id, action, user_id, remark }: { endpoint_id: string; guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }) {
19
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
16
+ async execute({ guild_id, action, user_id, remark }: { guild_id: string; action: 'add' | 'remove'; user_id: string; remark?: string }, context) {
17
+ const member = context.$client.pickGuildMember(guild_id, user_id);
20
18
  switch (action) {
21
19
  case 'add': {
22
- const success = await endpoint.addToBlacklist(guild_id, user_id, remark);
20
+ const success = await member.addToBlackList(remark);
23
21
  return { success, message: success ? `已将 ${user_id} 加入黑名单` : '操作失败' };
24
22
  }
25
23
  case 'remove': {
26
- const success = await endpoint.removeFromBlacklist(guild_id, user_id);
24
+ const success = await member.removeFromBlackList();
27
25
  return { success, message: success ? `已将 ${user_id} 从黑名单移除` : '操作失败' };
28
26
  }
29
27
  default:
@@ -1,21 +1,19 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; guild_id: string; name: string }>({
5
+ export default defineAgentTool<{ guild_id: string; name: string }>({
7
6
  description: '在 KOOK 服务器中创建新角色',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  guild_id: z.string().describe('服务器 ID'),
11
9
  name: z.string().describe('角色名称'),
12
10
  }),
13
- platforms: ['kook'],
11
+ adapter: 'kook',
14
12
  tags: ['kook'],
15
13
  permissions: [platformPermit('guild_owner')],
16
- async execute({ endpoint_id, guild_id, name }: { endpoint_id: string; guild_id: string; name: string }) {
17
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
18
- const role = await endpoint.createRole(guild_id, name);
14
+ async execute({ guild_id, name }: { guild_id: string; name: string }, context) {
15
+ const client = context.$client;
16
+ const role = await client.pickGuild(guild_id).createRole(name);
19
17
  return {
20
18
  success: true,
21
19
  message: `已创建角色 "${name}"`,
@@ -1,21 +1,19 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; guild_id: string; role_id: string }>({
5
+ export default defineAgentTool<{ guild_id: string; role_id: string }>({
7
6
  description: '删除 KOOK 服务器中的角色',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  guild_id: z.string().describe('服务器 ID'),
11
9
  role_id: z.string().describe('角色 ID'),
12
10
  }),
13
- platforms: ['kook'],
11
+ adapter: 'kook',
14
12
  tags: ['kook'],
15
13
  permissions: [platformPermit('guild_owner')],
16
- async execute({ endpoint_id, guild_id, role_id }: { endpoint_id: string; guild_id: string; role_id: string }) {
17
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
18
- const success = await endpoint.deleteRole(guild_id, role_id);
14
+ async execute({ guild_id, role_id }: { guild_id: string; role_id: string }, context) {
15
+ const client = context.$client;
16
+ const success = await client.pickGuild(guild_id).deleteRole(role_id);
19
17
  return { success, message: success ? `已删除角色 ${role_id}` : '删除角色失败' };
20
18
  },
21
19
  });
@@ -1,22 +1,20 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; guild_id: string; user_id: string; role_id: string }>({
5
+ export default defineAgentTool<{ guild_id: string; user_id: string; role_id: string }>({
7
6
  description: '给用户授予 KOOK 服务器角色',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  guild_id: z.string().describe('服务器 ID'),
11
9
  user_id: z.string().describe('用户 ID'),
12
10
  role_id: z.string().describe('角色 ID'),
13
11
  }),
14
- platforms: ['kook'],
12
+ adapter: 'kook',
15
13
  tags: ['kook'],
16
14
  permissions: [platformPermit('manage_roles')],
17
- async execute({ endpoint_id, guild_id, user_id, role_id }: { endpoint_id: string; guild_id: string; user_id: string; role_id: string }) {
18
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
19
- const success = await endpoint.grantRole(guild_id, user_id, role_id);
15
+ async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
16
+ const client = context.$client;
17
+ const success = await client.pickGuildMember(guild_id, user_id).grant(role_id);
20
18
  return { success, message: success ? `已授予用户 ${user_id} 角色 ${role_id}` : '授予角色失败' };
21
19
  },
22
20
  });
@@ -1,18 +1,16 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
4
3
 
5
- export default defineAgentTool<{ endpoint_id: string; guild_id: string }>({
4
+ export default defineAgentTool<{ guild_id: string }>({
6
5
  description: '获取 KOOK 服务器的角色列表',
7
6
  inputSchema: z.object({
8
- endpoint_id: z.string().describe('Endpoint 名称'),
9
7
  guild_id: z.string().describe('服务器 ID'),
10
8
  }),
11
- platforms: ['kook'],
9
+ adapter: 'kook',
12
10
  tags: ['kook'],
13
- async execute({ endpoint_id, guild_id }: { endpoint_id: string; guild_id: string }) {
14
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
15
- const roles = await endpoint.getRoleList(guild_id);
11
+ async execute({ guild_id }: { guild_id: string }, context) {
12
+ const client = context.$client;
13
+ const roles = await client.pickGuild(guild_id).getRoleList();
16
14
  return {
17
15
  roles: roles.map((r) => ({
18
16
  id: String(r.role_id),
@@ -1,22 +1,20 @@
1
1
  import { defineAgentTool } from '@zhin.js/agent/tools';
2
2
  import { z } from 'zod';
3
3
  import { platformPermit } from '../../src/platform-permit.js';
4
- import { getKookAgentDeps } from '../../src/kook-agent-deps.js';
5
4
 
6
- export default defineAgentTool<{ endpoint_id: string; guild_id: string; user_id: string; role_id: string }>({
5
+ export default defineAgentTool<{ guild_id: string; user_id: string; role_id: string }>({
7
6
  description: '撤销用户的 KOOK 服务器角色',
8
7
  inputSchema: z.object({
9
- endpoint_id: z.string().describe('Endpoint 名称'),
10
8
  guild_id: z.string().describe('服务器 ID'),
11
9
  user_id: z.string().describe('用户 ID'),
12
10
  role_id: z.string().describe('角色 ID'),
13
11
  }),
14
- platforms: ['kook'],
12
+ adapter: 'kook',
15
13
  tags: ['kook'],
16
14
  permissions: [platformPermit('manage_roles')],
17
- async execute({ endpoint_id, guild_id, user_id, role_id }: { endpoint_id: string; guild_id: string; user_id: string; role_id: string }) {
18
- const endpoint = getKookAgentDeps().getEndpoint(endpoint_id);
19
- const success = await endpoint.revokeRole(guild_id, user_id, role_id);
15
+ async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
16
+ const client = context.$client;
17
+ const success = await client.pickGuildMember(guild_id, user_id).revoke(role_id);
20
18
  return { success, message: success ? `已撤销用户 ${user_id} 的角色 ${role_id}` : '撤销角色失败' };
21
19
  },
22
20
  });
@@ -0,0 +1,11 @@
1
+ import type { KookClientTransport } from './ws.js';
2
+ export type KookClientEventMap = Record<string, unknown>;
3
+ declare module '@zhin.js/feature-kit' {
4
+ interface AdapterClientRegistry {
5
+ readonly kook: {
6
+ readonly client: KookClientTransport;
7
+ readonly events: KookClientEventMap;
8
+ };
9
+ }
10
+ }
11
+ export declare const kookClient: import("@zhin.js/adapter").EndpointClientToken<KookClientTransport, KookClientEventMap>;
package/lib/client.js ADDED
@@ -0,0 +1,2 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ export const kookClient = defineEndpointClient('kook');
package/lib/endpoint.d.ts CHANGED
@@ -1,59 +1,41 @@
1
- import { type EndpointControl, type EndpointInstance, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
2
- import type { MessageGateway, SideEventGateway } from '@zhin.js/core/runtime';
1
+ import { Endpoint } from 'zhin.js/adapter';
2
+ import { type EndpointControl, type EndpointManagement, type EndpointSendRequest } from 'zhin.js/adapter';
3
3
  import type { HttpHost } from '@zhin.js/host-http';
4
4
  import type { CapabilityId } from 'zhin.js';
5
- import { type KookInboundMessage, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig } from './protocol.js';
5
+ import { type KookInboundMessage, type KookWebhookEventData, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig } from './protocol.js';
6
6
  import { type CreateKookClient, type KookClientTransport } from './ws.js';
7
7
  export interface KookEndpointOptions {
8
8
  readonly id: CapabilityId;
9
- readonly gateway: MessageGateway;
10
- readonly sideEvents?: SideEventGateway;
11
9
  readonly config: ResolvedKookWebsocketConfig;
12
10
  readonly createClient?: CreateKookClient;
13
11
  }
14
- export declare class KookWebsocketEndpoint implements EndpointInstance {
12
+ export declare class KookWebsocketEndpoint extends Endpoint<KookClientTransport> {
15
13
  #private;
16
14
  readonly management: EndpointManagement;
17
15
  readonly control: EndpointControl;
18
16
  constructor(options: KookEndpointOptions);
17
+ get client(): KookClientTransport;
19
18
  start(): Promise<void>;
20
19
  open(): void;
21
20
  close(): void;
22
21
  stop(): Promise<void>;
23
22
  send({ conversation, payload }: EndpointSendRequest): Promise<string>;
24
- /** Test / internal: admit a message when open. */
23
+ /** Test / internal: admit a normalized message when open. */
25
24
  admit(msg: KookInboundMessage): void;
26
25
  recallMessage(messageId: string): Promise<void>;
27
- getRoleList(guildId: string): Promise<{
28
- role_id: string | number;
29
- name: string;
30
- color?: number;
31
- position?: number;
32
- permissions?: unknown;
33
- }[]>;
34
- createRole(guildId: string, name: string): Promise<{
35
- role_id: string | number;
36
- name: string;
37
- }>;
38
- deleteRole(guildId: string, roleId: string): Promise<boolean>;
39
- grantRole(guildId: string, userId: string, roleId: string): Promise<boolean>;
40
- revokeRole(guildId: string, userId: string, roleId: string): Promise<boolean>;
41
- addToBlacklist(guildId: string, userId: string, remark?: string): Promise<boolean>;
42
- removeFromBlacklist(guildId: string, userId: string): Promise<boolean>;
43
26
  }
44
27
  export interface KookWebhookEndpointOptions {
45
28
  readonly id: CapabilityId;
46
- readonly gateway: MessageGateway;
47
- readonly sideEvents?: SideEventGateway;
48
29
  readonly http: HttpHost;
49
30
  readonly config: ResolvedKookWebhookConfig;
50
31
  readonly createClient?: CreateKookClient;
51
32
  }
52
- export declare class KookWebhookEndpoint implements EndpointInstance {
33
+ export declare class KookWebhookEndpoint extends Endpoint<KookClientTransport> {
53
34
  #private;
54
35
  readonly management: EndpointManagement;
55
36
  readonly control: EndpointControl;
56
37
  constructor(options: KookWebhookEndpointOptions);
38
+ get client(): KookClientTransport;
57
39
  /** Used by webhook handler. */
58
40
  get isOpen(): boolean;
59
41
  get config(): ResolvedKookWebhookConfig;
@@ -63,26 +45,11 @@ export declare class KookWebhookEndpoint implements EndpointInstance {
63
45
  close(): void;
64
46
  stop(): Promise<void>;
65
47
  send({ conversation, payload }: EndpointSendRequest): Promise<string>;
48
+ admitEvent(event: KookWebhookEventData): void;
66
49
  /** Test / internal: admit a message when open. */
67
50
  admit(msg: KookInboundMessage): void;
68
51
  recallMessage(messageId: string): Promise<void>;
69
52
  checkAndRememberSn(sn: number): boolean;
70
- getRoleList(guildId: string): Promise<{
71
- role_id: string | number;
72
- name: string;
73
- color?: number;
74
- position?: number;
75
- permissions?: unknown;
76
- }[]>;
77
- createRole(guildId: string, name: string): Promise<{
78
- role_id: string | number;
79
- name: string;
80
- }>;
81
- deleteRole(guildId: string, roleId: string): Promise<boolean>;
82
- grantRole(guildId: string, userId: string, roleId: string): Promise<boolean>;
83
- revokeRole(guildId: string, userId: string, roleId: string): Promise<boolean>;
84
- addToBlacklist(guildId: string, userId: string, remark?: string): Promise<boolean>;
85
- removeFromBlacklist(guildId: string, userId: string): Promise<boolean>;
86
53
  }
87
54
  /**
88
55
  * KOOK endpoint 的 EndpointManagement 语义端口(websocket / webhook 共用)。
package/lib/endpoint.js CHANGED
@@ -1,31 +1,33 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
1
2
  import { createRecallEndpointControl, } from 'zhin.js/adapter';
2
3
  import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
3
- import { registerKookAgentEndpoint } from './kook-agent-deps.js';
4
- import { formatInboundContent, formatOutboundKmarkdown, isKookBotMentioned, kookInboundConversation, senderDisplayName, } from './protocol.js';
4
+ import { formatInboundContent, formatOutboundKmarkdown, isKookBotMentioned, kookInboundConversation, normalizeKookWebhookEvent, senderDisplayName, } from './protocol.js';
5
5
  import { registerKookWebhookRoutes } from './webhook.js';
6
6
  import { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, } from './ws.js';
7
7
  import { receiveKookSideEvent } from './side-event-dispatch.js';
8
- export class KookWebsocketEndpoint {
8
+ export class KookWebsocketEndpoint extends Endpoint {
9
9
  #logger;
10
10
  #options;
11
11
  #createClient;
12
12
  #client = null;
13
13
  #open = false;
14
14
  #started = false;
15
- #unregisterAgent;
16
15
  management = createKookEndpointManagement(() => this.#requireClient());
17
16
  control = createRecallEndpointControl((id) => this.recallMessage(id));
18
17
  constructor(options) {
18
+ super();
19
19
  this.#logger = getAdapterLogger('kook', options.config.id);
20
20
  this.#options = options;
21
21
  this.#createClient = options.createClient ?? defaultCreateClient;
22
22
  }
23
+ get client() {
24
+ return this.#requireClient();
25
+ }
23
26
  async start() {
24
27
  if (this.#started)
25
28
  return;
26
29
  this.#started = true;
27
30
  try {
28
- this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
29
31
  this.#client = this.#createClient(this.#options.config);
30
32
  this.#bindClient(this.#client);
31
33
  await this.#client.connect();
@@ -50,8 +52,6 @@ export class KookWebsocketEndpoint {
50
52
  }
51
53
  async stop() {
52
54
  this.#open = false;
53
- this.#unregisterAgent?.();
54
- this.#unregisterAgent = undefined;
55
55
  if (this.#client) {
56
56
  try {
57
57
  this.#client.removeAllListeners();
@@ -80,7 +80,7 @@ export class KookWebsocketEndpoint {
80
80
  }));
81
81
  return messageId;
82
82
  }
83
- /** Test / internal: admit a message when open. */
83
+ /** Test / internal: admit a normalized message when open. */
84
84
  admit(msg) {
85
85
  if (!this.#open)
86
86
  return;
@@ -88,7 +88,7 @@ export class KookWebsocketEndpoint {
88
88
  return;
89
89
  const conversation = kookInboundConversation(String(this.#options.id), msg);
90
90
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
91
- void this.#options.gateway.receive({
91
+ void this.emit('message.receive', {
92
92
  conversation,
93
93
  message: { conversation, id: msg.id },
94
94
  content: formatInboundContent(msg),
@@ -118,37 +118,26 @@ export class KookWebsocketEndpoint {
118
118
  return;
119
119
  await this.#requireClient().recallMsg?.(messageId);
120
120
  }
121
- // ── Agent tool surface ──────────────────────────────────────────────
122
- async getRoleList(guildId) {
123
- return this.#requireClient().pickGuild(guildId).getRoleList();
124
- }
125
- async createRole(guildId, name) {
126
- return this.#requireClient().pickGuild(guildId).createRole(name);
127
- }
128
- async deleteRole(guildId, roleId) {
129
- return this.#requireClient().pickGuild(guildId).deleteRole(roleId);
130
- }
131
- async grantRole(guildId, userId, roleId) {
132
- return this.#requireClient().pickGuildMember(guildId, userId).grant(roleId);
133
- }
134
- async revokeRole(guildId, userId, roleId) {
135
- return this.#requireClient().pickGuildMember(guildId, userId).revoke(roleId);
136
- }
137
- async addToBlacklist(guildId, userId, remark) {
138
- return this.#requireClient().pickGuildMember(guildId, userId).addToBlackList(remark);
139
- }
140
- async removeFromBlacklist(guildId, userId) {
141
- return this.#requireClient().pickGuildMember(guildId, userId).removeFromBlackList();
142
- }
143
121
  #bindClient(client) {
144
122
  client.on('message', (raw) => {
123
+ this.#emitPlatformEvent('message', raw);
145
124
  const msg = normalizeKookMessage(raw);
146
125
  if (msg)
147
126
  this.admit(msg);
148
127
  });
149
128
  const receiver = client.receiver;
150
129
  receiver?.on('event', (raw) => {
151
- receiveKookSideEvent(this.#options.sideEvents, this.#options.config.id, raw, this.#logger);
130
+ this.#emitPlatformEvent('event', raw);
131
+ receiveKookSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, raw, this.#logger);
132
+ });
133
+ }
134
+ #emitPlatformEvent(name, event) {
135
+ void this.emitPlatform(name, event).catch((error) => {
136
+ this.#logger.warn(formatCompact({
137
+ op: 'kook_platform_event_failed',
138
+ event: name,
139
+ error: error instanceof Error ? error.message : String(error),
140
+ }));
152
141
  });
153
142
  }
154
143
  #requireClient() {
@@ -157,7 +146,7 @@ export class KookWebsocketEndpoint {
157
146
  return this.#client;
158
147
  }
159
148
  }
160
- export class KookWebhookEndpoint {
149
+ export class KookWebhookEndpoint extends Endpoint {
161
150
  #logger;
162
151
  #options;
163
152
  #createClient;
@@ -166,14 +155,17 @@ export class KookWebhookEndpoint {
166
155
  #processedSn = new Set();
167
156
  #open = false;
168
157
  #started = false;
169
- #unregisterAgent;
170
158
  management = createKookEndpointManagement(() => this.#requireClient());
171
159
  control = createRecallEndpointControl((id) => this.recallMessage(id));
172
160
  constructor(options) {
161
+ super();
173
162
  this.#logger = getAdapterLogger('kook', options.config.id);
174
163
  this.#options = options;
175
164
  this.#createClient = options.createClient ?? defaultCreateWebhookClient;
176
165
  }
166
+ get client() {
167
+ return this.#requireClient();
168
+ }
177
169
  /** Used by webhook handler. */
178
170
  get isOpen() {
179
171
  return this.#open;
@@ -189,7 +181,6 @@ export class KookWebhookEndpoint {
189
181
  return;
190
182
  this.#started = true;
191
183
  try {
192
- this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
193
184
  this.#client = this.#createClient(this.#options.config);
194
185
  await this.#client.init();
195
186
  this.#routeReleases.push(...registerKookWebhookRoutes(this.#options.http, this));
@@ -217,8 +208,6 @@ export class KookWebhookEndpoint {
217
208
  this.#open = false;
218
209
  for (const release of this.#routeReleases.splice(0))
219
210
  release();
220
- this.#unregisterAgent?.();
221
- this.#unregisterAgent = undefined;
222
211
  this.#processedSn.clear();
223
212
  if (this.#client) {
224
213
  try {
@@ -248,6 +237,23 @@ export class KookWebhookEndpoint {
248
237
  }));
249
238
  return messageId;
250
239
  }
240
+ admitEvent(event) {
241
+ void this.emitPlatform(String(event.type ?? 'event'), event).catch((error) => {
242
+ this.#logger.warn(formatCompact({
243
+ op: 'kook_platform_event_failed',
244
+ event: String(event.type ?? 'event'),
245
+ error: error instanceof Error ? error.message : String(error),
246
+ }));
247
+ });
248
+ if (receiveKookSideEvent((name, payload) => this.emit(name, payload), this.#options.config.id, event, this.#logger))
249
+ return;
250
+ const message = normalizeKookWebhookEvent(event, {
251
+ ignore: this.#options.config.ignore,
252
+ selfId: this.selfId,
253
+ });
254
+ if (message)
255
+ this.admit(message);
256
+ }
251
257
  /** Test / internal: admit a message when open. */
252
258
  admit(msg) {
253
259
  if (!this.#open)
@@ -256,7 +262,7 @@ export class KookWebhookEndpoint {
256
262
  return;
257
263
  const conversation = kookInboundConversation(String(this.#options.id), msg);
258
264
  const selfId = this.#client?.self_id != null ? String(this.#client.self_id) : undefined;
259
- void this.#options.gateway.receive({
265
+ void this.emit('message.receive', {
260
266
  conversation,
261
267
  message: { conversation, id: msg.id },
262
268
  content: formatInboundContent(msg),
@@ -297,27 +303,6 @@ export class KookWebhookEndpoint {
297
303
  }
298
304
  return true;
299
305
  }
300
- async getRoleList(guildId) {
301
- return this.#requireClient().pickGuild(guildId).getRoleList();
302
- }
303
- async createRole(guildId, name) {
304
- return this.#requireClient().pickGuild(guildId).createRole(name);
305
- }
306
- async deleteRole(guildId, roleId) {
307
- return this.#requireClient().pickGuild(guildId).deleteRole(roleId);
308
- }
309
- async grantRole(guildId, userId, roleId) {
310
- return this.#requireClient().pickGuildMember(guildId, userId).grant(roleId);
311
- }
312
- async revokeRole(guildId, userId, roleId) {
313
- return this.#requireClient().pickGuildMember(guildId, userId).revoke(roleId);
314
- }
315
- async addToBlacklist(guildId, userId, remark) {
316
- return this.#requireClient().pickGuildMember(guildId, userId).addToBlackList(remark);
317
- }
318
- async removeFromBlacklist(guildId, userId) {
319
- return this.#requireClient().pickGuildMember(guildId, userId).removeFromBlackList();
320
- }
321
306
  #requireClient() {
322
307
  if (!this.#client)
323
308
  throw new Error('KOOK client not initialized');
package/lib/index.d.ts CHANGED
@@ -2,5 +2,5 @@ export { formatInboundContent, formatOutboundKmarkdown, resolveKookConfig, sende
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';
5
- export { getKookAgentDeps, registerKookAgentEndpoint, setKookAgentDeps, type KookAgentDeps, type KookAgentEndpoint, } from './kook-agent-deps.js';
5
+ export { kookClient, type KookClientEventMap } from './client.js';
6
6
  export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, type KookSenderInfo, } from './platform-permit.js';
package/lib/index.js CHANGED
@@ -2,5 +2,5 @@ export { formatInboundContent, formatOutboundKmarkdown, resolveKookConfig, sende
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';
5
- export { getKookAgentDeps, registerKookAgentEndpoint, setKookAgentDeps, } from './kook-agent-deps.js';
5
+ export { kookClient } from './client.js';
6
6
  export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, } from './platform-permit.js';