@zhin.js/adapter-discord 1.1.17 → 1.1.19

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 (46) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +19 -2
  3. package/adapters/discord/index.js +3 -23
  4. package/adapters/discord/index.ts +2 -27
  5. package/agents/discord/skills/discord/tools/send_embed/index.js +1 -1
  6. package/agents/discord/skills/discord/tools/send_embed/index.ts +1 -1
  7. package/agents/discord/skills/discord-guild/tools/create_thread/index.js +6 -2
  8. package/agents/discord/skills/discord-guild/tools/create_thread/index.ts +5 -2
  9. package/agents/discord/skills/discord-guild/tools/forum_post/index.js +1 -1
  10. package/agents/discord/skills/discord-guild/tools/forum_post/index.ts +1 -1
  11. package/commands/discord/endpoint/definition.js +0 -2
  12. package/commands/discord/endpoint/definition.ts +0 -2
  13. package/lib/adapter.d.ts +14 -0
  14. package/lib/adapter.js +55 -0
  15. package/lib/client.d.ts +9 -9
  16. package/lib/client.js +0 -2
  17. package/lib/console-spec.d.ts +12 -0
  18. package/lib/console-spec.js +19 -0
  19. package/lib/console.d.ts +2 -0
  20. package/lib/console.js +13 -0
  21. package/lib/endpoint.d.ts +36 -32
  22. package/lib/endpoint.js +174 -170
  23. package/lib/gateway.d.ts +6 -124
  24. package/lib/gateway.js +88 -63
  25. package/lib/index.d.ts +4 -3
  26. package/lib/index.js +3 -2
  27. package/lib/protocol.d.ts +4 -0
  28. package/lib/protocol.js +1 -0
  29. package/lib/webhook.d.ts +2 -3
  30. package/lib/webhook.js +42 -30
  31. package/package.json +27 -19
  32. package/pages/index/index.js +15 -0
  33. package/pages/index/index.ts +16 -0
  34. package/plugin.js +3 -4
  35. package/src/adapter.ts +38 -0
  36. package/src/client.ts +6 -12
  37. package/src/console-spec.ts +24 -0
  38. package/src/console.ts +17 -0
  39. package/src/endpoint.ts +197 -172
  40. package/src/gateway.ts +103 -151
  41. package/src/index.ts +2 -3
  42. package/src/protocol.ts +5 -0
  43. package/src/webhook.ts +42 -32
  44. package/lib/discord-runtime-state.d.ts +0 -1
  45. package/lib/discord-runtime-state.js +0 -6
  46. package/src/discord-runtime-state.ts +0 -7
package/src/adapter.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { Adapter, type AdapterContext, type EndpointCreationContext } from 'zhin.js/adapter';
2
+ import { httpHostToken } from '@zhin.js/host-http';
3
+ import { REST, Routes } from 'discord.js';
4
+ import { DiscordGatewayEndpoint, DiscordInteractionsEndpoint } from './endpoint.js';
5
+ import { createDiscordRestApiAgent } from './rest-api-proxy.js';
6
+ import { resolveDiscordConfig, type DiscordEndpointConfig } from './protocol.js';
7
+ import type { DiscordClientEventMap } from './client.js';
8
+
9
+ export class DiscordAdapter extends Adapter<DiscordGatewayEndpoint | DiscordInteractionsEndpoint, DiscordEndpointConfig, DiscordClientEventMap> {
10
+ constructor(private readonly context: AdapterContext<DiscordEndpointConfig>) { super(); }
11
+ override get configurationIdentityFields(): readonly string[] { return ['id', 'applicationId']; }
12
+ override get configurationIdentityProbeFields(): readonly string[] { return ['token', 'publicKey']; }
13
+ override get configurationUpdateFields(): readonly string[] { return ['token', 'connection', 'restApiProxy', 'restApiProxy.port',
14
+ 'gatewayFaultProxyUrl', 'intents', 'defaultActivity', 'defaultActivity.name', 'defaultActivity.type', 'defaultActivity.url', 'publicKey', 'interactionsPath']; }
15
+ protected override validateConfiguration(input: DiscordEndpointConfig): void { resolveDiscordConfig(input); }
16
+ protected override async identifyConfiguration(input: DiscordEndpointConfig, signal: AbortSignal): Promise<string> {
17
+ const config = resolveDiscordConfig(input);
18
+ const agent = config.connection === 'gateway' && config.restApiProxy ? createDiscordRestApiAgent(config.restApiProxy) : undefined;
19
+ const rest = new REST({ version: '10', retries: 0, rejectOnRateLimit: () => true, ...(agent ? { agent } : {}) }).setToken(config.token);
20
+ try {
21
+ const application = await rest.get(Routes.currentApplication(), { signal }) as { id?: unknown; verify_key?: unknown };
22
+ if (typeof application?.id !== 'string' || !application.id.trim()) throw new Error('Discord identity response is incomplete');
23
+ if (config.connection === 'interactions' && application.id !== config.applicationId) throw new Error('Discord application identity configuration does not match');
24
+ if (config.connection === 'interactions' && (typeof application.verify_key !== 'string'
25
+ || application.verify_key.toLowerCase() !== config.publicKey.toLowerCase())) {
26
+ throw new Error('Discord verification key does not match the application identity');
27
+ }
28
+ return JSON.stringify(['discord', application.id]);
29
+ } finally { rest.clearHashSweeper(); rest.clearHandlerSweeper(); await agent?.destroyProxy(); }
30
+ }
31
+ protected async createEndpoint(input: DiscordEndpointConfig, execution: EndpointCreationContext): Promise<DiscordGatewayEndpoint | DiscordInteractionsEndpoint> {
32
+ const config = resolveDiscordConfig(input);
33
+ if (config.connection === 'interactions') return new DiscordInteractionsEndpoint({ id: execution.canonicalId, config, http: this.context.use(httpHostToken) });
34
+ const restApiAgent = config.restApiProxy ? createDiscordRestApiAgent(config.restApiProxy) : undefined;
35
+ try { return new DiscordGatewayEndpoint({ id: execution.canonicalId, config, restApiAgent }); }
36
+ catch (error) { await restApiAgent?.destroyProxy(); throw error; }
37
+ }
38
+ }
package/src/client.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { defineEndpointClient } from 'zhin.js/adapter';
2
- import type { DiscordRestClient } from './endpoint.js';
1
+ import type { ClientEvents } from 'discord.js';
2
+ import type { DiscordAdapter } from './adapter.js';
3
+ import type { DiscordGatewayEndpoint, DiscordInteractionsEndpoint } from './endpoint.js';
3
4
  import type { DiscordClientTransport } from './gateway.js';
4
5
 
5
6
  /** Exact Client variants produced by the Gateway and Interactions Endpoints. */
6
- export type DiscordClient = DiscordClientTransport | DiscordRestClient;
7
- export type DiscordClientEventMap = Record<string, unknown>;
7
+ export type DiscordClient = DiscordGatewayEndpoint | DiscordInteractionsEndpoint;
8
+ export type DiscordClientEventMap = { readonly [K in keyof ClientEvents]: ClientEvents[K][0] } & Record<string, unknown>;
8
9
 
9
10
  /** Narrow an adapter Client for Gateway-only SDK operations. */
10
11
  export function requireDiscordGatewayClient(client: DiscordClient): DiscordClientTransport {
@@ -13,12 +14,5 @@ export function requireDiscordGatewayClient(client: DiscordClient): DiscordClien
13
14
  }
14
15
 
15
16
  declare module '@zhin.js/feature-kit' {
16
- interface AdapterClientRegistry {
17
- readonly discord: {
18
- readonly client: DiscordClient;
19
- readonly events: DiscordClientEventMap;
20
- };
21
- }
17
+ interface AdapterRegistry { readonly discord: DiscordAdapter; }
22
18
  }
23
-
24
- export const discordClient = defineEndpointClient<DiscordClient, DiscordClientEventMap>('discord');
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Discord Console 页面元数据(浏览器与服务端共享;不要在这里 import 服务端代码)。
3
+ */
4
+ import type { AdapterConsoleField } from 'zhin.js/adapter';
5
+
6
+ export const discordConsoleSpec = {
7
+ adapterKey: 'discord',
8
+ adapterDisplayName: 'Discord',
9
+ fields: [
10
+ { key: 'token', required: true, env: true, description: 'Discord bot token' },
11
+ { key: 'connection', description: 'gateway or interactions' },
12
+ { key: 'applicationId', description: 'Application ID for Interactions; identity changes replace the account' },
13
+ { key: 'publicKey', description: 'Application Ed25519 public key' },
14
+ { key: 'interactionsPath', description: 'Local Interactions route' },
15
+ { key: 'restApiProxy.port', type: 'number', description: 'Configured REST loopback proxy port' },
16
+ { key: 'gatewayFaultProxyUrl', description: 'Configured local Gateway fault proxy URL' },
17
+ { key: 'defaultActivity.name', description: 'SDK activity name' },
18
+ { key: 'defaultActivity.type', description: 'PLAYING, STREAMING, LISTENING, WATCHING or COMPETING' },
19
+ { key: 'defaultActivity.url', description: 'SDK activity URL' },
20
+ ] as readonly AdapterConsoleField[],
21
+ docsUrl: 'https://zhin.js.org/adapters/discord',
22
+ readPermission: 'discord:read',
23
+ writePermission: 'discord:write',
24
+ } as const;
package/src/console.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Discord Console RPC:运行状态 + endpoint 增删(原 `discord endpoint` 聊天命令)。
3
+ *
4
+ * 页面绑定 `pages/index`,读取 / 写入分别要求 `<adapter>:read` / `<adapter>:write`。
5
+ */
6
+ import { createAdapterConsoleRpc } from 'zhin.js/adapter';
7
+ import type { PluginConsoleRpc } from 'zhin.js';
8
+ import { discordConsoleSpec } from './console-spec.js';
9
+
10
+ export function createDiscordConsoleRpc(
11
+ getConfig: () => unknown,
12
+ ): PluginConsoleRpc {
13
+ return createAdapterConsoleRpc({
14
+ ...discordConsoleSpec,
15
+ getConfig,
16
+ });
17
+ }