@wenbin_wb/dsh-bridge 2.6.1 → 2.7.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/lib/qq/gateway.js CHANGED
@@ -174,11 +174,14 @@ export class QqGateway extends Service {
174
174
  }
175
175
 
176
176
  async start() {
177
+ if (this._startingPromise) return this._startingPromise
177
178
  if (!this.configured) { this.setStatus('idle'); return }
178
- if (!this.loopTask) {
179
+ if (this.loopTask) return
180
+ this._startingPromise = (async () => {
179
181
  this.stopRequested = false
180
182
  this.loopTask = this.runLoop().finally(() => { this.loopTask = null })
181
- }
183
+ })().finally(() => { this._startingPromise = null })
184
+ return this._startingPromise
182
185
  }
183
186
 
184
187
  async persist(patch) {
@@ -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.1",
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.1 Windows 一键升级与自建协议修复】\n• 🛠️ 修复 Windows 平台下一键升级触发 `spawn EINVAL` 的问题\n• 🌐 修复自建隧道 WebSocket (ws/wss) 协议诊断报错的问题\n• 🛡️ 强化 Gateway 启动并发锁与会话恢复防抖",
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
  ],