dsh-tg-bridge 1.2.2 → 1.2.4

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.
Files changed (2) hide show
  1. package/bridge.mjs +40 -0
  2. package/package.json +1 -1
package/bridge.mjs CHANGED
@@ -468,6 +468,35 @@ function commandOf(text) {
468
468
  return `/${match[1].toLowerCase().replace(/[.-]+/g, '')}`;
469
469
  }
470
470
 
471
+ /**
472
+ * Commands that must run *now*, not behind the turn they are about.
473
+ *
474
+ * Everything in a topic used to be queued, so `/stop` waited for the very turn
475
+ * it was supposed to kill — on 2026-10-24 a 26-minute turn swallowed `/stop`
476
+ * and the person got "ход уже идёт" instead of an interruption. These few
477
+ * commands touch no turn state, so they can run concurrently with one.
478
+ */
479
+ const IMMEDIATE_COMMANDS = new Set([
480
+ 'stop',
481
+ 'logs',
482
+ 'status',
483
+ 'help',
484
+ 'doctor',
485
+ 'restart',
486
+ ]);
487
+
488
+ /** Canonical immediate command name for a message, or '' when it must queue. */
489
+ function immediateCommandOf(text) {
490
+ const trimmed = String(text ?? '').trim();
491
+ if (!trimmed.startsWith('/')) return '';
492
+ const head = trimmed.split(/\s+/)[0];
493
+ const collapsed = commandOf(head).replace(/^\//, '');
494
+ if (collapsed === 'apprestart' || collapsed === 'apprestartconfirm' || collapsed === 'restartconfirm') {
495
+ return 'restart';
496
+ }
497
+ return IMMEDIATE_COMMANDS.has(collapsed) ? collapsed : '';
498
+ }
499
+
471
500
  /**
472
501
  * Turn model markdown into plain readable text.
473
502
  *
@@ -1657,6 +1686,17 @@ async function main() {
1657
1686
  }
1658
1687
  const queueKey = sessionKey(msg.chat.id, threadOf(msg));
1659
1688
  const thread = threadOf(msg);
1689
+ // `/stop` behind the turn it should kill is a no-op; run the few commands
1690
+ // that only read or kill state outside the per-topic queue.
1691
+ const immediate = immediateCommandOf(msg.text ?? '');
1692
+ if (immediate) {
1693
+ log(`command ${immediate} handled outside the queue`);
1694
+ Promise.resolve()
1695
+ .then(() => handleMessage(msg))
1696
+ .then(() => ack(update.update_id))
1697
+ .catch((error) => log(`command ${immediate} failed: ${error.message}`));
1698
+ return;
1699
+ }
1660
1700
  enqueue(
1661
1701
  queueKey,
1662
1702
  async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-tg-bridge",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Telegram bridge for DeepSeek Harness: text, voice, photos and project-per-topic sessions without opening the desktop app",
5
5
  "type": "module",
6
6
  "main": "bridge.mjs",