@zhin.js/adapter-discord 7.0.3 → 7.0.6

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,95 @@
1
1
  # @zhin.js/adapter-discord
2
2
 
3
+ ## 7.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [2d0a622]
8
+ - @zhin.js/command@1.0.10
9
+ - @zhin.js/adapter@1.1.7
10
+ - @zhin.js/core@1.5.5
11
+ - @zhin.js/agent@1.1.6
12
+ - zhin.js@6.0.5
13
+
14
+ ## 7.0.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
19
+
20
+ All adapter platform-permit checkers now accept PermissionSubject
21
+ (duck-typed from Message/CommandSession) instead of Message directly.
22
+ registerPlatformPermitChecker is replaced by host.registerPlatform in
23
+ the adapter plugin setup. activity-feedback service updated for new
24
+ PermissionHost integration.
25
+
26
+ - Updated dependencies [6f9c366]
27
+ - Updated dependencies [373a56b]
28
+ - Updated dependencies [0de46a8]
29
+ - Updated dependencies [c106ecc]
30
+ - Updated dependencies [ca92e03]
31
+ - Updated dependencies [b0f37ae]
32
+ - Updated dependencies [ba08a2f]
33
+ - Updated dependencies [b08f7fe]
34
+ - Updated dependencies [daffd4c]
35
+ - Updated dependencies [36c7400]
36
+ - Updated dependencies [a9fa72e]
37
+ - Updated dependencies [c8de3ef]
38
+ - Updated dependencies [60f0fc8]
39
+ - Updated dependencies [574c990]
40
+ - Updated dependencies [d096f16]
41
+ - Updated dependencies [3f29623]
42
+ - Updated dependencies [2916852]
43
+ - Updated dependencies [d047869]
44
+ - Updated dependencies [162fa34]
45
+ - Updated dependencies [e62561e]
46
+ - Updated dependencies [3eeeb46]
47
+ - Updated dependencies [85d0f82]
48
+ - Updated dependencies [61bfc1c]
49
+ - Updated dependencies [04bad47]
50
+ - Updated dependencies [e40b048]
51
+ - Updated dependencies [5a5b1bb]
52
+ - Updated dependencies [f1708c3]
53
+ - Updated dependencies [d254a81]
54
+ - Updated dependencies [7123c47]
55
+ - Updated dependencies [05befc1]
56
+ - Updated dependencies [0663b6a]
57
+ - Updated dependencies [f28f9b3]
58
+ - Updated dependencies [9f340f7]
59
+ - Updated dependencies [e53444f]
60
+ - Updated dependencies [5eedd26]
61
+ - Updated dependencies [92b0dd7]
62
+ - Updated dependencies [f919b6f]
63
+ - Updated dependencies [098e411]
64
+ - Updated dependencies [e1b7c01]
65
+ - Updated dependencies [9b94f87]
66
+ - Updated dependencies [a7df753]
67
+ - @zhin.js/agent@1.1.5
68
+ - @zhin.js/host-http@1.0.8
69
+ - @zhin.js/permission@1.0.1
70
+ - @zhin.js/im-contract@1.0.3
71
+ - @zhin.js/adapter@1.1.7
72
+ - @zhin.js/plugin-runtime@1.1.5
73
+ - @zhin.js/command@1.0.9
74
+ - @zhin.js/core@1.5.4
75
+ - zhin.js@6.0.4
76
+
77
+ ## 7.0.4
78
+
79
+ ### Patch Changes
80
+
81
+ - f8c7a54: fix: im
82
+ - Updated dependencies [f8c7a54]
83
+ - @zhin.js/logger@1.0.76
84
+ - @zhin.js/host-http@1.0.7
85
+ - @zhin.js/adapter@1.1.6
86
+ - @zhin.js/agent@1.1.4
87
+ - @zhin.js/command@1.0.8
88
+ - @zhin.js/core@1.5.3
89
+ - @zhin.js/im-contract@1.0.2
90
+ - @zhin.js/plugin-runtime@1.1.4
91
+ - zhin.js@6.0.3
92
+
3
93
  ## 7.0.3
4
94
 
5
95
  ### Patch Changes
@@ -21,8 +21,8 @@ export default defineAdapter({
21
21
  const config = resolveDiscordConfig(context.config);
22
22
  const gateway = context.use(messageGatewayToken);
23
23
  // 注册到插件运行时状态(discord.endpoint list 的"运行中"数据源)
24
- context.use(discordRuntimeStateToken).endpoints.set(config.name, {
25
- name: config.name,
24
+ context.use(discordRuntimeStateToken).endpoints.set(config.id, {
25
+ id: config.id,
26
26
  mode: config.connection,
27
27
  });
28
28
  if (config.connection === 'interactions') {
@@ -37,8 +37,8 @@ export default defineAdapter<DiscordAdapterConfig>({
37
37
  const config = resolveDiscordConfig(context.config);
38
38
  const gateway = context.use(messageGatewayToken);
39
39
  // 注册到插件运行时状态(discord.endpoint list 的"运行中"数据源)
40
- context.use(discordRuntimeStateToken).endpoints.set(config.name, {
41
- name: config.name,
40
+ context.use(discordRuntimeStateToken).endpoints.set(config.id, {
41
+ id: config.id,
42
42
  mode: config.connection,
43
43
  });
44
44
  if (config.connection === 'interactions') {
@@ -25,11 +25,11 @@ export interface DiscordAgentEndpoint {
25
25
  getGuildInfo(guildId: string): Promise<unknown>;
26
26
  }
27
27
  export interface DiscordAgentDeps {
28
- getEndpoint: (endpointId: string) => DiscordAgentEndpoint;
28
+ getEndpoint: (endpointKey: string) => DiscordAgentEndpoint;
29
29
  /** Alias kept for existing agent/tools that call getGatewayEndpoint. */
30
- getGatewayEndpoint: (endpointId: string) => DiscordAgentEndpoint;
30
+ getGatewayEndpoint: (endpointKey: string) => DiscordAgentEndpoint;
31
31
  }
32
- export declare function registerDiscordAgentEndpoint(endpointId: string, endpoint: DiscordAgentEndpoint): () => void;
32
+ export declare function registerDiscordAgentEndpoint(endpointKey: string, endpoint: DiscordAgentEndpoint): () => void;
33
33
  /** Optional override used by tests / transitional callers. Pass `null` to clear. */
34
34
  export declare function setDiscordAgentDeps(deps: DiscordAgentDeps | null): void;
35
35
  export declare function getDiscordAgentDeps(): DiscordAgentDeps;
@@ -4,11 +4,11 @@
4
4
  */
5
5
  const endpoints = new Map();
6
6
  let override = null;
7
- export function registerDiscordAgentEndpoint(endpointId, endpoint) {
8
- endpoints.set(endpointId, endpoint);
7
+ export function registerDiscordAgentEndpoint(endpointKey, endpoint) {
8
+ endpoints.set(endpointKey, endpoint);
9
9
  return () => {
10
- if (endpoints.get(endpointId) === endpoint) {
11
- endpoints.delete(endpointId);
10
+ if (endpoints.get(endpointKey) === endpoint) {
11
+ endpoints.delete(endpointKey);
12
12
  }
13
13
  };
14
14
  }
@@ -16,10 +16,10 @@ export function registerDiscordAgentEndpoint(endpointId, endpoint) {
16
16
  export function setDiscordAgentDeps(deps) {
17
17
  override = deps;
18
18
  }
19
- function lookup(endpointId) {
20
- const registered = endpoints.get(endpointId);
19
+ function lookup(endpointKey) {
20
+ const registered = endpoints.get(endpointKey);
21
21
  if (!registered)
22
- throw new Error(`Endpoint ${endpointId} 不存在`);
22
+ throw new Error(`Endpoint ${endpointKey} 不存在`);
23
23
  return registered;
24
24
  }
25
25
  export function getDiscordAgentDeps() {
package/lib/endpoint.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * DiscordEndpoint — lifecycle, outbound, admit, gateway / interactions modes, agent tool surface.
3
3
  */
4
4
  import { ChannelType } from 'discord.js';
5
- import { formatLegacyConversationRef, formatLegacyMessageReference, nativeConversationId, parseLegacyMessageReference, } from '@zhin.js/im-contract';
6
- import { formatCompact, getLogger } from '@zhin.js/logger';
5
+ import { formatLegacyConversationRef, formatLegacyMessageRef, nativeConversationId, parseLegacyMessageReference, } from '@zhin.js/im-contract';
6
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
7
7
  import { registerDiscordAgentEndpoint } from './discord-agent-deps.js';
8
8
  import { connectDiscordGatewayClient, defaultCreateClient, DEFAULT_INTENTS, resolveSenderRole, toMessageCreateOptions, } from './gateway.js';
9
9
  import { discordInboundConversation, formatButtonContent, formatButtonSegments, formatInboundContent, formatInboundSegments, formatOutboundBody, senderDisplayName, } from './protocol.js';
@@ -11,8 +11,8 @@ import { registerDiscordInteractionRoutes } from './webhook.js';
11
11
  const DISCORD_API = 'https://discord.com/api/v10';
12
12
  /** 出站 HTTP 调用统一 30s 超时。 */
13
13
  const OUTBOUND_TIMEOUT_MS = 30_000;
14
- const logger = getLogger('discord');
15
14
  export class DiscordGatewayEndpoint {
15
+ #logger;
16
16
  #options;
17
17
  #createClient;
18
18
  #client = null;
@@ -37,6 +37,7 @@ export class DiscordGatewayEndpoint {
37
37
  },
38
38
  });
39
39
  constructor(options) {
40
+ this.#logger = getAdapterLogger('discord', options.config.id);
40
41
  this.#options = options;
41
42
  this.#createClient = options.createClient ?? defaultCreateClient;
42
43
  }
@@ -45,7 +46,7 @@ export class DiscordGatewayEndpoint {
45
46
  return;
46
47
  this.#started = true;
47
48
  try {
48
- this.#unregisterAgent = registerDiscordAgentEndpoint(this.#options.config.name, this);
49
+ this.#unregisterAgent = registerDiscordAgentEndpoint(this.#options.config.id, this);
49
50
  const intents = this.#options.config.intents?.length
50
51
  ? [...this.#options.config.intents]
51
52
  : DEFAULT_INTENTS;
@@ -54,16 +55,16 @@ export class DiscordGatewayEndpoint {
54
55
  onMessage: (msg) => this.admit(msg),
55
56
  onButton: (interaction) => this.admitButton(interaction),
56
57
  });
57
- logger.info(formatCompact({
58
+ this.#logger.info(formatCompact({
58
59
  op: 'connect',
59
- endpoint: this.#options.config.name,
60
+ endpoint: this.#options.config.id,
60
61
  mode: 'gateway',
61
62
  user: this.#client.user?.tag,
62
63
  }));
63
64
  }
64
65
  catch (error) {
65
66
  await this.stop();
66
- logger.error('Failed to connect Discord gateway:', error);
67
+ this.#logger.error('Failed to connect Discord gateway:', error);
67
68
  throw error;
68
69
  }
69
70
  }
@@ -88,18 +89,17 @@ export class DiscordGatewayEndpoint {
88
89
  this.#client = null;
89
90
  }
90
91
  this.#started = false;
91
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
92
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
92
93
  }
93
94
  async send({ conversation, payload }) {
94
95
  const body = formatOutboundBody(payload);
95
- // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生 target
96
- const target = formatLegacyConversationRef(conversation);
96
+ // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生
97
97
  const snowflake = await this.#sendBody(conversation.id, body);
98
- const messageId = formatLegacyMessageReference({ target, messageId: snowflake });
99
- logger.debug(formatCompact({
98
+ const messageId = formatLegacyMessageRef({ conversation, id: snowflake });
99
+ this.#logger.debug(formatCompact({
100
100
  op: 'discord_send',
101
- endpoint: this.#options.config.name,
102
- target,
101
+ endpoint: this.#options.config.id,
102
+ target: formatLegacyConversationRef(conversation),
103
103
  messageId,
104
104
  }));
105
105
  return messageId;
@@ -130,18 +130,22 @@ export class DiscordGatewayEndpoint {
130
130
  message: { conversation, id: msg.id },
131
131
  content: formatInboundContent(msg),
132
132
  segments: formatInboundSegments(msg),
133
- sender: senderDisplayName(msg),
133
+ sender: {
134
+ id: msg.authorId,
135
+ name: senderDisplayName(msg) || undefined,
136
+ ...(resolveSenderRole(msg) ? { roles: [resolveSenderRole(msg)] } : {}),
137
+ },
138
+ endpointId: this.#options.config.id,
139
+ ...(msg.mentionedBot ? { mentioned: true } : {}),
134
140
  metadata: Object.freeze({
135
- endpoint: this.#options.config.name,
136
141
  channelKind: msg.channelKind,
137
142
  userId: msg.authorId,
138
143
  guildId: msg.guildId,
139
144
  permissions: msg.permissionTokens,
140
145
  role: resolveSenderRole(msg),
141
- ...(msg.mentionedBot ? { mentioned: true } : {}),
142
146
  }),
143
147
  }).catch((err) => {
144
- logger.warn(formatCompact({
148
+ this.#logger.warn(formatCompact({
145
149
  op: 'discord_gateway_receive_failed',
146
150
  target: `${conversation.kind}:${conversation.id}`,
147
151
  error: err instanceof Error ? err.message : String(err),
@@ -158,15 +162,15 @@ export class DiscordGatewayEndpoint {
158
162
  message: { conversation, id: interaction.id },
159
163
  content: formatButtonContent(interaction),
160
164
  segments: formatButtonSegments(interaction),
161
- sender: interaction.userName,
165
+ sender: { id: interaction.userId, name: interaction.userName },
166
+ endpointId: this.#options.config.id,
162
167
  metadata: Object.freeze({
163
- endpoint: this.#options.config.name,
164
168
  eventType: 'button',
165
169
  payload: interaction.customId,
166
170
  sourceMessageId: interaction.sourceMessageId,
167
171
  }),
168
172
  }).catch((err) => {
169
- logger.warn(formatCompact({
173
+ this.#logger.warn(formatCompact({
170
174
  op: 'discord_gateway_receive_failed',
171
175
  target: `${conversation.kind}:${conversation.id}`,
172
176
  error: err instanceof Error ? err.message : String(err),
@@ -307,6 +311,7 @@ export class DiscordGatewayEndpoint {
307
311
  }
308
312
  }
309
313
  export class DiscordInteractionsEndpoint {
314
+ #logger;
310
315
  #options;
311
316
  #fetch;
312
317
  #routeReleases = [];
@@ -316,6 +321,7 @@ export class DiscordInteractionsEndpoint {
316
321
  recall: (messageId) => this.recallMessage(messageId),
317
322
  });
318
323
  constructor(options) {
324
+ this.#logger = getAdapterLogger('discord', options.config.id);
319
325
  this.#options = options;
320
326
  this.#fetch = options.fetch ?? globalThis.fetch;
321
327
  }
@@ -330,9 +336,9 @@ export class DiscordInteractionsEndpoint {
330
336
  return;
331
337
  this.#started = true;
332
338
  this.#routeReleases.push(...registerDiscordInteractionRoutes(this.#options.http, this));
333
- logger.info(formatCompact({
339
+ this.#logger.info(formatCompact({
334
340
  op: 'connect',
335
- endpoint: this.#options.config.name,
341
+ endpoint: this.#options.config.id,
336
342
  mode: 'interactions',
337
343
  path: this.#options.config.interactionsPath,
338
344
  }));
@@ -348,7 +354,7 @@ export class DiscordInteractionsEndpoint {
348
354
  for (const release of this.#routeReleases.splice(0))
349
355
  release();
350
356
  this.#started = false;
351
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
357
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
352
358
  }
353
359
  async send({ conversation, payload }) {
354
360
  const body = formatOutboundBody(payload);
@@ -368,13 +374,8 @@ export class DiscordInteractionsEndpoint {
368
374
  }
369
375
  const data = JSON.parse(text);
370
376
  const snowflake = data.id ?? '';
371
- // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生 target
372
- return snowflake
373
- ? formatLegacyMessageReference({
374
- target: formatLegacyConversationRef(conversation),
375
- messageId: snowflake,
376
- })
377
- : '';
377
+ // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生
378
+ return snowflake ? formatLegacyMessageRef({ conversation, id: snowflake }) : '';
378
379
  }
379
380
  async recallMessage(messageId) {
380
381
  if (!messageId)
@@ -403,16 +404,20 @@ export class DiscordInteractionsEndpoint {
403
404
  message: { conversation, id: msg.id },
404
405
  content: formatInboundContent(msg),
405
406
  segments: formatInboundSegments(msg),
406
- sender: senderDisplayName(msg),
407
+ sender: {
408
+ id: msg.authorId,
409
+ name: senderDisplayName(msg) || undefined,
410
+ ...(resolveSenderRole(msg) ? { roles: [resolveSenderRole(msg)] } : {}),
411
+ },
412
+ endpointId: this.#options.config.id,
407
413
  metadata: Object.freeze({
408
- endpoint: this.#options.config.name,
409
414
  channelKind: msg.channelKind,
410
415
  userId: msg.authorId,
411
416
  guildId: msg.guildId,
412
417
  eventType: 'application_command',
413
418
  }),
414
419
  }).catch((err) => {
415
- logger.warn(formatCompact({
420
+ this.#logger.warn(formatCompact({
416
421
  op: 'discord_gateway_receive_failed',
417
422
  target: `${conversation.kind}:${conversation.id}`,
418
423
  error: err instanceof Error ? err.message : String(err),
package/lib/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { activityTypeCode, formatButtonContent, formatInboundContent, formatOutboundBody, resolveChannelKind, resolveDiscordConfig, senderDisplayName, type DiscordAdapterConfig, type DiscordButtonInbound, type DiscordInboundAttachment, type DiscordInboundMessage, type DiscordOutboundBody, type DiscordWireSegment, type ResolvedDiscordConfig, type ResolvedDiscordGatewayConfig, type ResolvedDiscordInteractionsConfig, } from './protocol.js';
2
2
  export { getDiscordAgentDeps, registerDiscordAgentEndpoint, setDiscordAgentDeps, type DiscordAgentDeps, type DiscordAgentEndpoint, } from './discord-agent-deps.js';
3
- export { checkDiscordPlatformPermit, discordGroupPermitResolver, normalizeDiscordSenderForPermit, platformPermit, registerDiscordPlatformPermitChecker, } from './platform-permit.js';
3
+ export { checkDiscordPlatformPermit, discordGroupPermitResolver, normalizeDiscordSenderForPermit, platformPermit, } from './platform-permit.js';
4
4
  export { DiscordGatewayEndpoint, DiscordInteractionsEndpoint, type CreateDiscordClient, type DiscordClientTransport, type DiscordEndpointOptions, type DiscordInteractionsEndpointOptions, } from './endpoint.js';
5
5
  export { connectDiscordGatewayClient, defaultCreateClient, normalizeDiscordMessage, resolveSenderRole, toMessageCreateOptions, type DiscordGatewayConnectHandlers, } from './gateway.js';
6
6
  export { handleDiscordInteractionRequest, registerDiscordInteractionRoutes, type DiscordInteractionsHandler, } from './webhook.js';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { activityTypeCode, formatButtonContent, formatInboundContent, formatOutboundBody, resolveChannelKind, resolveDiscordConfig, senderDisplayName, } from './protocol.js';
2
2
  export { getDiscordAgentDeps, registerDiscordAgentEndpoint, setDiscordAgentDeps, } from './discord-agent-deps.js';
3
- export { checkDiscordPlatformPermit, discordGroupPermitResolver, normalizeDiscordSenderForPermit, platformPermit, registerDiscordPlatformPermitChecker, } from './platform-permit.js';
3
+ export { checkDiscordPlatformPermit, discordGroupPermitResolver, normalizeDiscordSenderForPermit, platformPermit, } from './platform-permit.js';
4
4
  export { DiscordGatewayEndpoint, DiscordInteractionsEndpoint, } from './endpoint.js';
5
5
  export { connectDiscordGatewayClient, defaultCreateClient, normalizeDiscordMessage, resolveSenderRole, toMessageCreateOptions, } from './gateway.js';
6
6
  export { handleDiscordInteractionRequest, registerDiscordInteractionRoutes, } from './webhook.js';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Discord platform permit — Guild 权限位
3
3
  */
4
- import { type Message } from '@zhin.js/core';
4
+ import type { PermissionSubject } from '@zhin.js/permission';
5
5
  export declare function platformPermit(perm: string): string;
6
6
  export declare function discordGroupPermitResolver(logicalPerm: string): string;
7
7
  export declare function normalizeDiscordSenderForPermit(input: {
@@ -11,5 +11,4 @@ export declare function normalizeDiscordSenderForPermit(input: {
11
11
  role?: string;
12
12
  permissions?: string[];
13
13
  };
14
- export declare function checkDiscordPlatformPermit(perm: string, message: Message<any>): boolean;
15
- export declare function registerDiscordPlatformPermitChecker(): () => void;
14
+ export declare function checkDiscordPlatformPermit(perm: string, subject: PermissionSubject): boolean;
@@ -1,7 +1,3 @@
1
- /**
2
- * Discord platform permit — Guild 权限位
3
- */
4
- import { registerPlatformPermitChecker } from '@zhin.js/core';
5
1
  const ADAPTER = 'discord';
6
2
  export function platformPermit(perm) {
7
3
  return `platform(${ADAPTER},${perm})`;
@@ -27,12 +23,9 @@ export function normalizeDiscordSenderForPermit(input) {
27
23
  }
28
24
  return { role: 'member', permissions };
29
25
  }
30
- function senderPermits(message) {
31
- const sender = message.$sender;
32
- return { role: sender.role, permissions: sender.permissions ?? [] };
33
- }
34
- export function checkDiscordPlatformPermit(perm, message) {
35
- const { role, permissions } = senderPermits(message);
26
+ export function checkDiscordPlatformPermit(perm, subject) {
27
+ const role = subject.sender?.role?.[0];
28
+ const permissions = subject.sender?.permissions ?? [];
36
29
  const has = (t) => permissions.includes(t);
37
30
  switch (perm) {
38
31
  case 'guild_owner':
@@ -47,6 +40,3 @@ export function checkDiscordPlatformPermit(perm, message) {
47
40
  return false;
48
41
  }
49
42
  }
50
- export function registerDiscordPlatformPermitChecker() {
51
- return registerPlatformPermitChecker(ADAPTER, checkDiscordPlatformPermit);
52
- }
package/lib/protocol.d.ts CHANGED
@@ -6,7 +6,7 @@ import type { Segment } from '@zhin.js/core/runtime';
6
6
  import type { ConversationRef } from '@zhin.js/im-contract';
7
7
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
8
8
  export interface DiscordAdapterConfig {
9
- readonly name?: string;
9
+ readonly id?: string;
10
10
  readonly token?: string;
11
11
  /** Default `gateway`. `interactions` uses httpHostToken POST + Ed25519 verify. */
12
12
  readonly connection?: 'gateway' | 'interactions';
@@ -26,7 +26,7 @@ export interface DiscordAdapterConfig {
26
26
  /** Transitional: legacy root `endpoints[]` with `context: discord`. */
27
27
  readonly endpoints?: ReadonlyArray<{
28
28
  readonly context?: string;
29
- readonly name?: string;
29
+ readonly id?: string;
30
30
  readonly token?: string;
31
31
  readonly connection?: 'gateway' | 'interactions';
32
32
  readonly intents?: readonly number[];
@@ -42,7 +42,7 @@ export interface DiscordAdapterConfig {
42
42
  export interface ResolvedDiscordGatewayConfig {
43
43
  readonly context: 'discord';
44
44
  readonly connection: 'gateway';
45
- readonly name: string;
45
+ readonly id: string;
46
46
  readonly token: string;
47
47
  readonly intents?: readonly number[];
48
48
  readonly enableSlashCommands: boolean;
@@ -53,7 +53,7 @@ export interface ResolvedDiscordGatewayConfig {
53
53
  export interface ResolvedDiscordInteractionsConfig {
54
54
  readonly context: 'discord';
55
55
  readonly connection: 'interactions';
56
- readonly name: string;
56
+ readonly id: string;
57
57
  readonly token: string;
58
58
  readonly applicationId: string;
59
59
  readonly publicKey: string;
@@ -128,7 +128,7 @@ export declare function resolveChannelKind(channelType: number | string | undefi
128
128
  * guild 频道 → 'channel' + guild 容器进 parent(guild 是频道容器,kind 'channel')。
129
129
  * endpoint.adapter = owner PluginId(CapabilityId 以 \0 分隔)。
130
130
  */
131
- export declare function discordInboundConversation(endpointId: string, msg: {
131
+ export declare function discordInboundConversation(endpointKey: string, msg: {
132
132
  readonly channelId: string;
133
133
  readonly channelKind: 'private' | 'group' | 'channel';
134
134
  readonly guildId?: string;
package/lib/protocol.js CHANGED
@@ -15,8 +15,8 @@ export function resolveDiscordConfig(config = {}) {
15
15
  if (!token) {
16
16
  throw new TypeError('Discord adapter requires token (plugins.<key>.token or endpoints with context: discord)');
17
17
  }
18
- const name = (typeof config.name === 'string' && config.name)
19
- || (typeof entry?.name === 'string' && entry.name)
18
+ const id = (typeof config.id === 'string' && config.id)
19
+ || (typeof entry?.id === 'string' && entry.id)
20
20
  || process.env.DISCORD_BOT_NAME
21
21
  || 'discord-bot';
22
22
  const connection = config.connection
@@ -31,7 +31,7 @@ export function resolveDiscordConfig(config = {}) {
31
31
  return {
32
32
  context: 'discord',
33
33
  connection: 'interactions',
34
- name,
34
+ id,
35
35
  token,
36
36
  applicationId,
37
37
  publicKey,
@@ -41,7 +41,7 @@ export function resolveDiscordConfig(config = {}) {
41
41
  return {
42
42
  context: 'discord',
43
43
  connection: 'gateway',
44
- name,
44
+ id,
45
45
  token,
46
46
  intents: config.intents ?? entry?.intents,
47
47
  enableSlashCommands: config.enableSlashCommands === true
@@ -64,9 +64,9 @@ export function resolveChannelKind(channelType) {
64
64
  * guild 频道 → 'channel' + guild 容器进 parent(guild 是频道容器,kind 'channel')。
65
65
  * endpoint.adapter = owner PluginId(CapabilityId 以 \0 分隔)。
66
66
  */
67
- export function discordInboundConversation(endpointId, msg) {
67
+ export function discordInboundConversation(endpointKey, msg) {
68
68
  return {
69
- endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
69
+ endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
70
70
  kind: msg.channelKind,
71
71
  id: msg.channelId,
72
72
  ...(msg.guildId && msg.channelKind === 'channel'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-discord",
3
- "version": "7.0.3",
3
+ "version": "7.0.6",
4
4
  "description": "Zhin.js Discord adapter for Plugin Runtime (Gateway WebSocket)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -33,21 +33,22 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "discord.js": "^14.27.0",
36
- "@zhin.js/adapter": "1.1.5",
37
- "@zhin.js/command": "1.0.7",
38
- "@zhin.js/core": "1.5.2",
39
- "@zhin.js/host-http": "1.0.6",
40
- "@zhin.js/im-contract": "1.0.1",
41
- "@zhin.js/logger": "1.0.75",
42
- "@zhin.js/plugin-runtime": "1.1.3"
36
+ "@zhin.js/adapter": "1.1.7",
37
+ "@zhin.js/command": "1.0.10",
38
+ "@zhin.js/core": "1.5.5",
39
+ "@zhin.js/host-http": "1.0.8",
40
+ "@zhin.js/im-contract": "1.0.3",
41
+ "@zhin.js/logger": "1.0.76",
42
+ "@zhin.js/permission": "1.0.1",
43
+ "@zhin.js/plugin-runtime": "1.1.5"
43
44
  },
44
45
  "peerDependencies": {
45
46
  "zod": "^4.0.0",
46
- "@zhin.js/adapter": "1.1.5",
47
- "@zhin.js/agent": "1.1.3",
48
- "@zhin.js/core": "1.5.2",
49
- "@zhin.js/plugin-runtime": "1.1.3",
50
- "zhin.js": "6.0.2"
47
+ "@zhin.js/adapter": "1.1.7",
48
+ "@zhin.js/agent": "1.1.6",
49
+ "@zhin.js/core": "1.5.5",
50
+ "@zhin.js/plugin-runtime": "1.1.5",
51
+ "zhin.js": "6.0.5"
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.3",
69
- "@zhin.js/host-http": "1.0.6",
70
- "zhin.js": "6.0.2"
69
+ "@zhin.js/agent": "1.1.6",
70
+ "@zhin.js/host-http": "1.0.8",
71
+ "zhin.js": "6.0.5"
71
72
  },
72
73
  "files": [
73
74
  "adapters",
package/plugin.js CHANGED
@@ -1,7 +1,8 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { createEndpointRuntimeState } from '@zhin.js/adapter';
3
3
  import { definePlugin } from '@zhin.js/plugin-runtime';
4
- import { registerDiscordPlatformPermitChecker } from "./lib/platform-permit.js";
4
+ import { permissionHostToken } from '@zhin.js/permission';
5
+ import { checkDiscordPlatformPermit } from "./lib/platform-permit.js";
5
6
  import { discordRuntimeStateToken } from "./lib/discord-runtime-state.js";
6
7
  export default definePlugin({
7
8
  name: 'discord',
@@ -9,9 +10,10 @@ export default definePlugin({
9
10
  displayName: 'Discord Gateway Adapter',
10
11
  },
11
12
  setup(context) {
12
- // 运行中 endpoint 注册表(discord.endpoint list 的"运行中"数据源)
13
13
  context.resources.provide(discordRuntimeStateToken, createEndpointRuntimeState());
14
- // 平台权限门禁:guild_owner / moderate_members 等(agent 工具 platformPermit)
15
- return registerDiscordPlatformPermitChecker();
14
+ if (context.resources.has(permissionHostToken)) {
15
+ const host = context.resources.use(permissionHostToken);
16
+ return host.registerPlatform('discord', checkDiscordPlatformPermit);
17
+ }
16
18
  },
17
19
  });
package/schema.json CHANGED
@@ -71,24 +71,60 @@
71
71
  "default": "/discord/interactions",
72
72
  "description": "POST path on httpHostToken when connection is interactions."
73
73
  },
74
+ "master": {
75
+ "type": [
76
+ "string",
77
+ "number"
78
+ ],
79
+ "description": "框架 master(Discord user snowflake;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
80
+ },
81
+ "trusted": {
82
+ "type": "array",
83
+ "items": {
84
+ "type": [
85
+ "string",
86
+ "number"
87
+ ],
88
+ "description": "Trusted Discord user snowflake"
89
+ },
90
+ "description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
91
+ },
74
92
  "endpoints": {
75
93
  "type": "array",
76
- "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(name 必填,其余覆盖顶层)",
94
+ "description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
77
95
  "items": {
78
96
  "type": "object",
79
97
  "additionalProperties": true,
80
98
  "properties": {
81
- "name": {
82
- "type": "string",
83
- "description": "Discord bot name"
99
+ "master": {
100
+ "type": [
101
+ "string",
102
+ "number"
103
+ ],
104
+ "description": "本 endpoint 的框架 master(Discord user snowflake);覆盖顶层 master"
105
+ },
106
+ "trusted": {
107
+ "type": "array",
108
+ "items": {
109
+ "type": [
110
+ "string",
111
+ "number"
112
+ ],
113
+ "description": "Trusted Discord user snowflake"
114
+ },
115
+ "description": "本 endpoint 的 trusted 列表"
84
116
  },
85
117
  "token": {
86
118
  "type": "string",
87
119
  "description": "Discord bot token"
120
+ },
121
+ "id": {
122
+ "type": "string",
123
+ "description": "Discord bot name"
88
124
  }
89
125
  },
90
126
  "required": [
91
- "name",
127
+ "id",
92
128
  "token"
93
129
  ]
94
130
  }
@@ -39,22 +39,22 @@ export interface DiscordAgentEndpoint {
39
39
  }
40
40
 
41
41
  export interface DiscordAgentDeps {
42
- getEndpoint: (endpointId: string) => DiscordAgentEndpoint;
42
+ getEndpoint: (endpointKey: string) => DiscordAgentEndpoint;
43
43
  /** Alias kept for existing agent/tools that call getGatewayEndpoint. */
44
- getGatewayEndpoint: (endpointId: string) => DiscordAgentEndpoint;
44
+ getGatewayEndpoint: (endpointKey: string) => DiscordAgentEndpoint;
45
45
  }
46
46
 
47
47
  const endpoints = new Map<string, DiscordAgentEndpoint>();
48
48
  let override: DiscordAgentDeps | null = null;
49
49
 
50
50
  export function registerDiscordAgentEndpoint(
51
- endpointId: string,
51
+ endpointKey: string,
52
52
  endpoint: DiscordAgentEndpoint,
53
53
  ): () => void {
54
- endpoints.set(endpointId, endpoint);
54
+ endpoints.set(endpointKey, endpoint);
55
55
  return () => {
56
- if (endpoints.get(endpointId) === endpoint) {
57
- endpoints.delete(endpointId);
56
+ if (endpoints.get(endpointKey) === endpoint) {
57
+ endpoints.delete(endpointKey);
58
58
  }
59
59
  };
60
60
  }
@@ -64,9 +64,9 @@ export function setDiscordAgentDeps(deps: DiscordAgentDeps | null): void {
64
64
  override = deps;
65
65
  }
66
66
 
67
- function lookup(endpointId: string): DiscordAgentEndpoint {
68
- const registered = endpoints.get(endpointId);
69
- if (!registered) throw new Error(`Endpoint ${endpointId} 不存在`);
67
+ function lookup(endpointKey: string): DiscordAgentEndpoint {
68
+ const registered = endpoints.get(endpointKey);
69
+ if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
70
70
  return registered;
71
71
  }
72
72
 
package/src/endpoint.ts CHANGED
@@ -14,11 +14,11 @@ import type { MessageGateway } from '@zhin.js/core/runtime';
14
14
  import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
15
15
  import {
16
16
  formatLegacyConversationRef,
17
- formatLegacyMessageReference,
17
+ formatLegacyMessageRef,
18
18
  nativeConversationId,
19
19
  parseLegacyMessageReference,
20
20
  } from '@zhin.js/im-contract';
21
- import { formatCompact, getLogger } from '@zhin.js/logger';
21
+ import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
22
22
  import type { CapabilityId } from '@zhin.js/plugin-runtime';
23
23
  import { registerDiscordAgentEndpoint } from './discord-agent-deps.js';
24
24
  import {
@@ -49,8 +49,6 @@ import { registerDiscordInteractionRoutes } from './webhook.js';
49
49
  const DISCORD_API = 'https://discord.com/api/v10';
50
50
  /** 出站 HTTP 调用统一 30s 超时。 */
51
51
  const OUTBOUND_TIMEOUT_MS = 30_000;
52
- const logger = getLogger('discord');
53
-
54
52
  export type {
55
53
  CreateDiscordClient,
56
54
  DiscordClientTransport,
@@ -64,6 +62,8 @@ export interface DiscordEndpointOptions {
64
62
  }
65
63
 
66
64
  export class DiscordGatewayEndpoint implements EndpointInstance {
65
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
66
+
67
67
  readonly #options: DiscordEndpointOptions;
68
68
  readonly #createClient: CreateDiscordClient;
69
69
  #client: DiscordClientTransport | null = null;
@@ -92,6 +92,7 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
92
92
  });
93
93
 
94
94
  constructor(options: DiscordEndpointOptions) {
95
+ this.#logger = getAdapterLogger('discord', options.config.id);
95
96
  this.#options = options;
96
97
  this.#createClient = options.createClient ?? defaultCreateClient;
97
98
  }
@@ -100,7 +101,7 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
100
101
  if (this.#started) return;
101
102
  this.#started = true;
102
103
  try {
103
- this.#unregisterAgent = registerDiscordAgentEndpoint(this.#options.config.name, this);
104
+ this.#unregisterAgent = registerDiscordAgentEndpoint(this.#options.config.id, this);
104
105
  const intents = this.#options.config.intents?.length
105
106
  ? [...this.#options.config.intents]
106
107
  : DEFAULT_INTENTS;
@@ -109,15 +110,15 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
109
110
  onMessage: (msg) => this.admit(msg),
110
111
  onButton: (interaction) => this.admitButton(interaction),
111
112
  });
112
- logger.info(formatCompact({
113
+ this.#logger.info(formatCompact({
113
114
  op: 'connect',
114
- endpoint: this.#options.config.name,
115
+ endpoint: this.#options.config.id,
115
116
  mode: 'gateway',
116
117
  user: this.#client.user?.tag,
117
118
  }));
118
119
  } catch (error) {
119
120
  await this.stop();
120
- logger.error('Failed to connect Discord gateway:', error);
121
+ this.#logger.error('Failed to connect Discord gateway:', error);
121
122
  throw error;
122
123
  }
123
124
  }
@@ -144,19 +145,18 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
144
145
  this.#client = null;
145
146
  }
146
147
  this.#started = false;
147
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
148
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
148
149
  }
149
150
 
150
151
  async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
151
152
  const body = formatOutboundBody(payload);
152
- // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生 target
153
- const target = formatLegacyConversationRef(conversation);
153
+ // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生
154
154
  const snowflake = await this.#sendBody(conversation.id, body);
155
- const messageId = formatLegacyMessageReference({ target, messageId: snowflake });
156
- logger.debug(formatCompact({
155
+ const messageId = formatLegacyMessageRef({ conversation, id: snowflake });
156
+ this.#logger.debug(formatCompact({
157
157
  op: 'discord_send',
158
- endpoint: this.#options.config.name,
159
- target,
158
+ endpoint: this.#options.config.id,
159
+ target: formatLegacyConversationRef(conversation),
160
160
  messageId,
161
161
  }));
162
162
  return messageId;
@@ -184,18 +184,22 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
184
184
  message: { conversation, id: msg.id },
185
185
  content: formatInboundContent(msg),
186
186
  segments: formatInboundSegments(msg),
187
- sender: senderDisplayName(msg),
187
+ sender: {
188
+ id: msg.authorId,
189
+ name: senderDisplayName(msg) || undefined,
190
+ ...(resolveSenderRole(msg) ? { roles: [resolveSenderRole(msg)!] } : {}),
191
+ },
192
+ endpointId: this.#options.config.id,
193
+ ...(msg.mentionedBot ? { mentioned: true } : {}),
188
194
  metadata: Object.freeze({
189
- endpoint: this.#options.config.name,
190
195
  channelKind: msg.channelKind,
191
196
  userId: msg.authorId,
192
197
  guildId: msg.guildId,
193
198
  permissions: msg.permissionTokens,
194
199
  role: resolveSenderRole(msg),
195
- ...(msg.mentionedBot ? { mentioned: true } : {}),
196
200
  }),
197
201
  }).catch((err) => {
198
- logger.warn(formatCompact({
202
+ this.#logger.warn(formatCompact({
199
203
  op: 'discord_gateway_receive_failed',
200
204
  target: `${conversation.kind}:${conversation.id}`,
201
205
  error: err instanceof Error ? err.message : String(err),
@@ -212,15 +216,15 @@ export class DiscordGatewayEndpoint implements EndpointInstance {
212
216
  message: { conversation, id: interaction.id },
213
217
  content: formatButtonContent(interaction),
214
218
  segments: formatButtonSegments(interaction),
215
- sender: interaction.userName,
219
+ sender: { id: interaction.userId, name: interaction.userName },
220
+ endpointId: this.#options.config.id,
216
221
  metadata: Object.freeze({
217
- endpoint: this.#options.config.name,
218
222
  eventType: 'button',
219
223
  payload: interaction.customId,
220
224
  sourceMessageId: interaction.sourceMessageId,
221
225
  }),
222
226
  }).catch((err) => {
223
- logger.warn(formatCompact({
227
+ this.#logger.warn(formatCompact({
224
228
  op: 'discord_gateway_receive_failed',
225
229
  target: `${conversation.kind}:${conversation.id}`,
226
230
  error: err instanceof Error ? err.message : String(err),
@@ -419,6 +423,8 @@ export interface DiscordInteractionsEndpointOptions {
419
423
  }
420
424
 
421
425
  export class DiscordInteractionsEndpoint implements EndpointInstance {
426
+ readonly #logger!: ReturnType<typeof getAdapterLogger>;
427
+
422
428
  readonly #options: DiscordInteractionsEndpointOptions;
423
429
  readonly #fetch: typeof globalThis.fetch;
424
430
  #routeReleases: HttpRouteRegistration[] = [];
@@ -429,6 +435,7 @@ export class DiscordInteractionsEndpoint implements EndpointInstance {
429
435
  });
430
436
 
431
437
  constructor(options: DiscordInteractionsEndpointOptions) {
438
+ this.#logger = getAdapterLogger('discord', options.config.id);
432
439
  this.#options = options;
433
440
  this.#fetch = options.fetch ?? globalThis.fetch;
434
441
  }
@@ -445,9 +452,9 @@ export class DiscordInteractionsEndpoint implements EndpointInstance {
445
452
  if (this.#started) return;
446
453
  this.#started = true;
447
454
  this.#routeReleases.push(...registerDiscordInteractionRoutes(this.#options.http, this));
448
- logger.info(formatCompact({
455
+ this.#logger.info(formatCompact({
449
456
  op: 'connect',
450
- endpoint: this.#options.config.name,
457
+ endpoint: this.#options.config.id,
451
458
  mode: 'interactions',
452
459
  path: this.#options.config.interactionsPath,
453
460
  }));
@@ -465,7 +472,7 @@ export class DiscordInteractionsEndpoint implements EndpointInstance {
465
472
  this.#open = false;
466
473
  for (const release of this.#routeReleases.splice(0)) release();
467
474
  this.#started = false;
468
- logger.debug(formatCompact({ op: 'disconnect', endpoint: this.#options.config.name }));
475
+ this.#logger.debug(formatCompact({ op: 'disconnect' }));
469
476
  }
470
477
 
471
478
  async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
@@ -486,13 +493,8 @@ export class DiscordInteractionsEndpoint implements EndpointInstance {
486
493
  }
487
494
  const data = JSON.parse(text) as { id?: string };
488
495
  const snowflake = data.id ?? '';
489
- // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生 target
490
- return snowflake
491
- ? formatLegacyMessageReference({
492
- target: formatLegacyConversationRef(conversation),
493
- messageId: snowflake,
494
- })
495
- : '';
496
+ // recall 链路仍是本端点编码的 legacy 引用,在边界内部从 conversation 派生
497
+ return snowflake ? formatLegacyMessageRef({ conversation, id: snowflake }) : '';
496
498
  }
497
499
 
498
500
  async recallMessage(messageId: string): Promise<void> {
@@ -520,16 +522,20 @@ export class DiscordInteractionsEndpoint implements EndpointInstance {
520
522
  message: { conversation, id: msg.id },
521
523
  content: formatInboundContent(msg),
522
524
  segments: formatInboundSegments(msg),
523
- sender: senderDisplayName(msg),
525
+ sender: {
526
+ id: msg.authorId,
527
+ name: senderDisplayName(msg) || undefined,
528
+ ...(resolveSenderRole(msg) ? { roles: [resolveSenderRole(msg)!] } : {}),
529
+ },
530
+ endpointId: this.#options.config.id,
524
531
  metadata: Object.freeze({
525
- endpoint: this.#options.config.name,
526
532
  channelKind: msg.channelKind,
527
533
  userId: msg.authorId,
528
534
  guildId: msg.guildId,
529
535
  eventType: 'application_command',
530
536
  }),
531
537
  }).catch((err) => {
532
- logger.warn(formatCompact({
538
+ this.#logger.warn(formatCompact({
533
539
  op: 'discord_gateway_receive_failed',
534
540
  target: `${conversation.kind}:${conversation.id}`,
535
541
  error: err instanceof Error ? err.message : String(err),
package/src/index.ts CHANGED
@@ -30,7 +30,6 @@ export {
30
30
  discordGroupPermitResolver,
31
31
  normalizeDiscordSenderForPermit,
32
32
  platformPermit,
33
- registerDiscordPlatformPermitChecker,
34
33
  } from './platform-permit.js';
35
34
 
36
35
  export {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Discord platform permit — Guild 权限位
3
3
  */
4
- import { registerPlatformPermitChecker, type Message } from '@zhin.js/core';
4
+ import type { PermissionSubject } from '@zhin.js/permission';
5
5
 
6
6
  const ADAPTER = 'discord';
7
7
 
@@ -36,13 +36,9 @@ export function normalizeDiscordSenderForPermit(input: {
36
36
  return { role: 'member', permissions };
37
37
  }
38
38
 
39
- function senderPermits(message: Message<any>): { role?: string; permissions: string[] } {
40
- const sender = message.$sender as { role?: string; permissions?: string[] };
41
- return { role: sender.role, permissions: sender.permissions ?? [] };
42
- }
43
-
44
- export function checkDiscordPlatformPermit(perm: string, message: Message<any>): boolean {
45
- const { role, permissions } = senderPermits(message);
39
+ export function checkDiscordPlatformPermit(perm: string, subject: PermissionSubject): boolean {
40
+ const role = subject.sender?.role?.[0];
41
+ const permissions = subject.sender?.permissions ?? [];
46
42
  const has = (t: string) => permissions.includes(t);
47
43
 
48
44
  switch (perm) {
@@ -59,6 +55,3 @@ export function checkDiscordPlatformPermit(perm: string, message: Message<any>):
59
55
  }
60
56
  }
61
57
 
62
- export function registerDiscordPlatformPermitChecker(): () => void {
63
- return registerPlatformPermitChecker(ADAPTER, checkDiscordPlatformPermit);
64
- }
package/src/protocol.ts CHANGED
@@ -13,7 +13,7 @@ const logger = getLogger('discord');
13
13
 
14
14
  /** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
15
15
  export interface DiscordAdapterConfig {
16
- readonly name?: string;
16
+ readonly id?: string;
17
17
  readonly token?: string;
18
18
  /** Default `gateway`. `interactions` uses httpHostToken POST + Ed25519 verify. */
19
19
  readonly connection?: 'gateway' | 'interactions';
@@ -33,7 +33,7 @@ export interface DiscordAdapterConfig {
33
33
  /** Transitional: legacy root `endpoints[]` with `context: discord`. */
34
34
  readonly endpoints?: ReadonlyArray<{
35
35
  readonly context?: string;
36
- readonly name?: string;
36
+ readonly id?: string;
37
37
  readonly token?: string;
38
38
  readonly connection?: 'gateway' | 'interactions';
39
39
  readonly intents?: readonly number[];
@@ -50,7 +50,7 @@ export interface DiscordAdapterConfig {
50
50
  export interface ResolvedDiscordGatewayConfig {
51
51
  readonly context: 'discord';
52
52
  readonly connection: 'gateway';
53
- readonly name: string;
53
+ readonly id: string;
54
54
  readonly token: string;
55
55
  readonly intents?: readonly number[];
56
56
  readonly enableSlashCommands: boolean;
@@ -62,7 +62,7 @@ export interface ResolvedDiscordGatewayConfig {
62
62
  export interface ResolvedDiscordInteractionsConfig {
63
63
  readonly context: 'discord';
64
64
  readonly connection: 'interactions';
65
- readonly name: string;
65
+ readonly id: string;
66
66
  readonly token: string;
67
67
  readonly applicationId: string;
68
68
  readonly publicKey: string;
@@ -152,8 +152,8 @@ export function resolveDiscordConfig(config: DiscordAdapterConfig = {}): Resolve
152
152
  'Discord adapter requires token (plugins.<key>.token or endpoints with context: discord)',
153
153
  );
154
154
  }
155
- const name = (typeof config.name === 'string' && config.name)
156
- || (typeof entry?.name === 'string' && entry.name)
155
+ const id = (typeof config.id === 'string' && config.id)
156
+ || (typeof entry?.id === 'string' && entry.id)
157
157
  || process.env.DISCORD_BOT_NAME
158
158
  || 'discord-bot';
159
159
  const connection = config.connection
@@ -171,7 +171,7 @@ export function resolveDiscordConfig(config: DiscordAdapterConfig = {}): Resolve
171
171
  return {
172
172
  context: 'discord',
173
173
  connection: 'interactions',
174
- name,
174
+ id,
175
175
  token,
176
176
  applicationId,
177
177
  publicKey,
@@ -182,7 +182,7 @@ export function resolveDiscordConfig(config: DiscordAdapterConfig = {}): Resolve
182
182
  return {
183
183
  context: 'discord',
184
184
  connection: 'gateway',
185
- name,
185
+ id,
186
186
  token,
187
187
  intents: config.intents ?? entry?.intents,
188
188
  enableSlashCommands: config.enableSlashCommands === true
@@ -206,7 +206,7 @@ export function resolveChannelKind(channelType: number | string | undefined): 'p
206
206
  * endpoint.adapter = owner PluginId(CapabilityId 以 \0 分隔)。
207
207
  */
208
208
  export function discordInboundConversation(
209
- endpointId: string,
209
+ endpointKey: string,
210
210
  msg: {
211
211
  readonly channelId: string;
212
212
  readonly channelKind: 'private' | 'group' | 'channel';
@@ -214,7 +214,7 @@ export function discordInboundConversation(
214
214
  },
215
215
  ): ConversationRef {
216
216
  return {
217
- endpoint: { id: endpointId, adapter: endpointId.split('\0')[0] ?? endpointId },
217
+ endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
218
218
  kind: msg.channelKind,
219
219
  id: msg.channelId,
220
220
  ...(msg.guildId && msg.channelKind === 'channel'
File without changes
File without changes
File without changes
File without changes