@zhin.js/adapter-discord 1.0.87 → 1.1.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +949 -66
  2. package/PERMITS.md +25 -0
  3. package/README.md +60 -67
  4. package/adapters/discord/index.js +41 -0
  5. package/adapters/discord/index.ts +57 -0
  6. package/agents/discord/agent.json +20 -0
  7. package/agents/discord/boundaries.md +3 -0
  8. package/agents/discord/conventions.md +3 -0
  9. package/agents/discord/skills/discord/SKILL.md +21 -0
  10. package/agents/discord/skills/discord/tools/add_role/index.js +24 -0
  11. package/agents/discord/skills/discord/tools/add_role/index.ts +26 -0
  12. package/agents/discord/skills/discord/tools/create_thread/index.js +29 -0
  13. package/agents/discord/skills/discord/tools/create_thread/index.ts +28 -0
  14. package/agents/discord/skills/discord/tools/forum_post/index.js +33 -0
  15. package/agents/discord/skills/discord/tools/forum_post/index.ts +33 -0
  16. package/agents/discord/skills/discord/tools/list_roles/index.js +28 -0
  17. package/agents/discord/skills/discord/tools/list_roles/index.ts +34 -0
  18. package/agents/discord/skills/discord/tools/react/index.js +24 -0
  19. package/agents/discord/skills/discord/tools/react/index.ts +24 -0
  20. package/agents/discord/skills/discord/tools/remove_role/index.js +24 -0
  21. package/agents/discord/skills/discord/tools/remove_role/index.ts +26 -0
  22. package/agents/discord/skills/discord/tools/send_embed/index.js +43 -0
  23. package/agents/discord/skills/discord/tools/send_embed/index.ts +38 -0
  24. package/agents/discord/system.md +3 -0
  25. package/commands/discord/endpoint/add/[id]/index.js +3 -0
  26. package/commands/discord/endpoint/add/[id]/index.ts +3 -0
  27. package/commands/discord/endpoint/definition.js +19 -0
  28. package/commands/discord/endpoint/definition.ts +19 -0
  29. package/commands/discord/endpoint/list/index.js +3 -0
  30. package/commands/discord/endpoint/list/index.ts +3 -0
  31. package/commands/discord/endpoint/remove/[id]/index.js +3 -0
  32. package/commands/discord/endpoint/remove/[id]/index.ts +3 -0
  33. package/lib/client.d.ts +16 -0
  34. package/lib/client.js +8 -0
  35. package/lib/discord-runtime-state.d.ts +1 -0
  36. package/lib/discord-runtime-state.js +6 -0
  37. package/lib/endpoint.d.ts +72 -0
  38. package/lib/endpoint.js +458 -0
  39. package/lib/gateway.d.ts +144 -0
  40. package/lib/gateway.js +303 -0
  41. package/lib/index.d.ts +6 -18
  42. package/lib/index.js +6 -323
  43. package/lib/platform-permit.d.ts +14 -0
  44. package/lib/platform-permit.js +42 -0
  45. package/lib/protocol.d.ts +145 -0
  46. package/lib/protocol.js +320 -0
  47. package/lib/side-event-dispatch.d.ts +8 -0
  48. package/lib/side-event-dispatch.js +24 -0
  49. package/lib/webhook.d.ts +14 -0
  50. package/lib/webhook.js +88 -0
  51. package/package.json +74 -30
  52. package/plugin.js +19 -0
  53. package/schema.json +205 -0
  54. package/src/client.ts +24 -0
  55. package/src/discord-runtime-state.ts +7 -0
  56. package/src/endpoint.ts +562 -0
  57. package/src/gateway.ts +426 -0
  58. package/src/index.ts +57 -323
  59. package/src/platform-permit.ts +57 -0
  60. package/src/protocol.ts +475 -0
  61. package/src/side-event-dispatch.ts +37 -0
  62. package/src/webhook.ts +123 -0
  63. package/client/Dashboard.tsx +0 -195
  64. package/client/index.tsx +0 -11
  65. package/client/tsconfig.json +0 -7
  66. package/client/utils/api.ts +0 -17
  67. package/dist/index.js +0 -29
  68. package/lib/adapter.d.ts +0 -19
  69. package/lib/adapter.d.ts.map +0 -1
  70. package/lib/adapter.js +0 -90
  71. package/lib/adapter.js.map +0 -1
  72. package/lib/bot-interactions.d.ts +0 -33
  73. package/lib/bot-interactions.d.ts.map +0 -1
  74. package/lib/bot-interactions.js +0 -278
  75. package/lib/bot-interactions.js.map +0 -1
  76. package/lib/bot.d.ts +0 -117
  77. package/lib/bot.d.ts.map +0 -1
  78. package/lib/bot.js +0 -904
  79. package/lib/bot.js.map +0 -1
  80. package/lib/index.d.ts.map +0 -1
  81. package/lib/index.js.map +0 -1
  82. package/lib/types.d.ts +0 -49
  83. package/lib/types.d.ts.map +0 -1
  84. package/lib/types.js +0 -2
  85. package/lib/types.js.map +0 -1
  86. package/plugin.yml +0 -3
  87. package/skills/discord/SKILL.md +0 -104
  88. package/src/adapter.ts +0 -107
  89. package/src/bot-interactions.ts +0 -348
  90. package/src/bot.ts +0 -1037
  91. package/src/types.ts +0 -60
@@ -0,0 +1,24 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
5
+ import { platformPermission } from '@zhin.js/permission';
6
+ export default defineAgentTool({
7
+ description: '移除成员的 Discord 角色',
8
+ inputSchema: z.object({
9
+ guild_id: z.string().describe('服务器 ID'),
10
+ user_id: z.string().describe('用户 ID'),
11
+ role_id: z.string().describe('角色 ID'),
12
+ }),
13
+ adapter: 'discord',
14
+ tags: ['discord'],
15
+ permissions: [platformPermission('discord', 'manage_roles')],
16
+ async execute({ guild_id, user_id, role_id }, context) {
17
+ const client = requireDiscordGatewayClient(context.$client);
18
+ const guild = await client.guilds.fetch(guild_id);
19
+ const member = await guild.members.fetch(user_id);
20
+ await member.roles.remove(role_id);
21
+ const success = true;
22
+ return { success, message: success ? `已移除用户 ${user_id} 的角色` : '操作失败' };
23
+ },
24
+ });
@@ -0,0 +1,26 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
4
+ import { platformPermission } from '@zhin.js/permission';
5
+
6
+ export default defineAgentTool<{ guild_id: string; user_id: string; role_id: string }>({
7
+ description: '移除成员的 Discord 角色',
8
+ inputSchema: z.object({
9
+ guild_id: z.string().describe('服务器 ID'),
10
+ user_id: z.string().describe('用户 ID'),
11
+ role_id: z.string().describe('角色 ID'),
12
+ }),
13
+ adapter: 'discord',
14
+ tags: ['discord'],
15
+ permissions: [platformPermission('discord', 'manage_roles')],
16
+ async execute({ guild_id, user_id, role_id }: { guild_id: string; user_id: string; role_id: string }, context) {
17
+ const client = requireDiscordGatewayClient(context.$client);
18
+ const guild = await client.guilds.fetch(guild_id);
19
+ const member = await guild.members.fetch(user_id) as {
20
+ roles: { remove(id: string): Promise<unknown> };
21
+ };
22
+ await member.roles.remove(role_id);
23
+ const success = true;
24
+ return { success, message: success ? `已移除用户 ${user_id} 的角色` : '操作失败' };
25
+ },
26
+ });
@@ -0,0 +1,43 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { defineAgentTool } from '@zhin.js/tool';
3
+ import { z } from 'zod';
4
+ import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
5
+ export default defineAgentTool({
6
+ description: '发送 Discord 富文本嵌入消息(Embed)',
7
+ inputSchema: z.object({
8
+ channel_id: z.string().describe('频道 ID'),
9
+ title: z.string().optional().describe('Embed 标题'),
10
+ description: z.string().optional().describe('Embed 描述'),
11
+ color: z.number().optional().describe('颜色值(十进制,如 0x00ff00 = 65280)'),
12
+ url: z.string().optional().describe('标题链接(可选)'),
13
+ fields: z.string().optional().describe('字段,JSON 格式: [{"name":"k","value":"v","inline":false}]'),
14
+ }),
15
+ adapter: 'discord',
16
+ tags: ['discord'],
17
+ async execute({ channel_id, title, description, color, url, fields }, context) {
18
+ const client = requireDiscordGatewayClient(context.$client);
19
+ const embedData = {};
20
+ if (title)
21
+ embedData.title = title;
22
+ if (description)
23
+ embedData.description = description;
24
+ if (color)
25
+ embedData.color = color;
26
+ if (url)
27
+ embedData.url = url;
28
+ if (fields) {
29
+ try {
30
+ embedData.fields = JSON.parse(fields);
31
+ }
32
+ catch {
33
+ return { success: false, message: 'fields 格式错误,应为 JSON 数组' };
34
+ }
35
+ }
36
+ const channel = await client.channels.fetch(channel_id);
37
+ if (!channel?.isTextBased() || !channel.send) {
38
+ throw new Error(`Channel ${channel_id} 不是文本频道`);
39
+ }
40
+ const msg = await channel.send({ embeds: [embedData] });
41
+ return { success: true, message_id: msg.id, message: 'Embed 已发送' };
42
+ },
43
+ });
@@ -0,0 +1,38 @@
1
+ import { defineAgentTool } from '@zhin.js/tool';
2
+ import { z } from 'zod';
3
+ import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
4
+
5
+ export default defineAgentTool<{ channel_id: string; title?: string; description?: string; color?: number; url?: string; fields?: string }>({
6
+ description: '发送 Discord 富文本嵌入消息(Embed)',
7
+ inputSchema: z.object({
8
+ channel_id: z.string().describe('频道 ID'),
9
+ title: z.string().optional().describe('Embed 标题'),
10
+ description: z.string().optional().describe('Embed 描述'),
11
+ color: z.number().optional().describe('颜色值(十进制,如 0x00ff00 = 65280)'),
12
+ url: z.string().optional().describe('标题链接(可选)'),
13
+ fields: z.string().optional().describe('字段,JSON 格式: [{"name":"k","value":"v","inline":false}]'),
14
+ }),
15
+ adapter: 'discord',
16
+ tags: ['discord'],
17
+ async execute({ channel_id, title, description, color, url, fields }: { channel_id: string; title?: string; description?: string; color?: number; url?: string; fields?: string }, context) {
18
+ const client = requireDiscordGatewayClient(context.$client);
19
+ const embedData: Record<string, unknown> = {};
20
+ if (title) embedData.title = title;
21
+ if (description) embedData.description = description;
22
+ if (color) embedData.color = color;
23
+ if (url) embedData.url = url;
24
+ if (fields) {
25
+ try {
26
+ embedData.fields = JSON.parse(fields);
27
+ } catch {
28
+ return { success: false, message: 'fields 格式错误,应为 JSON 数组' };
29
+ }
30
+ }
31
+ const channel = await client.channels.fetch(channel_id);
32
+ if (!channel?.isTextBased() || !channel.send) {
33
+ throw new Error(`Channel ${channel_id} 不是文本频道`);
34
+ }
35
+ const msg = await channel.send({ embeds: [embedData] } as never);
36
+ return { success: true, message_id: msg.id, message: 'Embed 已发送' };
37
+ },
38
+ });
@@ -0,0 +1,3 @@
1
+ # DISCORD Platform Agent
2
+
3
+ You are the discord platform specialist. Interpret requests in the current discord conversation and load only the narrowest private Skill needed for the task.
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { discordEndpointCommands } from '../../definition.js';
3
+ export default discordEndpointCommands.add;
@@ -0,0 +1,3 @@
1
+ import { discordEndpointCommands } from '../../definition.js';
2
+
3
+ export default discordEndpointCommands.add;
@@ -0,0 +1,19 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ /**
3
+ * `discord endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
4
+ * commands/discord/endpoint/ 下的 list / add / remove 直接默认导出这三项。
5
+ * 注:applicationId / publicKey 为顶层共享字段(slash commands / interactions 用),
6
+ * endpoints[i] 仅需 id + token(见 schema.json),故 add 只录入 token。
7
+ */
8
+ import { createEndpointCommands } from 'zhin.js/adapter';
9
+ import { defineCommand } from 'zhin.js/command';
10
+ import { discordRuntimeStateToken } from "../../../lib/discord-runtime-state.js";
11
+ export const discordEndpointCommands = createEndpointCommands({
12
+ adapterKey: 'discord',
13
+ adapterDisplayName: 'Discord',
14
+ fields: [
15
+ { key: 'token', required: true, env: true, description: 'Discord bot token' },
16
+ ],
17
+ running: (use) => use(discordRuntimeStateToken).endpoints.values(),
18
+ describeEntry: (entry) => `token: ${String(entry.token)}`,
19
+ }, defineCommand);
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `discord endpoint` 命令族:由 @zhin.js/adapter 的 createEndpointCommands 套件生成。
3
+ * commands/discord/endpoint/ 下的 list / add / remove 直接默认导出这三项。
4
+ * 注:applicationId / publicKey 为顶层共享字段(slash commands / interactions 用),
5
+ * endpoints[i] 仅需 id + token(见 schema.json),故 add 只录入 token。
6
+ */
7
+ import { createEndpointCommands } from 'zhin.js/adapter';
8
+ import { defineCommand } from 'zhin.js/command';
9
+ import { discordRuntimeStateToken } from '../../../src/discord-runtime-state.js';
10
+
11
+ export const discordEndpointCommands = createEndpointCommands({
12
+ adapterKey: 'discord',
13
+ adapterDisplayName: 'Discord',
14
+ fields: [
15
+ { key: 'token', required: true, env: true, description: 'Discord bot token' },
16
+ ],
17
+ running: (use) => use(discordRuntimeStateToken).endpoints.values(),
18
+ describeEntry: (entry) => `token: ${String(entry.token)}`,
19
+ }, defineCommand);
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { discordEndpointCommands } from '../definition.js';
3
+ export default discordEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ import { discordEndpointCommands } from '../definition.js';
2
+
3
+ export default discordEndpointCommands.list;
@@ -0,0 +1,3 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { discordEndpointCommands } from '../../definition.js';
3
+ export default discordEndpointCommands.remove;
@@ -0,0 +1,3 @@
1
+ import { discordEndpointCommands } from '../../definition.js';
2
+
3
+ export default discordEndpointCommands.remove;
@@ -0,0 +1,16 @@
1
+ import type { DiscordRestClient } from './endpoint.js';
2
+ import type { DiscordClientTransport } from './gateway.js';
3
+ /** Exact Client variants produced by the Gateway and Interactions Endpoints. */
4
+ export type DiscordClient = DiscordClientTransport | DiscordRestClient;
5
+ export type DiscordClientEventMap = Record<string, unknown>;
6
+ /** Narrow an adapter Client for Gateway-only SDK operations. */
7
+ export declare function requireDiscordGatewayClient(client: DiscordClient): DiscordClientTransport;
8
+ declare module '@zhin.js/feature-kit' {
9
+ interface AdapterClientRegistry {
10
+ readonly discord: {
11
+ readonly client: DiscordClient;
12
+ readonly events: DiscordClientEventMap;
13
+ };
14
+ }
15
+ }
16
+ export declare const discordClient: import("@zhin.js/adapter").EndpointClientToken<DiscordClient, DiscordClientEventMap>;
package/lib/client.js ADDED
@@ -0,0 +1,8 @@
1
+ import { defineEndpointClient } from 'zhin.js/adapter';
2
+ /** Narrow an adapter Client for Gateway-only SDK operations. */
3
+ export function requireDiscordGatewayClient(client) {
4
+ if ('guilds' in client && 'channels' in client)
5
+ return client;
6
+ throw new Error('This Discord tool requires a Gateway Endpoint Client');
7
+ }
8
+ export const discordClient = defineEndpointClient('discord');
@@ -0,0 +1 @@
1
+ export declare const discordRuntimeStateToken: import("zhin.js").Token<import("@zhin.js/adapter").EndpointRuntimeState>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Discord 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
3
+ * 由 plugin.ts setup() provide,adapter create 与 `discord endpoint` 命令共享(同一 owner generation)。
4
+ */
5
+ import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
6
+ export const discordRuntimeStateToken = defineEndpointRuntimeStateToken('discord');
@@ -0,0 +1,72 @@
1
+ import { Endpoint } from 'zhin.js/adapter';
2
+ import type { EndpointContentPort, EndpointControl, EndpointManagement, EndpointSendRequest } from 'zhin.js/adapter';
3
+ import type { HttpHost } from '@zhin.js/host-http';
4
+ import { type MessageRef } from '@zhin.js/im-contract';
5
+ import type { CapabilityId } from 'zhin.js';
6
+ import { type CreateDiscordClient, type DiscordClientTransport } from './gateway.js';
7
+ import { type DiscordButtonInbound, type DiscordInboundMessage, type ResolvedDiscordGatewayConfig, type ResolvedDiscordInteractionsConfig } from './protocol.js';
8
+ export type { CreateDiscordClient, DiscordClientTransport, } from './gateway.js';
9
+ export interface DiscordEndpointOptions {
10
+ readonly id: CapabilityId;
11
+ readonly config: ResolvedDiscordGatewayConfig;
12
+ readonly createClient?: CreateDiscordClient;
13
+ readonly fetch?: typeof globalThis.fetch;
14
+ }
15
+ export declare class DiscordGatewayEndpoint extends Endpoint<DiscordClientTransport> {
16
+ #private;
17
+ readonly management: EndpointManagement;
18
+ readonly control: EndpointControl;
19
+ readonly content: EndpointContentPort;
20
+ constructor(options: DiscordEndpointOptions);
21
+ /** The actual discord.js-compatible client used by this connection. */
22
+ get client(): DiscordClientTransport;
23
+ start(): Promise<void>;
24
+ open(): void;
25
+ close(): void;
26
+ stop(): Promise<void>;
27
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
28
+ recallMessage(message: MessageRef): Promise<void>;
29
+ /** Test / internal: admit a message when open. */
30
+ admit(msg: DiscordInboundMessage): void;
31
+ /** Test / internal: admit a button interaction when open. */
32
+ admitButton(interaction: DiscordButtonInbound): void;
33
+ }
34
+ export interface DiscordInteractionsEndpointOptions {
35
+ readonly id: CapabilityId;
36
+ readonly http: HttpHost;
37
+ readonly config: ResolvedDiscordInteractionsConfig;
38
+ readonly fetch?: typeof globalThis.fetch;
39
+ }
40
+ /** Minimal Discord REST client used when Gateway is intentionally disabled. */
41
+ export declare class DiscordRestClient {
42
+ readonly token: string;
43
+ readonly fetch: typeof globalThis.fetch;
44
+ constructor(token: string, fetch?: typeof globalThis.fetch);
45
+ request<T = unknown>(method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', path: string, body?: unknown): Promise<T>;
46
+ createMessage(channelId: string, body: unknown): Promise<{
47
+ id?: string;
48
+ }>;
49
+ deleteMessage(channelId: string, messageId: string): Promise<void>;
50
+ }
51
+ export declare class DiscordInteractionsEndpoint extends Endpoint<DiscordRestClient> {
52
+ #private;
53
+ readonly client: DiscordRestClient;
54
+ readonly control: EndpointControl;
55
+ readonly content: EndpointContentPort;
56
+ constructor(options: DiscordInteractionsEndpointOptions);
57
+ get isOpen(): boolean;
58
+ get config(): ResolvedDiscordInteractionsConfig;
59
+ start(): Promise<void>;
60
+ open(): void;
61
+ close(): void;
62
+ stop(): Promise<void>;
63
+ send({ conversation, payload }: EndpointSendRequest): Promise<string>;
64
+ recallMessage(message: MessageRef): Promise<void>;
65
+ admit(msg: DiscordInboundMessage): void;
66
+ admitPlatform(event: Record<string, unknown>): void;
67
+ }
68
+ /**
69
+ * DiscordGatewayEndpoint 的 EndpointManagement 语义端口(参照 qq 的工厂模式)。
70
+ * 数据源为 discord.js SDK 缓存:guilds.cache / guild.channels.cache / guild.members。
71
+ */
72
+ export declare function createDiscordEndpointManagement(requireClient: () => DiscordClientTransport): EndpointManagement;