polygram 0.5.4 → 0.5.6
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/package.json +1 -1
- package/polygram.js +41 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
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
|
@@ -571,6 +571,37 @@ async function sendToProcess(sessionKey, prompt, context = {}) {
|
|
|
571
571
|
const CONCURRENT_WARN_THRESHOLD = 20;
|
|
572
572
|
const inFlightHandlers = new Map(); // sessionKey → count
|
|
573
573
|
|
|
574
|
+
// Set true by the SIGTERM/SIGINT handler. Module-scoped so the
|
|
575
|
+
// fire-and-forget catch in dispatchHandleMessage can check it: when
|
|
576
|
+
// polygram is going down, in-flight handlers reject with "Process
|
|
577
|
+
// killed" / "Process exited" but those failures aren't "real" — the
|
|
578
|
+
// next boot's replay will re-dispatch them. Suppressing the user-facing
|
|
579
|
+
// error reply during shutdown removes a misleading post-mortem apology
|
|
580
|
+
// the user shouldn't see. (The boot replay's own _isReplay flag handles
|
|
581
|
+
// the OTHER half: suppressing if the replay itself fails.)
|
|
582
|
+
let isShuttingDown = false;
|
|
583
|
+
|
|
584
|
+
// Map a handler-error to a user-facing reply that says what happened
|
|
585
|
+
// and what to do next. The technical strings come from process-manager
|
|
586
|
+
// (idle / wall-clock timeouts) and node child_process (Process exited /
|
|
587
|
+
// killed). Anything we don't recognise falls back to a generic line
|
|
588
|
+
// with a single-line snippet of the error so the user can at least
|
|
589
|
+
// distinguish unique failures from the obvious "try again" cases.
|
|
590
|
+
function errorReplyText(err) {
|
|
591
|
+
const msg = err?.message || '';
|
|
592
|
+
if (/idle with no Claude activity/i.test(msg)) {
|
|
593
|
+
return '⏳ I went quiet too long without finishing. Try resending or simplifying the task.';
|
|
594
|
+
}
|
|
595
|
+
if (/wall-clock ceiling/i.test(msg)) {
|
|
596
|
+
return '⏱ This was taking too long, so I stopped. Try resending or simplifying the task.';
|
|
597
|
+
}
|
|
598
|
+
if (/Process (exited|killed)/i.test(msg)) {
|
|
599
|
+
return '💥 Something crashed on my end. Try again.';
|
|
600
|
+
}
|
|
601
|
+
const reason = msg.split('\n')[0].slice(0, 120);
|
|
602
|
+
return `Hit a snag: ${reason || 'unknown error'}. Try resending.`;
|
|
603
|
+
}
|
|
604
|
+
|
|
574
605
|
// Sessions the operator just /stop'd (or natural-language "стоп"). Keyed
|
|
575
606
|
// by sessionKey → timestamp of abort. ANY pending that rejects within
|
|
576
607
|
// ABORT_GRACE_MS of the mark is considered abort-caused — its generic
|
|
@@ -627,14 +658,16 @@ function dispatchHandleMessage(sessionKey, chatId, msg, bot) {
|
|
|
627
658
|
aborted: wasAborted || undefined,
|
|
628
659
|
replay: isReplay || undefined,
|
|
629
660
|
}), 'log handler-error');
|
|
630
|
-
// Suppress the
|
|
631
|
-
// boot replay
|
|
632
|
-
//
|
|
633
|
-
//
|
|
634
|
-
|
|
661
|
+
// Suppress the user-facing error reply when:
|
|
662
|
+
// - boot replay (user typed this minutes ago and moved on)
|
|
663
|
+
// - polygram is shutting down (the failure is "Process killed" /
|
|
664
|
+
// "Process exited" which isn't a real error — boot replay will
|
|
665
|
+
// re-dispatch it on next start)
|
|
666
|
+
// - user just /stop'd (already saw their abort acknowledgement)
|
|
667
|
+
if (!wasAborted && !isReplay && !isShuttingDown) {
|
|
635
668
|
tg(bot, 'sendMessage', {
|
|
636
669
|
chat_id: chatId,
|
|
637
|
-
text:
|
|
670
|
+
text: errorReplyText(err),
|
|
638
671
|
reply_parameters: { message_id: msg.message_id },
|
|
639
672
|
}, { source: 'error-reply', botName: BOT_NAME }).catch((replyErr) => {
|
|
640
673
|
console.error(`[${sessionKey}] failed to send error reply: ${replyErr.message}`);
|
|
@@ -2157,10 +2190,9 @@ async function main() {
|
|
|
2157
2190
|
// replay picks it up. Prevents "Sorry, I couldn't process that message"
|
|
2158
2191
|
// from showing on every restart.
|
|
2159
2192
|
const SHUTDOWN_DRAIN_MS = 30_000;
|
|
2160
|
-
let shuttingDown = false;
|
|
2161
2193
|
const shutdown = async () => {
|
|
2162
|
-
if (
|
|
2163
|
-
|
|
2194
|
+
if (isShuttingDown) return;
|
|
2195
|
+
isShuttingDown = true;
|
|
2164
2196
|
console.log('\nShutting down...');
|
|
2165
2197
|
// 1. Stop accepting new inbound first so nothing new queues behind the drain.
|
|
2166
2198
|
if (bot && bot._stop) bot._stop();
|