polygram 0.6.11 → 0.6.12

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/package.json +1 -1
  2. package/polygram.js +32 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polygram",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "Telegram daemon for Claude Code that preserves the OpenClaw per-chat session model. Migration path for OpenClaw users moving to Claude Code.",
5
5
  "main": "lib/ipc-client.js",
6
6
  "bin": {
package/polygram.js CHANGED
@@ -777,13 +777,23 @@ function dispatchHandleMessage(sessionKey, chatId, msg, bot) {
777
777
  const wasAborted = isSessionRecentlyAborted(sessionKey);
778
778
  const isReplay = msg._isReplay === true;
779
779
  console.error(`[${sessionKey}] Error:`, err.message);
780
- // Mark the row as 'failed' so boot replay doesn't re-dispatch it.
781
- // Exception: aborted sessions → 'aborted' (same — not replayable).
782
- // Shutdown case handled separately in the SIGTERM handler.
780
+ // Mark the row terminal so the right thing happens on next boot:
781
+ // - aborted: user explicitly stopped → 'aborted' (not replayable)
782
+ // - shutting down: the error is "Process exited" / "Process killed"
783
+ // from the SIGINT/SIGTERM tearing down claude mid-turn. Mark
784
+ // 'replay-pending' so the next boot picks it up via
785
+ // getReplayCandidates. Pre-0.6.12 we marked 'failed' here, which
786
+ // excluded the row from replay — a clean restart between user
787
+ // send and reply silently dropped the turn forever.
788
+ // - everything else: 'failed' (genuine claude crash / timeout etc).
789
+ const status = wasAborted
790
+ ? 'aborted'
791
+ : isShuttingDown
792
+ ? 'replay-pending'
793
+ : 'failed';
783
794
  dbWrite(() => db.setInboundHandlerStatus({
784
- chat_id: chatId, msg_id: msg.message_id,
785
- status: wasAborted ? 'aborted' : 'failed',
786
- }), 'set handler_status=failed/aborted');
795
+ chat_id: chatId, msg_id: msg.message_id, status,
796
+ }), `set handler_status=${status}`);
787
797
  logEvent('handler-error', {
788
798
  chat_id: chatId, session_key: sessionKey,
789
799
  msg_id: msg?.message_id,
@@ -1965,29 +1975,31 @@ function createBot(token) {
1965
1975
  });
1966
1976
  // Reply in the same language the user aborted in. Cyrillic-detection
1967
1977
  // is crude but reliable for ru/en (the only two cue sets we ship).
1978
+ // 0.6.12 fix: pre-0.6.5 the message included a "queue cleared (N)"
1979
+ // suffix when N > 0; that came from drainQueuesForChat which always
1980
+ // returned 0 in the concurrent model and was deleted in 0.6.5.
1981
+ // The reference to `dropped` here was missed, so EVERY abort hit
1982
+ // a ReferenceError that the surrounding `catch {}` swallowed —
1983
+ // leaving the user with no ack at all. Reduced to "stopped vs
1984
+ // nothing-to-stop" since the queue-cleared variant was already
1985
+ // dead.
1968
1986
  const lang = /[а-яё]/i.test(cleanText) ? 'ru' : 'en';
1969
1987
  const strs = {
1970
- en: {
1971
- stopped: 'Stopped.',
1972
- withDropped: (n) => `Stopped. Cleared ${n} queued message${n === 1 ? '' : 's'}.`,
1973
- nothing: 'Nothing to stop.',
1974
- },
1975
- ru: {
1976
- stopped: 'Остановлено.',
1977
- withDropped: (n) => `Остановлено. Очередь очищена (${n}).`,
1978
- nothing: 'Нечего останавливать.',
1979
- },
1988
+ en: { stopped: 'Stopped.', nothing: 'Nothing to stop.' },
1989
+ ru: { stopped: 'Остановлено.', nothing: 'Нечего останавливать.' },
1980
1990
  }[lang];
1981
- const reply = hadActive || dropped
1982
- ? (dropped ? strs.withDropped(dropped) : strs.stopped)
1983
- : strs.nothing;
1991
+ const reply = hadActive ? strs.stopped : strs.nothing;
1984
1992
  try {
1985
1993
  await tg(bot, 'sendMessage', {
1986
1994
  chat_id: chatId, text: reply,
1987
1995
  reply_parameters: { message_id: msg.message_id, allow_sending_without_reply: true },
1988
1996
  ...(threadId && { message_thread_id: threadId }),
1989
1997
  }, { source: 'abort-ack', botName: BOT_NAME });
1990
- } catch {}
1998
+ } catch (err) {
1999
+ // Don't swallow silently — if the ack itself fails, the operator
2000
+ // needs to know (the user typed stop and saw nothing).
2001
+ console.error(`[${BOT_NAME}] abort-ack send failed: ${err.message}`);
2002
+ }
1991
2003
  return;
1992
2004
  }
1993
2005