@wenbin_wb/dsh-bridge 2.6.1 → 2.7.0

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.
@@ -277,30 +277,37 @@ export class TelegramGateway extends Service {
277
277
  // ---- 生命周期 ----
278
278
 
279
279
  async start() {
280
+ if (this._startingPromise) return this._startingPromise
280
281
  if (!this.configured) {
281
282
  this.logger.info?.('[dsh-bridge telegram] not configured (missing botToken); staying idle')
282
283
  this.setStatus('idle')
283
284
  return false
284
285
  }
285
286
 
286
- this._stopPolling = false
287
- this.setStatus('connecting')
288
- if (this.config.proxy) {
289
- this._agent = createConnectProxyAgent(this.config.proxy)
290
- }
287
+ this._startingPromise = (async () => {
288
+ this._stopPolling = false
289
+ this.setStatus('connecting')
290
+ if (this.config.proxy) {
291
+ this._agent = createConnectProxyAgent(this.config.proxy)
292
+ }
291
293
 
292
- try {
293
- this.botInfo = await this.request('getMe')
294
- this.logger.info?.(`[dsh-bridge telegram] authenticated as @${this.botInfo.username} (id=${this.botInfo.id})`)
295
- this.setStatus('online')
296
- void this.registerCommands().catch(() => {})
297
- this._startPollLoop()
298
- return true
299
- } catch (err) {
300
- this.logger.error?.('[dsh-bridge telegram] getMe error:', err.message)
301
- this.setStatus('error', err.message)
302
- return false
303
- }
294
+ try {
295
+ this.botInfo = await this.request('getMe')
296
+ this.logger.info?.(`[dsh-bridge telegram] authenticated as @${this.botInfo.username} (id=${this.botInfo.id})`)
297
+ this.setStatus('online')
298
+ void this.registerCommands().catch(() => {})
299
+ this._startPollLoop()
300
+ return true
301
+ } catch (err) {
302
+ this.logger.error?.('[dsh-bridge telegram] getMe error:', err.message)
303
+ this.setStatus('error', err.message)
304
+ return false
305
+ } finally {
306
+ this._startingPromise = null
307
+ }
308
+ })()
309
+
310
+ return this._startingPromise
304
311
  }
305
312
 
306
313
  /**
@@ -335,6 +342,7 @@ export class TelegramGateway extends Service {
335
342
  async stop() {
336
343
  this._stopPolling = true
337
344
  this._polling = false
345
+ this._startingPromise = null
338
346
  this.setStatus('idle')
339
347
  }
340
348
 
@@ -387,11 +387,17 @@ export class WechatGateway extends Service {
387
387
  }
388
388
 
389
389
  async start() {
390
+ if (this._startingPromise) return this._startingPromise
390
391
  if (!this.configured) {
391
392
  this.setStatus('idle')
392
393
  return
393
394
  }
394
- await this.restart()
395
+ this._startingPromise = this.restart()
396
+ try {
397
+ await this._startingPromise
398
+ } finally {
399
+ this._startingPromise = null
400
+ }
395
401
  }
396
402
 
397
403
  setCredentials({ token, accountId, baseUrl } = {}) {
@@ -723,19 +729,27 @@ export class WechatGateway extends Service {
723
729
  // -------------------------------------------------------------------------
724
730
 
725
731
  async restart() {
726
- this.stopPollingLocal = true
727
- const previous = this.pollTask
728
- this.pollTask = null
729
- if (previous) {
730
- try { await previous } catch { /* 被替换 */ }
731
- }
732
- if (!this.configured) {
733
- this.setStatus('idle')
734
- return
732
+ if (this._restartingPromise) return this._restartingPromise
733
+ this._restartingPromise = (async () => {
734
+ this.stopPollingLocal = true
735
+ const previous = this.pollTask
736
+ this.pollTask = null
737
+ if (previous) {
738
+ try { await previous } catch { /* 被替换 */ }
739
+ }
740
+ if (!this.configured) {
741
+ this.setStatus('idle')
742
+ return
743
+ }
744
+ this.stopPollingLocal = false
745
+ this.setStatus('starting')
746
+ this.pollTask = this.runPollLoop()
747
+ })()
748
+ try {
749
+ await this._restartingPromise
750
+ } finally {
751
+ this._restartingPromise = null
735
752
  }
736
- this.stopPollingLocal = false
737
- this.setStatus('starting')
738
- this.pollTask = this.runPollLoop()
739
753
  }
740
754
 
741
755
  setStatus(status) {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@wenbin_wb/dsh-bridge",
3
- "version": "2.6.1",
3
+ "version": "2.7.0",
4
4
  "description": "手机扫码即可在移动端/公网继续用 DeepSeek Harness,人不在电脑前也能接着干。一键局域网二维码、Cloudflare 公网隧道、自建隧道与微信 / QQ / 飞书 / Telegram Bot(多工作区/会话持久化/媒体/卡片审批/流式输出),无需自己搭公网服务器。",
5
- "releaseNotes": "【v2.6.1 公网隧道自启与固定域名】\n• 🔄 支持公网隧道(Cloudflare/自建)开机自启与重启状态记忆\n• 🌐 支持 Cloudflare 命名隧道(Token 模式),永久固定专属域名永不变更\n• ⚙️ 控制台新增「随 DSH 启动自动开启」开关与高级 Token 配置",
5
+ "releaseNotes": "【v2.7.0 运维监控看板、网络诊断与会话重命名】\n• 📊 新增「宿主系统看板」:实时监控 CPU 核心、Uptime 运行时间与内存负载\n• 🔍 新增「网络连通性诊断」:一键探测本地端口、局域网、Cloudflare 与自建隧道服务器连通性\n• 🗄️ 新增「配置备份与恢复」:支持一键导出/导入全局配置与平台凭证\n• 🏷️ 新增「会话重命名指令」:IM 对话发送 `/rename <新标题>` 实时更新会话标题\n• 🔄 升级后支持一键重启 DSH 服务并自动探测重连刷新\n• 🎨 优化 Tab 栏无滚动条视觉排版与移动端触控体验",
6
6
  "type": "module",
7
7
  "main": "lib/index.js",
8
8
  "exports": {
@@ -18,6 +18,7 @@
18
18
  "cordis.patch.yml",
19
19
  "README.md",
20
20
  "README.en.md",
21
+ "CHANGELOG.md",
21
22
  "LICENSE",
22
23
  "docs"
23
24
  ],