dsh-im-union 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  本项目版本号遵循语义化版本;发布面与宿主兼容矩阵见 `scripts/hosts.mjs`(README 管理块同源)。
4
4
 
5
+ ## 0.5.2(Discord 服务器频道消息失联:Gateway intents 位值修正)
6
+
7
+ 感谢 @lide4144 在 #1 里的报告与双连接对照实验,定位、根因与修正值全部准确。
8
+
9
+ ### Fixed
10
+
11
+ - **Gateway intents 位值写错导致服务器频道消息永远收不到**(#1):`GUILD_MESSAGES` 实写为 `1 << 15`(应为 `1 << 9`)、`MESSAGE_CONTENT` 实写为 `1 << 24`(应为 `1 << 15`,且 `1 << 24` 不是任何已定义 intent)。于是 IDENTIFY 实际请求的是 `MESSAGE_CONTENT | DIRECT_MESSAGES | 未定义位`,**从未订阅 GUILD_MESSAGES**——Discord 因此不推送服务器频道的 `MESSAGE_CREATE`;而握手/READY/心跳全部正常,连接看着是健康的,故极难发现。有有效值 `16814080 → 37377`。**不引入新的门户勾选要求**:`MESSAGE_CONTENT`(特权位)此前已被 `1 << 15` 误命名请求着,行为不变。
12
+ - **IDENTIFY 补齐 `GUILDS`(`1 << 0`)**:此前 `INTENTS.GUILDS` 定了却从未使用,招不到 `GUILD_CREATE`,部分场景(刚加入的服务器、缓存缺失的频道)拿不到上下文。
13
+ - **`createDiscordAdapter` 透传 `logger`**:`ChannelFactory` 契约早已有 `logger` 字段(宿主接线到 `plugin.log`),本工厂始终丢弃它,导致 Discord 适配器的全量生命周期日志(含“Gateway 断开”)不落盘——#1 里“`plugin.log` 没有任何入站记录”的次因。
14
+ - **测试不得拿实现值自证**:`tests/discord.test.mjs` 原本把错误位值 `(1<<15)|(1<<12)|(1<<24)` 钉进了断言,这是本缺陷能存活的原因。现改为按官方文档值逐位断言,并加“`1<<24` 必须为 0”的回归守卫;新增 logger 透传用例。全量 771/771 绿。
15
+
16
+ ### Known(本版本未动,另单跟踪)
17
+
18
+ - Gateway `close` 后无自动重连(仅记日志),op 7 RECONNECT 后靠重建;`AccountManager.ensureConnected` 只在操作时触发——Discord 定期下发 RECONNECT 时会静默失联直到手动重启。属代码内已标注的 **T2.5 挂账**(需退避策略 + RESUME/session 生命周期设计),与本次位值修正无关。
19
+
5
20
  ## 0.5.0(QQ 渠道能力补齐:出站图片 / Markdown / 入站图片文件 / 审批按钮 / 群管理)
6
21
 
7
22
  对照 `_ref-im/dsh-qqbot`(同一套 QQ 官方 api-v2)逐面解锁 `src/channels/qq.ts`,遵守净室 / 零运行时依赖 / D7 纪律。
package/dsh.plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "dsh-im-union",
3
3
  "name": "dsh-im-union",
4
- "version": "0.5.1",
4
+ "version": "0.5.2",
5
5
  "description": {
6
6
  "en": "Union IM bridge for DeepSeek Harness: multi-account bots across messaging platforms, each chat bound to its own session, with cross-host-version compatibility (0.1.2-rc.1 .. 0.2.1-rc.3).",
7
7
  "zh": "DeepSeek Harness 的 IM 联合桥:多平台多账号机器人、每个聊天绑定独立会话,跨宿主版本兼容(0.1.2-rc.1 至 0.2.1-rc.3)。"
@@ -131,6 +131,8 @@ export declare function createDiscordAdapter(options: {
131
131
  accountId: string;
132
132
  config: Record<string, string>;
133
133
  secrets: Record<string, string | undefined>;
134
+ /** 生命周期日志出口(`ChannelFactory` 契约字段);不接则 Gateway 断开等日志静默。 */
135
+ logger?: (msg: string) => void;
134
136
  }): DiscordAdapter;
135
137
  interface DiscordMessageLike {
136
138
  channel_id?: string;
@@ -1,10 +1,23 @@
1
1
  import { FILE_BUDGET } from '../engine/files.js';
2
2
  import { mergeQuote } from '../engine/quote.js';
3
+ /**
4
+ * Gateway intents:位值逐条对齐官方 list-of-intents。
5
+ *
6
+ * 写错不会报错也不会断连——只是对应事件永远不推,连接看着完全健康,所以很难发现
7
+ * (历史上 `GUILD_MESSAGES` 被写成 `1 << 15`、`MESSAGE_CONTENT` 写成 `1 << 24`,
8
+ * 于是服务器频道消息永远收不到)。故每个常量带官方位号注释,并由
9
+ * `tests/discord.test.mjs` 按位钉值校验(断言写在测试里的必须是官方文档值,
10
+ * 不得拿实现值自证)。
11
+ */
3
12
  const INTENTS = {
13
+ /** `1 << 0` GUILDS:`GUILD_CREATE` 等(非特权)。 */
4
14
  GUILDS: 1 << 0,
15
+ /** `1 << 9` GUILD_MESSAGES:服务器频道 `MESSAGE_CREATE`(非特权)。 */
16
+ GUILD_MESSAGES: 1 << 9,
17
+ /** `1 << 12` DIRECT_MESSAGES:私聊 `MESSAGE_CREATE`(非特权)。 */
5
18
  DIRECT_MESSAGES: 1 << 12,
6
- GUILD_MESSAGES: 1 << 15,
7
- MESSAGE_CONTENT: 1 << 24,
19
+ /** `1 << 15` MESSAGE_CONTENT:读消息正文(**特权** intent,需在开发者门户勾选)。 */
20
+ MESSAGE_CONTENT: 1 << 15,
8
21
  };
9
22
  const OP = {
10
23
  DISPATCH: 0,
@@ -204,7 +217,8 @@ export class DiscordAdapter {
204
217
  op: OP.IDENTIFY,
205
218
  d: {
206
219
  token: this.token,
207
- intents: INTENTS.GUILD_MESSAGES | INTENTS.DIRECT_MESSAGES | INTENTS.MESSAGE_CONTENT,
220
+ // 含 GUILDS:否则无 GUILD_CREATE,部分场景(刚加入的服务器、缓存缺失的频道)拿不到上下文。
221
+ intents: INTENTS.GUILDS | INTENTS.GUILD_MESSAGES | INTENTS.DIRECT_MESSAGES | INTENTS.MESSAGE_CONTENT,
208
222
  properties: { os: 'dsh-plugin', browser: 'dsh-im-union', device: 'dsh-im-union' },
209
223
  },
210
224
  });
@@ -549,5 +563,9 @@ export function createDiscordAdapter(options) {
549
563
  throw new Error(`discord 账号 ${options.accountId}: botToken 未入库(检查凭据配置)`);
550
564
  }
551
565
  const apiBase = options.config.apiBaseUrl;
552
- return new DiscordAdapter({ token, ...(apiBase !== undefined && apiBase !== '' ? { apiBase } : {}) });
566
+ return new DiscordAdapter({
567
+ token,
568
+ ...(apiBase !== undefined && apiBase !== '' ? { apiBase } : {}),
569
+ ...(options.logger !== undefined ? { logger: options.logger } : {}),
570
+ });
553
571
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-im-union",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Union IM bridge for DeepSeek Harness 鈥?clean-room merge of dsh-im and dsh-im-connect capabilities, compatible across 0.1.2-rc.1 .. 0.2.1-rc.2 hosts.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -39,11 +39,24 @@ import type {
39
39
  SemanticMessage,
40
40
  } from './types.js'
41
41
 
42
+ /**
43
+ * Gateway intents:位值逐条对齐官方 list-of-intents。
44
+ *
45
+ * 写错不会报错也不会断连——只是对应事件永远不推,连接看着完全健康,所以很难发现
46
+ * (历史上 `GUILD_MESSAGES` 被写成 `1 << 15`、`MESSAGE_CONTENT` 写成 `1 << 24`,
47
+ * 于是服务器频道消息永远收不到)。故每个常量带官方位号注释,并由
48
+ * `tests/discord.test.mjs` 按位钉值校验(断言写在测试里的必须是官方文档值,
49
+ * 不得拿实现值自证)。
50
+ */
42
51
  const INTENTS = {
52
+ /** `1 << 0` GUILDS:`GUILD_CREATE` 等(非特权)。 */
43
53
  GUILDS: 1 << 0,
54
+ /** `1 << 9` GUILD_MESSAGES:服务器频道 `MESSAGE_CREATE`(非特权)。 */
55
+ GUILD_MESSAGES: 1 << 9,
56
+ /** `1 << 12` DIRECT_MESSAGES:私聊 `MESSAGE_CREATE`(非特权)。 */
44
57
  DIRECT_MESSAGES: 1 << 12,
45
- GUILD_MESSAGES: 1 << 15,
46
- MESSAGE_CONTENT: 1 << 24,
58
+ /** `1 << 15` MESSAGE_CONTENT:读消息正文(**特权** intent,需在开发者门户勾选)。 */
59
+ MESSAGE_CONTENT: 1 << 15,
47
60
  } as const
48
61
 
49
62
  const OP = {
@@ -277,7 +290,8 @@ export class DiscordAdapter implements ChannelAdapter {
277
290
  op: OP.IDENTIFY,
278
291
  d: {
279
292
  token: this.token,
280
- intents: INTENTS.GUILD_MESSAGES | INTENTS.DIRECT_MESSAGES | INTENTS.MESSAGE_CONTENT,
293
+ // 含 GUILDS:否则无 GUILD_CREATE,部分场景(刚加入的服务器、缓存缺失的频道)拿不到上下文。
294
+ intents: INTENTS.GUILDS | INTENTS.GUILD_MESSAGES | INTENTS.DIRECT_MESSAGES | INTENTS.MESSAGE_CONTENT,
281
295
  properties: { os: 'dsh-plugin', browser: 'dsh-im-union', device: 'dsh-im-union' },
282
296
  },
283
297
  })
@@ -647,13 +661,19 @@ export function createDiscordAdapter(options: {
647
661
  accountId: string
648
662
  config: Record<string, string>
649
663
  secrets: Record<string, string | undefined>
664
+ /** 生命周期日志出口(`ChannelFactory` 契约字段);不接则 Gateway 断开等日志静默。 */
665
+ logger?: (msg: string) => void
650
666
  }): DiscordAdapter {
651
667
  const token = options.secrets.botToken
652
668
  if (typeof token !== 'string' || token === '') {
653
669
  throw new Error(`discord 账号 ${options.accountId}: botToken 未入库(检查凭据配置)`)
654
670
  }
655
671
  const apiBase = options.config.apiBaseUrl
656
- return new DiscordAdapter({ token, ...(apiBase !== undefined && apiBase !== '' ? { apiBase } : {}) })
672
+ return new DiscordAdapter({
673
+ token,
674
+ ...(apiBase !== undefined && apiBase !== '' ? { apiBase } : {}),
675
+ ...(options.logger !== undefined ? { logger: options.logger } : {}),
676
+ })
657
677
  }
658
678
 
659
679
  interface DiscordMessageLike {