polygram 0.38.1 → 0.38.3
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/.claude-plugin/plugin.json +1 -1
- package/lib/approvals/store.js +45 -7
- package/lib/codex/runtime-controller.js +107 -1
- package/lib/db/event-detail-schema.js +523 -0
- package/lib/db/pairings.js +9 -1
- package/lib/db/secret-sweep.js +6 -3
- package/lib/db/sessions.js +2 -2
- package/lib/db.js +353 -49
- package/lib/handlers/abort.js +20 -3
- package/lib/handlers/approvals.js +2 -2
- package/lib/handlers/config-callback.js +7 -7
- package/lib/handlers/dispatcher.js +24 -9
- package/lib/handlers/questions.js +546 -45
- package/lib/handlers/slash-commands.js +54 -13
- package/lib/handlers/voice.js +1 -1
- package/lib/ipc/handlers.js +4 -0
- package/lib/ops/clean-restart-qualification.js +1 -0
- package/lib/ops/clean-shutdown.js +5 -0
- package/lib/ops/deploy-restart-handler.js +111 -0
- package/lib/ops/foreground-canary-target.js +454 -0
- package/lib/questions/questions.js +51 -0
- package/lib/questions/store.js +61 -5
- package/lib/rewind/execute.js +12 -2
- package/lib/rewind/rewind.js +1 -1
- package/lib/sdk/build-options.js +2 -2
- package/lib/sdk/callbacks.js +14 -9
- package/lib/secret-detect.js +280 -12
- package/lib/telegram/api.js +10 -2
- package/lib/telegram/rich-edit.js +9 -5
- package/lib/telegram/rich-send.js +6 -6
- package/migrations/020-drop-secret-fingerprint.sql +13 -0
- package/package.json +2 -2
- package/polygram.js +117 -68
|
@@ -605,19 +605,19 @@ function createHandleConfigCallback({
|
|
|
605
605
|
for (const { scope, value } of cleared) scope[configField] = value;
|
|
606
606
|
};
|
|
607
607
|
// The user tapped one card; topics they never touched can change value
|
|
608
|
-
// with it. Record
|
|
609
|
-
//
|
|
610
|
-
//
|
|
608
|
+
// with it. Record WHICH ones, by id, so a config that moved on its own
|
|
609
|
+
// is still explicable afterwards — the values they held are
|
|
610
|
+
// configuration content and the ids answer the question without them.
|
|
611
|
+
// Logged only once the sweep is persisted — an event for a rolled-back
|
|
612
|
+
// sweep is worse than none.
|
|
611
613
|
const logTopicRichTextSweep = (cleared) => {
|
|
612
614
|
if (!cleared.length) return;
|
|
613
615
|
dbWrite(() => {
|
|
614
616
|
db.logEvent('config-topic-override-swept', {
|
|
615
617
|
chat_id: chatId,
|
|
616
618
|
field: configField,
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
old_value: value,
|
|
620
|
-
})),
|
|
619
|
+
topic_ids: cleared.map(({ threadId }) => String(threadId)),
|
|
620
|
+
topics_cleared: cleared.length,
|
|
621
621
|
});
|
|
622
622
|
}, 'log topic-override sweep');
|
|
623
623
|
};
|
|
@@ -77,6 +77,7 @@ function createDispatcher({
|
|
|
77
77
|
// Per-session in-flight handler count.
|
|
78
78
|
const inFlightHandlers = new Map();
|
|
79
79
|
const activeHandlers = new Set();
|
|
80
|
+
const activeHandlerTargets = new Set();
|
|
80
81
|
|
|
81
82
|
function trackTask(task) {
|
|
82
83
|
activeHandlers.add(task);
|
|
@@ -265,6 +266,15 @@ function createDispatcher({
|
|
|
265
266
|
}
|
|
266
267
|
|
|
267
268
|
function dispatchHandleMessage(sessionKey, chatId, msg, bot) {
|
|
269
|
+
const activeHandlerTarget = Object.freeze({
|
|
270
|
+
sessionKey: String(sessionKey),
|
|
271
|
+
chatId: String(chatId),
|
|
272
|
+
threadId: msg?.message_thread_id == null
|
|
273
|
+
? null
|
|
274
|
+
: String(msg.message_thread_id),
|
|
275
|
+
telegramMessageId: String(msg?.message_id),
|
|
276
|
+
});
|
|
277
|
+
activeHandlerTargets.add(activeHandlerTarget);
|
|
268
278
|
const count = (inFlightHandlers.get(sessionKey) || 0) + 1;
|
|
269
279
|
inFlightHandlers.set(sessionKey, count);
|
|
270
280
|
const warnAt = queueWarnThreshold();
|
|
@@ -305,13 +315,14 @@ function createDispatcher({
|
|
|
305
315
|
logEvent('handler-error', {
|
|
306
316
|
chat_id: chatId, session_key: sessionKey,
|
|
307
317
|
msg_id: msg?.message_id,
|
|
308
|
-
|
|
318
|
+
error_class: err.name || 'Error',
|
|
319
|
+
error_len: err.message?.length ?? 0,
|
|
309
320
|
code: err.code || undefined,
|
|
310
321
|
cause_code: err.cause?.code || undefined,
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
322
|
+
// A spawn failure's stderr is process output, not a field: its size
|
|
323
|
+
// says whether the child said anything at all, which is the signal
|
|
324
|
+
// that distinguishes "tmux refused" from "tmux said nothing".
|
|
325
|
+
stderr_len: typeof err.stderr === 'string' ? err.stderr.length : undefined,
|
|
315
326
|
aborted: wasAborted || undefined,
|
|
316
327
|
replay: isReplay || undefined,
|
|
317
328
|
oom_shutdown: oomShutdown || undefined,
|
|
@@ -332,7 +343,7 @@ function createDispatcher({
|
|
|
332
343
|
logger.error?.(`[${sessionKey}] failed to clear lost session: ${resetErr.message}`);
|
|
333
344
|
logEvent('session-reset-after-process-loss-failed', {
|
|
334
345
|
chat_id: chatId, session_key: sessionKey, msg_id: msg?.message_id,
|
|
335
|
-
|
|
346
|
+
error_class: resetErr.name || 'Error',
|
|
336
347
|
});
|
|
337
348
|
}
|
|
338
349
|
}
|
|
@@ -368,7 +379,8 @@ function createDispatcher({
|
|
|
368
379
|
logger.error?.(`[auth] (${botName}) Claude access DISABLED by Anthropic — turn rejected immediately instead of wedging; check the account/billing.`);
|
|
369
380
|
logEvent('auth-disabled', {
|
|
370
381
|
chat_id: chatId, session_key: sessionKey, msg_id: msg?.message_id,
|
|
371
|
-
|
|
382
|
+
error_class: err.name || 'Error',
|
|
383
|
+
error_len: err.message?.length ?? 0,
|
|
372
384
|
});
|
|
373
385
|
// Never let the gate itself become a new failure mode — AUTH_DISABLED
|
|
374
386
|
// is account-wide, so a bad gate would throw on every concurrent
|
|
@@ -486,7 +498,7 @@ function createDispatcher({
|
|
|
486
498
|
autoResumeTracker.markAttempt(sessionKey);
|
|
487
499
|
logEvent('auto-resume-attempted', {
|
|
488
500
|
chat_id: chatId, session_key: sessionKey, msg_id: msg.message_id,
|
|
489
|
-
|
|
501
|
+
error_class: err.name || 'Error',
|
|
490
502
|
});
|
|
491
503
|
return attemptAutoResume(sessionKey, chatId, msg, bot, {
|
|
492
504
|
provider,
|
|
@@ -502,7 +514,7 @@ function createDispatcher({
|
|
|
502
514
|
logger.error?.(`[${sessionKey}] auto-resume failed: ${resumeErr?.message}`);
|
|
503
515
|
logEvent('auto-resume-failed', {
|
|
504
516
|
chat_id: chatId, session_key: sessionKey, msg_id: msg.message_id,
|
|
505
|
-
|
|
517
|
+
error_class: resumeErr?.name || 'Error',
|
|
506
518
|
});
|
|
507
519
|
// Music topic incident (2026-06-01): a channels session whose
|
|
508
520
|
// context grew large enough to auto-/compact on resume loses its
|
|
@@ -562,6 +574,7 @@ function createDispatcher({
|
|
|
562
574
|
}
|
|
563
575
|
}
|
|
564
576
|
}).finally(() => {
|
|
577
|
+
activeHandlerTargets.delete(activeHandlerTarget);
|
|
565
578
|
const n = (inFlightHandlers.get(sessionKey) || 1) - 1;
|
|
566
579
|
if (n <= 0) inFlightHandlers.delete(sessionKey);
|
|
567
580
|
else inFlightHandlers.set(sessionKey, n);
|
|
@@ -575,6 +588,8 @@ function createDispatcher({
|
|
|
575
588
|
errorReplyText,
|
|
576
589
|
queueWarnThreshold,
|
|
577
590
|
inFlightHandlers, // exposed so polygram.js can introspect for shutdown drain
|
|
591
|
+
getActiveHandlerCount: () => activeHandlers.size,
|
|
592
|
+
getActiveHandlerTargets: () => [...activeHandlerTargets],
|
|
578
593
|
awaitSettlement,
|
|
579
594
|
trackTask,
|
|
580
595
|
};
|