@zhin.js/adapter-kook 1.1.26 → 1.1.27

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/LICENSE +21 -0
  3. package/PERMITS.md +20 -14
  4. package/README.md +6 -2
  5. package/adapters/kook/index.js +3 -0
  6. package/adapters/kook/index.ts +3 -0
  7. package/agents/kook/conversation.js +88 -0
  8. package/agents/kook/conversation.ts +99 -0
  9. package/agents/kook/messages.js +16 -0
  10. package/agents/kook/messages.ts +16 -0
  11. package/agents/kook/skills/kook/tools/blacklist/index.js +9 -6
  12. package/agents/kook/skills/kook/tools/blacklist/index.ts +9 -7
  13. package/agents/kook/skills/kook/tools/create_role/index.js +5 -6
  14. package/agents/kook/skills/kook/tools/create_role/index.ts +6 -7
  15. package/agents/kook/skills/kook/tools/delete_role/index.js +5 -6
  16. package/agents/kook/skills/kook/tools/delete_role/index.ts +6 -7
  17. package/agents/kook/skills/kook/tools/grant_role/index.js +9 -7
  18. package/agents/kook/skills/kook/tools/grant_role/index.ts +9 -8
  19. package/agents/kook/skills/kook/tools/list_roles/index.js +5 -7
  20. package/agents/kook/skills/kook/tools/list_roles/index.ts +6 -8
  21. package/agents/kook/skills/kook/tools/revoke_role/index.js +9 -7
  22. package/agents/kook/skills/kook/tools/revoke_role/index.ts +9 -8
  23. package/lib/endpoint.d.ts +2 -1
  24. package/lib/endpoint.js +27 -12
  25. package/lib/index.d.ts +1 -1
  26. package/lib/index.js +1 -1
  27. package/lib/platform-permit.d.ts +4 -19
  28. package/lib/platform-permit.js +7 -46
  29. package/lib/protocol.d.ts +1 -5
  30. package/lib/protocol.js +3 -28
  31. package/lib/sender-roles.d.ts +6 -6
  32. package/lib/sender-roles.js +55 -21
  33. package/lib/webhook.d.ts +1 -2
  34. package/lib/webhook.js +13 -33
  35. package/package.json +23 -26
  36. package/plugin.js +0 -6
  37. package/schema.json +0 -56
  38. package/src/endpoint.ts +27 -13
  39. package/src/index.ts +1 -7
  40. package/src/platform-permit.ts +5 -70
  41. package/src/protocol.ts +4 -33
  42. package/src/sender-roles.ts +59 -27
  43. package/src/webhook.ts +14 -36
@@ -1,21 +1,20 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentGuild } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '在 KOOK 服务器中创建新角色',
7
+ description: '在当前 KOOK 服务器中创建新角色',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  name: z.string().describe('角色名称'),
11
10
  }),
12
11
  adapter: 'kook',
13
12
  scopes: ["channel"],
14
13
  tags: ['kook'],
15
- permissions: [platformPermission('kook', 'guild_owner')],
16
- async execute({ guild_id, name }, context) {
14
+ permissions: ['platform:owner', 'bot-permission:manage_roles'],
15
+ async execute({ name }, context) {
17
16
  const client = context.$client;
18
- const role = await client.pickGuild(guild_id).createRole(name);
17
+ const role = await client.pickGuild(currentGuild(context)).createRole(name);
19
18
  return {
20
19
  success: true,
21
20
  message: t(context.locale, 'roleCreated', { p0: name }),
@@ -1,21 +1,20 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentGuild } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
- export default defineAgentTool<{ guild_id: string; name: string }>({
7
- description: '在 KOOK 服务器中创建新角色',
6
+ export default defineAgentTool<{ name: string }>({
7
+ description: '在当前 KOOK 服务器中创建新角色',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  name: z.string().describe('角色名称'),
11
10
  }),
12
11
  adapter: 'kook',
13
12
  scopes: ["channel"],
14
13
  tags: ['kook'],
15
- permissions: [platformPermission('kook', 'guild_owner')],
16
- async execute({ guild_id, name }: { guild_id: string; name: string }, context) {
14
+ permissions: ['platform:owner', 'bot-permission:manage_roles'],
15
+ async execute({ name }, context) {
17
16
  const client = context.$client;
18
- const role = await client.pickGuild(guild_id).createRole(name);
17
+ const role = await client.pickGuild(currentGuild(context)).createRole(name);
19
18
  return {
20
19
  success: true,
21
20
  message: t(context.locale, 'roleCreated', { p0: name }),
@@ -1,21 +1,20 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentGuild } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '删除 KOOK 服务器中的角色',
7
+ description: '删除当前 KOOK 服务器中的角色',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  role_id: z.string().describe('角色 ID'),
11
10
  }),
12
11
  adapter: 'kook',
13
12
  scopes: ["channel"],
14
13
  tags: ['kook'],
15
- permissions: [platformPermission('kook', 'guild_owner')],
16
- async execute({ guild_id, role_id }, context) {
14
+ permissions: ['platform:owner', 'bot-permission:manage_roles'],
15
+ async execute({ role_id }, context) {
17
16
  const client = context.$client;
18
- const success = await client.pickGuild(guild_id).deleteRole(role_id);
17
+ const success = await client.pickGuild(currentGuild(context)).deleteRole(role_id);
19
18
  return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
20
19
  },
21
20
  });
@@ -1,21 +1,20 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentGuild } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
- export default defineAgentTool<{ guild_id: string; role_id: string }>({
7
- description: '删除 KOOK 服务器中的角色',
6
+ export default defineAgentTool<{ role_id: string }>({
7
+ description: '删除当前 KOOK 服务器中的角色',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  role_id: z.string().describe('角色 ID'),
11
10
  }),
12
11
  adapter: 'kook',
13
12
  scopes: ["channel"],
14
13
  tags: ['kook'],
15
- permissions: [platformPermission('kook', 'guild_owner')],
16
- async execute({ guild_id, role_id }: { guild_id: string; role_id: string }, context) {
14
+ permissions: ['platform:owner', 'bot-permission:manage_roles'],
15
+ async execute({ role_id }, context) {
17
16
  const client = context.$client;
18
- const success = await client.pickGuild(guild_id).deleteRole(role_id);
17
+ const success = await client.pickGuild(currentGuild(context)).deleteRole(role_id);
19
18
  return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
20
19
  },
21
20
  });
@@ -1,22 +1,24 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '给用户授予 KOOK 服务器角色',
7
+ description: '在当前 KOOK 服务器给用户授予角色(只能是低于你最高角色的角色)',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  user_id: z.string().describe('用户 ID'),
11
10
  role_id: z.string().describe('角色 ID'),
12
11
  }),
13
12
  adapter: 'kook',
14
13
  scopes: ["channel"],
15
14
  tags: ['kook'],
16
- permissions: [platformPermission('kook', 'manage_roles')],
17
- async execute({ guild_id, user_id, role_id }, context) {
18
- const client = context.$client;
19
- const success = await client.pickGuildMember(guild_id, user_id).grant(role_id);
15
+ permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
16
+ async execute({ user_id, role_id }, context) {
17
+ const guildId = currentGuild(context);
18
+ const denied = await requireRoleBelowRequester(context, guildId, role_id);
19
+ if (denied)
20
+ return { success: false, message: denied };
21
+ const success = await context.$client.pickGuildMember(guildId, user_id).grant(role_id);
20
22
  return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
21
23
  },
22
24
  });
@@ -1,22 +1,23 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
- export default defineAgentTool<{ guild_id: string; user_id: string; role_id: string }>({
7
- description: '给用户授予 KOOK 服务器角色',
6
+ export default defineAgentTool<{ user_id: string; role_id: string }>({
7
+ description: '在当前 KOOK 服务器给用户授予角色(只能是低于你最高角色的角色)',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  user_id: z.string().describe('用户 ID'),
11
10
  role_id: z.string().describe('角色 ID'),
12
11
  }),
13
12
  adapter: 'kook',
14
13
  scopes: ["channel"],
15
14
  tags: ['kook'],
16
- permissions: [platformPermission('kook', 'manage_roles')],
17
- async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
18
- const client = context.$client;
19
- const success = await client.pickGuildMember(guild_id, user_id).grant(role_id);
15
+ permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
16
+ async execute({ user_id, role_id }, context) {
17
+ const guildId = currentGuild(context);
18
+ const denied = await requireRoleBelowRequester(context, guildId, role_id);
19
+ if (denied) return { success: false, message: denied };
20
+ const success = await context.$client.pickGuildMember(guildId, user_id).grant(role_id);
20
21
  return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
21
22
  },
22
23
  });
@@ -1,17 +1,15 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { currentGuild } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
5
  export default defineAgentTool({
5
- description: '获取 KOOK 服务器的角色列表',
6
- inputSchema: z.object({
7
- guild_id: z.string().describe('服务器 ID'),
8
- }),
6
+ description: '获取当前 KOOK 服务器的角色列表(position 越小优先级越高)',
7
+ inputSchema: z.object({}),
9
8
  adapter: 'kook',
10
9
  scopes: ["channel"],
11
10
  tags: ['kook'],
12
- async execute({ guild_id }, context) {
13
- const client = context.$client;
14
- const roles = await client.pickGuild(guild_id).getRoleList();
11
+ async execute(_args, context) {
12
+ const roles = await context.$client.pickGuild(currentGuild(context)).getRoleList();
15
13
  return {
16
14
  roles: roles.map((r) => ({
17
15
  id: String(r.role_id),
@@ -1,17 +1,15 @@
1
+ import { currentGuild } from "../../../../conversation.js";
1
2
  import { defineAgentTool } from '@zhin.js/tool';
2
3
  import { z } from 'zod';
3
4
 
4
- export default defineAgentTool<{ guild_id: string }>({
5
- description: '获取 KOOK 服务器的角色列表',
6
- inputSchema: z.object({
7
- guild_id: z.string().describe('服务器 ID'),
8
- }),
5
+ export default defineAgentTool<Record<string, never>>({
6
+ description: '获取当前 KOOK 服务器的角色列表(position 越小优先级越高)',
7
+ inputSchema: z.object({}),
9
8
  adapter: 'kook',
10
9
  scopes: ["channel"],
11
10
  tags: ['kook'],
12
- async execute({ guild_id }: { guild_id: string }, context) {
13
- const client = context.$client;
14
- const roles = await client.pickGuild(guild_id).getRoleList();
11
+ async execute(_args, context) {
12
+ const roles = await context.$client.pickGuild(currentGuild(context)).getRoleList();
15
13
  return {
16
14
  roles: roles.map((r) => ({
17
15
  id: String(r.role_id),
@@ -1,22 +1,24 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { messages as t } from "../../../../messages.js";
3
+ import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
3
4
  import { defineAgentTool } from '@zhin.js/tool';
4
5
  import { z } from 'zod';
5
- import { platformPermission } from '@zhin.js/permission';
6
6
  export default defineAgentTool({
7
- description: '撤销用户的 KOOK 服务器角色',
7
+ description: '撤销当前 KOOK 服务器中用户的角色(只能是低于你最高角色的角色)',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  user_id: z.string().describe('用户 ID'),
11
10
  role_id: z.string().describe('角色 ID'),
12
11
  }),
13
12
  adapter: 'kook',
14
13
  scopes: ["channel"],
15
14
  tags: ['kook'],
16
- permissions: [platformPermission('kook', 'manage_roles')],
17
- async execute({ guild_id, user_id, role_id }, context) {
18
- const client = context.$client;
19
- const success = await client.pickGuildMember(guild_id, user_id).revoke(role_id);
15
+ permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
16
+ async execute({ user_id, role_id }, context) {
17
+ const guildId = currentGuild(context);
18
+ const denied = await requireRoleBelowRequester(context, guildId, role_id);
19
+ if (denied)
20
+ return { success: false, message: denied };
21
+ const success = await context.$client.pickGuildMember(guildId, user_id).revoke(role_id);
20
22
  return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
21
23
  },
22
24
  });
@@ -1,22 +1,23 @@
1
1
  import { messages as t } from "../../../../messages.js";
2
+ import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
2
3
  import { defineAgentTool } from '@zhin.js/tool';
3
4
  import { z } from 'zod';
4
- import { platformPermission } from '@zhin.js/permission';
5
5
 
6
- export default defineAgentTool<{ guild_id: string; user_id: string; role_id: string }>({
7
- description: '撤销用户的 KOOK 服务器角色',
6
+ export default defineAgentTool<{ user_id: string; role_id: string }>({
7
+ description: '撤销当前 KOOK 服务器中用户的角色(只能是低于你最高角色的角色)',
8
8
  inputSchema: z.object({
9
- guild_id: z.string().describe('服务器 ID'),
10
9
  user_id: z.string().describe('用户 ID'),
11
10
  role_id: z.string().describe('角色 ID'),
12
11
  }),
13
12
  adapter: 'kook',
14
13
  scopes: ["channel"],
15
14
  tags: ['kook'],
16
- permissions: [platformPermission('kook', 'manage_roles')],
17
- async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
18
- const client = context.$client;
19
- const success = await client.pickGuildMember(guild_id, user_id).revoke(role_id);
15
+ permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
16
+ async execute({ user_id, role_id }, context) {
17
+ const guildId = currentGuild(context);
18
+ const denied = await requireRoleBelowRequester(context, guildId, role_id);
19
+ if (denied) return { success: false, message: denied };
20
+ const success = await context.$client.pickGuildMember(guildId, user_id).revoke(role_id);
20
21
  return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
21
22
  },
22
23
  });
package/lib/endpoint.d.ts CHANGED
@@ -7,6 +7,7 @@ import type { HttpHost } from '@zhin.js/host-http';
7
7
  import type { CapabilityId } from 'zhin.js';
8
8
  import { type KookInboundMessage, type KookWebhookEventData, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig } from './protocol.js';
9
9
  import { RuntimeKookClient, type KookClientTransport } from './ws.js';
10
+ import { KookSenderRoleResolver } from './sender-roles.js';
10
11
  export interface KookEndpointOptions {
11
12
  readonly id: CapabilityId;
12
13
  readonly config: ResolvedKookWebsocketConfig;
@@ -45,4 +46,4 @@ export declare class KookWebhookEndpoint extends RuntimeKookClient implements En
45
46
  * 数据走 kook-client 的 HTTP API 封装:/api/v3/guild/list、
46
47
  * /api/v3/channel/list、/api/v3/guild/user-list(SDK 内部已做分页聚合)。
47
48
  */
48
- export declare function createKookEndpointManagement(requireClient: () => KookClientTransport): EndpointManagement;
49
+ export declare function createKookEndpointManagement(requireClient: () => KookClientTransport, roles?: KookSenderRoleResolver): EndpointManagement;
package/lib/endpoint.js CHANGED
@@ -11,8 +11,8 @@ import { recallKookMessage, sendKookOutbound } from './outbound.js';
11
11
  import { KookSenderRoleResolver } from './sender-roles.js';
12
12
  import { receiveKookSideEvent } from './side-event-dispatch.js';
13
13
  import { createKookSelfProfile } from './self-profile.js';
14
- /** 入站 message.receive 载荷:规范角色 owner/admin 进 roles,原始角色 id 进 permissions。 */
15
- function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
14
+ /** 入站 message.receive 载荷:发送者平台身份进 `sender.platform`(ADR 0056 §1)。 */
15
+ function kookInboundPayload(endpointId, conversation, msg, platform, selfId) {
16
16
  return {
17
17
  conversation,
18
18
  event: msg.event,
@@ -22,8 +22,7 @@ function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
22
22
  sender: {
23
23
  id: msg.authorId,
24
24
  name: senderDisplayName(msg) || undefined,
25
- ...(projection.role ? { roles: [projection.role] } : {}),
26
- ...(projection.permissions.length ? { permissions: [...projection.permissions] } : {}),
25
+ ...(platform ? { platform } : {}),
27
26
  },
28
27
  endpointId,
29
28
  ...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
@@ -32,7 +31,6 @@ function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
32
31
  userId: msg.authorId,
33
32
  guildId: msg.guildId,
34
33
  authorRoleIds: msg.authorRoles,
35
- ...(projection.role ? { senderRole: projection.role } : {}),
36
34
  }),
37
35
  };
38
36
  }
@@ -45,7 +43,7 @@ export class KookWebsocketEndpoint extends RuntimeKookClient {
45
43
  #open = false;
46
44
  #executionSignal;
47
45
  #started = false;
48
- #management = createKookEndpointManagement(() => this.#requireClient());
46
+ #management = createKookEndpointManagement(() => this.#requireClient(), this.#roles);
49
47
  #control = Object.freeze({
50
48
  recall: request => recallKookMessage(this.#requireClient(), request),
51
49
  });
@@ -122,9 +120,9 @@ export class KookWebsocketEndpoint extends RuntimeKookClient {
122
120
  return;
123
121
  const conversation = kookInboundConversation(String(this.#options.id), msg);
124
122
  const selfId = this.self_id != null ? String(this.self_id) : undefined;
125
- return this.#roles.resolve(msg).then((projection) => {
123
+ return this.#roles.resolve(msg).then((platform) => {
126
124
  this.#executionSignal?.throwIfAborted();
127
- return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, projection, selfId));
125
+ return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, platform, selfId));
128
126
  }).catch((err) => {
129
127
  this.#logger.warn(formatCompact({
130
128
  op: 'kook_gateway_receive_failed',
@@ -196,7 +194,7 @@ export class KookWebhookEndpoint extends RuntimeKookClient {
196
194
  #open = false;
197
195
  #executionSignal;
198
196
  #started = false;
199
- #management = createKookEndpointManagement(() => this.#requireClient());
197
+ #management = createKookEndpointManagement(() => this.#requireClient(), this.#roles);
200
198
  #control = Object.freeze({
201
199
  recall: request => recallKookMessage(this.#requireClient(), request),
202
200
  });
@@ -306,9 +304,9 @@ export class KookWebhookEndpoint extends RuntimeKookClient {
306
304
  return;
307
305
  const conversation = kookInboundConversation(String(this.#options.id), msg);
308
306
  const selfId = this.self_id != null ? String(this.self_id) : undefined;
309
- return this.#roles.resolve(msg).then((projection) => {
307
+ return this.#roles.resolve(msg).then((platform) => {
310
308
  this.#executionSignal?.throwIfAborted();
311
- return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, projection, selfId));
309
+ return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, platform, selfId));
312
310
  }).catch((err) => {
313
311
  this.#logger.warn(formatCompact({
314
312
  op: 'kook_gateway_receive_failed',
@@ -364,8 +362,25 @@ function isKookTextChannelType(type) {
364
362
  * 数据走 kook-client 的 HTTP API 封装:/api/v3/guild/list、
365
363
  * /api/v3/channel/list、/api/v3/guild/user-list(SDK 内部已做分页聚合)。
366
364
  */
367
- export function createKookEndpointManagement(requireClient) {
365
+ export function createKookEndpointManagement(requireClient, roles = new KookSenderRoleResolver(requireClient)) {
368
366
  return Object.freeze({
367
+ /**
368
+ * ADR 0056 §1: the Bot's own standing in the channel's guild (`/v3/user/view` self → its role
369
+ * ids, then the same guild owner / role-permission resolution as senders).
370
+ */
371
+ async inspectSelfStanding({ conversation, signal }) {
372
+ const guildId = conversation.kind === 'channel' ? conversation.parent?.id : undefined;
373
+ if (!guildId)
374
+ return undefined;
375
+ const operation = createEndpointOperation({ signal });
376
+ const client = requireClient();
377
+ const selfId = client.self_id != null ? String(client.self_id) : undefined;
378
+ if (!selfId)
379
+ return undefined;
380
+ const { data } = await operation.run(() => client.request.get('/v3/user/view', { params: { user_id: selfId, guild_id: guildId } }));
381
+ const held = Array.isArray(data?.roles) ? data.roles.map(Number).filter(Number.isFinite) : [];
382
+ return roles.resolve({ guildId, authorId: selfId, authorRoles: held });
383
+ },
369
384
  async listGroups(request = {}) {
370
385
  const operation = createEndpointOperation(request);
371
386
  const guilds = await operation.run(() => requireClient().getGuildList());
package/lib/index.d.ts CHANGED
@@ -4,4 +4,4 @@ export { registerKookWebhookRoutes, handleKookWebhookRequest, type KookWebhookHa
4
4
  export { kookWebsocketClientOptions, kookWebhookClientOptions, normalizeKookMessage, type KookClientTransport, } from './ws.js';
5
5
  export { type KookClientEventMap } from './client.js';
6
6
  export { KookAdapter } from './adapter.js';
7
- export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, type KookSenderInfo, } from './platform-permit.js';
7
+ export { platformPermit } from './platform-permit.js';
package/lib/index.js CHANGED
@@ -3,4 +3,4 @@ export { KookWebhookEndpoint, KookWebsocketEndpoint, } from './endpoint.js';
3
3
  export { registerKookWebhookRoutes, handleKookWebhookRequest, } from './webhook.js';
4
4
  export { kookWebsocketClientOptions, kookWebhookClientOptions, normalizeKookMessage, } from './ws.js';
5
5
  export { KookAdapter } from './adapter.js';
6
- export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, } from './platform-permit.js';
6
+ export { platformPermit } from './platform-permit.js';
@@ -1,22 +1,7 @@
1
1
  /**
2
- * KOOK platform permit — guild / channel 差异化门禁
2
+ * KOOK platform permit helper(ADR 0056 §5)。
3
+ *
4
+ * 平台身份由适配器上报到 `sender.platform`(见 `sender-roles.ts`),permit 由内置评估器
5
+ * (`@zhin.js/permission`)判断;适配器不再导出自有的 permit 解析器或检查函数。
3
6
  */
4
- import type { PermissionSubject } from '@zhin.js/permission';
5
- import { KookPermission } from './protocol.js';
6
7
  export declare function platformPermit(perm: string): string;
7
- export declare function kookGroupPermitResolver(logicalPerm: string): string;
8
- export interface KookSenderInfo {
9
- id: string;
10
- name: string;
11
- permission?: KookPermission;
12
- roles?: number[];
13
- isGuildOwner?: boolean;
14
- isAdmin?: boolean;
15
- role?: string;
16
- permissions?: string[];
17
- }
18
- export declare function normalizeKookSenderForPermit(info: KookSenderInfo, isChannel: boolean): {
19
- role?: string;
20
- permissions?: string[];
21
- };
22
- export declare function checkKookPlatformPermit(perm: string, subject: PermissionSubject): boolean;
@@ -1,48 +1,9 @@
1
- import { KookPermission } from './protocol.js';
2
- const ADAPTER = 'kook';
1
+ /**
2
+ * KOOK platform permit helper(ADR 0056 §5)。
3
+ *
4
+ * 平台身份由适配器上报到 `sender.platform`(见 `sender-roles.ts`),permit 由内置评估器
5
+ * (`@zhin.js/permission`)判断;适配器不再导出自有的 permit 解析器或检查函数。
6
+ */
3
7
  export function platformPermit(perm) {
4
- return `platform(${ADAPTER},${perm})`;
5
- }
6
- const FACTORY_PERM_MAP = {
7
- scene_admin: 'guild_admin',
8
- scene_owner: 'guild_owner',
9
- };
10
- export function kookGroupPermitResolver(logicalPerm) {
11
- return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
12
- }
13
- export function normalizeKookSenderForPermit(info, isChannel) {
14
- const permissions = [];
15
- if (info.roles?.length) {
16
- permissions.push(...info.roles.map((r) => `role:${r}`));
17
- }
18
- if (info.isGuildOwner || info.permission === KookPermission.Owner) {
19
- permissions.push('guild_owner', 'guild_admin');
20
- return { role: 'owner', permissions };
21
- }
22
- if (info.permission === KookPermission.ChannelAdmin && isChannel) {
23
- permissions.push('channel_admin', 'guild_admin');
24
- return { role: 'channel_admin', permissions };
25
- }
26
- if (info.isAdmin || info.permission === KookPermission.Admin) {
27
- permissions.push('guild_admin');
28
- return { role: 'admin', permissions };
29
- }
30
- return { role: 'member', permissions };
31
- }
32
- export function checkKookPlatformPermit(perm, subject) {
33
- const role = subject.sender?.role?.[0];
34
- const permissions = subject.sender?.permissions ?? [];
35
- const has = (t) => permissions.includes(t);
36
- switch (perm) {
37
- case 'guild_owner':
38
- return role === 'owner' || has('guild_owner');
39
- case 'guild_admin':
40
- return role === 'owner' || role === 'admin' || role === 'channel_admin' || has('guild_admin') || has('channel_admin');
41
- case 'channel_admin':
42
- return role === 'owner' || role === 'admin' || role === 'channel_admin' || has('channel_admin') || has('guild_admin');
43
- case 'manage_roles':
44
- return role === 'owner' || role === 'admin' || has('guild_owner') || has('guild_admin');
45
- default:
46
- return false;
47
- }
8
+ return `platform-permission:${perm}`;
48
9
  }
package/lib/protocol.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { EndpointProfileConfiguration } from 'zhin.js/adapter';
2
- import type { IncomingMessage } from 'node:http';
3
2
  import { type ConversationRef } from '@zhin.js/im-contract';
4
3
  import type { Locale } from 'zhin.js/i18n';
5
4
  export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'mark' | 'off';
@@ -131,10 +130,7 @@ export declare function isKookBotMentioned(msg: KookInboundMessage, selfId?: str
131
130
  */
132
131
  export declare function formatOutboundKmarkdown(payload: unknown, locale?: Locale): string;
133
132
  export declare function normalizeWebhookPath(path: string): string;
134
- export declare function readTextBody(request: IncomingMessage, options?: {
135
- readonly limit?: number;
136
- }): Promise<string>;
137
- export declare function readRequestBody(request: IncomingMessage, options?: {
133
+ export declare function readRequestBody(request: Request, options?: {
138
134
  readonly limit?: number;
139
135
  }): Promise<Buffer>;
140
136
  export declare function padKookEncryptKey(key: string): Buffer;
package/lib/protocol.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /** KOOK protocol helpers. Canonicalization is owned by Core. */
2
2
  import { createDecipheriv, timingSafeEqual } from 'node:crypto';
3
3
  import { inflateSync } from 'node:zlib';
4
+ import { readBodyBytes } from '@zhin.js/host-http';
4
5
  import { EndpointDeliveryError, isMediaRef } from '@zhin.js/im-contract';
5
6
  import { formatCompact, getLogger } from '@zhin.js/logger';
6
7
  import { outboundMessages as t } from './i18n.js';
@@ -192,35 +193,9 @@ export function normalizeWebhookPath(path) {
192
193
  const trimmed = path.trim() || '/kook/webhook';
193
194
  return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
194
195
  }
195
- export async function readTextBody(request, options = {}) {
196
- const limit = options.limit ?? 1_048_576;
197
- const chunks = [];
198
- let size = 0;
199
- for await (const chunk of request) {
200
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
201
- size += buffer.length;
202
- if (size > limit) {
203
- request.destroy();
204
- throw new Error(`Request body exceeds ${limit} bytes`);
205
- }
206
- chunks.push(buffer);
207
- }
208
- return Buffer.concat(chunks).toString('utf8');
209
- }
210
196
  export async function readRequestBody(request, options = {}) {
211
- const limit = options.limit ?? 1_048_576;
212
- const chunks = [];
213
- let size = 0;
214
- for await (const chunk of request) {
215
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
216
- size += buffer.length;
217
- if (size > limit) {
218
- request.destroy();
219
- throw new Error(`Request body exceeds ${limit} bytes`);
220
- }
221
- chunks.push(buffer);
222
- }
223
- return Buffer.concat(chunks);
197
+ // Oversize bodies throw (the webhook answers its generic OK), as before.
198
+ return Buffer.from(await readBodyBytes(request, { limit: options.limit ?? 1_048_576 }));
224
199
  }
225
200
  export function padKookEncryptKey(key) {
226
201
  const buf = Buffer.alloc(32, 0);
@@ -1,9 +1,9 @@
1
+ import type { PlatformStanding } from '@zhin.js/im-contract';
1
2
  import type { KookClientTransport } from './ws.js';
2
- export interface KookSenderRoleProjection {
3
- /** 规范角色:owner / admin;普通成员为 undefined。 */
4
- readonly role?: 'owner' | 'admin';
5
- readonly permissions: readonly string[];
6
- }
3
+ /** KOOK 角色权限位(按位序,见 KOOK 开发者文档「权限说明」)。 */
4
+ export declare const KOOK_ROLE_PERMISSIONS: readonly string[];
5
+ /** KOOK 权限位 → 权限名;未知位丢弃。 */
6
+ export declare function kookPermissionNames(bits: number): string[];
7
7
  export declare class KookSenderRoleResolver {
8
8
  #private;
9
9
  private readonly getClient;
@@ -12,5 +12,5 @@ export declare class KookSenderRoleResolver {
12
12
  readonly guildId?: string;
13
13
  readonly authorId: string;
14
14
  readonly authorRoles?: readonly number[];
15
- }): Promise<KookSenderRoleProjection>;
15
+ }): Promise<PlatformStanding | undefined>;
16
16
  }