@wenbin_wb/dsh-bridge 2.8.0 → 2.8.1

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
@@ -4,6 +4,15 @@
4
4
 
5
5
  ---
6
6
 
7
+ ## [v2.8.1] - 2026-08-26
8
+
9
+ ### 🛡️ 微信/IM 消息分块保护与流式体验修复
10
+ - **🛡️ 修复消息被切成 20 字符碎片的问题**:排查并修复历史配置中 `maxMessageChars` 异常写入 `20` 导致的聊天框逐句高频切块分发问题;
11
+ - **⚙️ 全链路字符数下限安全防御**:在会话桥基类、各平台 Service 配置接口及启动加载链路中增加强制安全下限(`< 200` 自动回退为平台标准默认容量),彻底杜绝异常分块;
12
+ - **💬 微信与各 IM 平台体验恢复**:恢复完整 Markdown 回复、段落与代码块的原生一次性聚合推送。
13
+
14
+ ---
15
+
7
16
  ## [v2.8.0] - 2026-08-25
8
17
 
9
18
  ### 📱 移动端体验革新、远程工作区管理与全面安全加固
package/client/client.js CHANGED
@@ -1173,7 +1173,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
1173
1173
  setCfgDraft({
1174
1174
  digestIntervalSec: String(platform.config.digestIntervalSec ?? 300),
1175
1175
  approvalTimeoutSec: String(platform.config.approvalTimeoutSec ?? 600),
1176
- maxMessageChars: String(platform.config.maxMessageChars ?? (platformId === "telegram" ? 4096 : 2e3)),
1176
+ maxMessageChars: String((platform.config.maxMessageChars >= 500 ? platform.config.maxMessageChars : null) ?? (platformId === "telegram" ? 4096 : 2e3)),
1177
1177
  sendChunkDelayMs: String(platform.config.sendChunkDelayMs ?? 1500),
1178
1178
  appId: platform.config.appId ?? "",
1179
1179
  // Secret 不由后端回传;空值表示沿用已保存密钥
package/client/index.js CHANGED
@@ -1001,7 +1001,7 @@ function PlatformCard({ platformId, platformName, platformDesc, rpcCall, onStatu
1001
1001
  setCfgDraft({
1002
1002
  digestIntervalSec: String(platform.config.digestIntervalSec ?? 300),
1003
1003
  approvalTimeoutSec: String(platform.config.approvalTimeoutSec ?? 600),
1004
- maxMessageChars: String(platform.config.maxMessageChars ?? (platformId === 'telegram' ? 4096 : 2000)),
1004
+ maxMessageChars: String((platform.config.maxMessageChars >= 500 ? platform.config.maxMessageChars : null) ?? (platformId === 'telegram' ? 4096 : 2000)),
1005
1005
  sendChunkDelayMs: String(platform.config.sendChunkDelayMs ?? 1500),
1006
1006
  appId: platform.config.appId ?? '',
1007
1007
  // Secret 不由后端回传;空值表示沿用已保存密钥
@@ -181,7 +181,10 @@ export class FeishuService extends Platform {
181
181
  async setConfig({ digestIntervalSec, approvalTimeoutSec, maxMessageChars, sendChunkDelayMs, appId, appSecret, domain } = {}) {
182
182
  if (digestIntervalSec != null) this.node.config.digestIntervalSec = Number(digestIntervalSec)
183
183
  if (approvalTimeoutSec != null) this.node.config.approvalTimeoutSec = Number(approvalTimeoutSec)
184
- if (maxMessageChars != null) this.node.config.maxMessageChars = Number(maxMessageChars)
184
+ if (maxMessageChars != null) {
185
+ const val = Number(maxMessageChars)
186
+ this.node.config.maxMessageChars = (val >= 200) ? val : 2000
187
+ }
185
188
  if (sendChunkDelayMs != null) this.node.config.sendChunkDelayMs = Number(sendChunkDelayMs)
186
189
  if (appId !== undefined || appSecret !== undefined || domain !== undefined) {
187
190
  this.gateway.updateConfig({
package/lib/index.js CHANGED
@@ -1440,7 +1440,10 @@ function apply(ctx, config = {}) {
1440
1440
  wechat.node.config.allowFrom = Array.isArray(cfg.allowFrom) ? cfg.allowFrom : [];
1441
1441
  if (cfg.digestIntervalSec != null) wechat.node.config.digestIntervalSec = Number(cfg.digestIntervalSec);
1442
1442
  if (cfg.approvalTimeoutSec != null) wechat.node.config.approvalTimeoutSec = Number(cfg.approvalTimeoutSec);
1443
- if (cfg.maxMessageChars != null) wechat.node.config.maxMessageChars = Number(cfg.maxMessageChars);
1443
+ if (cfg.maxMessageChars != null) {
1444
+ const val = Number(cfg.maxMessageChars);
1445
+ wechat.node.config.maxMessageChars = (val >= 200) ? val : 2000;
1446
+ }
1444
1447
  if (cfg.sendChunkDelayMs != null) wechat.node.config.sendChunkDelayMs = Number(cfg.sendChunkDelayMs);
1445
1448
 
1446
1449
  wechat.node._restoringConfig = (async () => {
@@ -1552,7 +1555,10 @@ function apply(ctx, config = {}) {
1552
1555
  telegram.node.config.allowFrom = Array.isArray(cfg.allowFrom) ? cfg.allowFrom : [];
1553
1556
  if (cfg.digestIntervalSec != null) telegram.node.config.digestIntervalSec = Number(cfg.digestIntervalSec);
1554
1557
  if (cfg.approvalTimeoutSec != null) telegram.node.config.approvalTimeoutSec = Number(cfg.approvalTimeoutSec);
1555
- if (cfg.maxMessageChars != null) telegram.node.config.maxMessageChars = Number(cfg.maxMessageChars);
1558
+ if (cfg.maxMessageChars != null) {
1559
+ const val = Number(cfg.maxMessageChars);
1560
+ telegram.node.config.maxMessageChars = (val >= 200) ? val : 4096;
1561
+ }
1556
1562
  if (cfg.sendChunkDelayMs != null) telegram.node.config.sendChunkDelayMs = Number(cfg.sendChunkDelayMs);
1557
1563
 
1558
1564
  telegram.node._restoringConfig = (async () => {
@@ -220,11 +220,13 @@ export class ConversationBridge {
220
220
  this.onActiveSessionChange = onActiveSessionChange
221
221
 
222
222
  const maxChars = platform.capabilities?.maxMessageChars ?? 2000
223
+ const rawMax = Number(config.maxMessageChars)
224
+ const safeMaxChars = (Number.isFinite(rawMax) && rawMax > 0) ? rawMax : maxChars
223
225
  this.config = {
224
226
  allowFrom: Array.isArray(config.allowFrom) ? config.allowFrom : [],
225
227
  digestIntervalSec: config.digestIntervalSec ?? 300,
226
228
  approvalTimeoutSec: config.approvalTimeoutSec ?? 600,
227
- maxMessageChars: config.maxMessageChars ?? maxChars,
229
+ maxMessageChars: safeMaxChars,
228
230
  sendChunkDelayMs: config.sendChunkDelayMs ?? 1500,
229
231
  cwd: config.cwd,
230
232
  agentPreset: config.agentPreset,
package/lib/qq/index.js CHANGED
@@ -268,7 +268,10 @@ export class QqService extends Platform {
268
268
  async setConfig({ digestIntervalSec, approvalTimeoutSec, maxMessageChars, sendChunkDelayMs, appId, clientSecret } = {}) {
269
269
  if (digestIntervalSec != null) this.node.config.digestIntervalSec = Number(digestIntervalSec)
270
270
  if (approvalTimeoutSec != null) this.node.config.approvalTimeoutSec = Number(approvalTimeoutSec)
271
- if (maxMessageChars != null) this.node.config.maxMessageChars = Number(maxMessageChars)
271
+ if (maxMessageChars != null) {
272
+ const val = Number(maxMessageChars)
273
+ this.node.config.maxMessageChars = (val >= 200) ? val : 2000
274
+ }
272
275
  if (sendChunkDelayMs != null) this.node.config.sendChunkDelayMs = Number(sendChunkDelayMs)
273
276
  if (appId !== undefined || clientSecret !== undefined) {
274
277
  this.gateway.setCredentials({
@@ -175,7 +175,10 @@ export class TelegramService extends Platform {
175
175
  async setConfig({ digestIntervalSec, approvalTimeoutSec, maxMessageChars, sendChunkDelayMs, botToken, proxy } = {}) {
176
176
  if (digestIntervalSec != null) this.node.config.digestIntervalSec = Number(digestIntervalSec)
177
177
  if (approvalTimeoutSec != null) this.node.config.approvalTimeoutSec = Number(approvalTimeoutSec)
178
- if (maxMessageChars != null) this.node.config.maxMessageChars = Number(maxMessageChars)
178
+ if (maxMessageChars != null) {
179
+ const val = Number(maxMessageChars)
180
+ this.node.config.maxMessageChars = (val >= 200) ? val : 4096
181
+ }
179
182
  if (sendChunkDelayMs != null) this.node.config.sendChunkDelayMs = Number(sendChunkDelayMs)
180
183
 
181
184
  if (botToken !== undefined || proxy !== undefined) {
@@ -222,7 +222,10 @@ export class WechatService extends Platform {
222
222
  async setConfig({ digestIntervalSec, approvalTimeoutSec, maxMessageChars, sendChunkDelayMs } = {}) {
223
223
  if (digestIntervalSec != null) this.node.config.digestIntervalSec = Number(digestIntervalSec)
224
224
  if (approvalTimeoutSec != null) this.node.config.approvalTimeoutSec = Number(approvalTimeoutSec)
225
- if (maxMessageChars != null) this.node.config.maxMessageChars = Number(maxMessageChars)
225
+ if (maxMessageChars != null) {
226
+ const val = Number(maxMessageChars)
227
+ this.node.config.maxMessageChars = (val >= 200) ? val : gatewayConstants.MAX_MESSAGE_CHARS
228
+ }
226
229
  if (sendChunkDelayMs != null) this.node.config.sendChunkDelayMs = Number(sendChunkDelayMs)
227
230
  await this.persist({
228
231
  digestIntervalSec: this.node.config.digestIntervalSec,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@wenbin_wb/dsh-bridge",
3
- "version": "2.8.0",
3
+ "version": "2.8.1",
4
4
  "description": "手机扫码即可在移动端/公网继续用 DeepSeek Harness,人不在电脑前也能接着干。一键局域网二维码、Cloudflare 公网隧道、自建隧道与微信 / QQ / 飞书 / Telegram Bot(多工作区/会话持久化/媒体/卡片审批/流式输出),无需自己搭公网服务器。",
5
- "releaseNotes": "【v2.8.0 移动端体验革新、远程工作区管理与全面安全加固】\n• 🗂️ 远程工作区网页选择器:移动端/远程点击添加工作区自动呼出网页端目录浏览器,本机电脑智能无感分流原生系统选择器\n• 📱 移动端视觉与布局体验深度优化:顶部导航栏居中动态标题、第二行徽标与极简下载图标两端排布、底部工具栏防重叠自适应\n• 🔐 全方位安全加固:RPC 端点鉴权、路径穿越与系统核心目录防御、滑动窗口限流与 IM 权限拦截",
5
+ "releaseNotes": "【v2.8.1 微信/IM 消息分块保护与流式体验修复】\n• 🛡️ 修复微信/IM 平台单条消息分块字符数因异常配置被切成 20 字符碎片的问题\n• ⚙️ 增加消息分块字符数全局安全下限防御(自动纠偏并保底为平台标准容量)\n• 💬 恢复微信/各平台完整段落与 Markdown 代码块的原生一次性下发",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
8
8
  "exports": {