polygram 0.33.4 → 0.33.5

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
3
  "name": "polygram",
4
- "version": "0.33.4",
4
+ "version": "0.33.5",
5
5
  "description": "Telegram integration for Claude Code that preserves the OpenClaw per-chat session model. Migration target for OpenClaw users. Multi-bot, multi-chat, per-topic isolation; SQLite transcripts; inline-keyboard approvals. Bundles /polygram:status|logs|pair-code|approvals admin commands plus history (transcript queries) and polygram-send (out-of-turn IPC sends with file-upload validation) skills.",
6
6
  "keywords": [
7
7
  "telegram",
@@ -152,6 +152,10 @@ function listUnresolvedCodexAttempts(rawDb, input = {}) {
152
152
  location.telegram_message_id,
153
153
  unresolved.telegram_source_message_id
154
154
  )
155
+ WHERE COALESCE(
156
+ location.telegram_message_id,
157
+ unresolved.telegram_source_message_id
158
+ ) IS NOT NULL
155
159
  ORDER BY unresolved.ambiguous_ts,
156
160
  unresolved.attempt_id
157
161
  `).all(sessionKey, sessionKey);
@@ -59,7 +59,7 @@ function createDispatcher({
59
59
  // the historic 4096 for back-compat in synthetic test runs that pass
60
60
  // pre-formatted text.
61
61
  chunkBudget = 4096,
62
- // Delay before a silent startup auto-retry re-dispatches (TMUX_SESSION_GONE).
62
+ // Delay before a silent startup auto-retry re-dispatches a pre-delivery failure.
63
63
  // Injected so tests can drive it to 0; production uses STARTUP_RETRY_DELAY_MS.
64
64
  startupRetryDelayMs = STARTUP_RETRY_DELAY_MS,
65
65
  // AUTH_DISABLED dedupe/re-arm gate (docs/AUTH_DISABLED_HANDLING_SPEC.md).
@@ -306,6 +306,11 @@ function createDispatcher({
306
306
  chat_id: chatId, session_key: sessionKey,
307
307
  msg_id: msg?.message_id,
308
308
  error: err.message?.slice(0, 500),
309
+ code: err.code || undefined,
310
+ cause_code: err.cause?.code || undefined,
311
+ stderr_tail: err.code === 'TMUX_SPAWN_FAILED' && typeof err.stderr === 'string'
312
+ ? err.stderr.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, '').slice(-500)
313
+ : undefined,
309
314
  stack: err.stack?.split('\n').slice(0, 5).join('\n'),
310
315
  aborted: wasAborted || undefined,
311
316
  replay: isReplay || undefined,
@@ -442,23 +447,17 @@ function createDispatcher({
442
447
  }
443
448
  }
444
449
  const provider = providerRecovery?.provider;
445
- // Startup auto-retry (option a, 2026-06-04). TMUX_SESSION_GONE = claude
446
- // exited INSIDE the startup gate, before the dev-channels channel went
447
- // live — so the user's message was NEVER delivered to claude. That makes
448
- // a re-send idempotent BY CONSTRUCTION (unlike a mid-turn drop, where
449
- // claude might still be slowly processing). The session_id was just
450
- // poison-cleared above, so re-dispatching the SAME message spawns a FRESH
451
- // session and delivers it. Silent: a transient startup flake (recurs
452
- // ~once/9h on the channels backend) never reaches the user — instead of
453
- // the "🔄 reset it, resend" papercut, polygram just retries. One-shot
454
- // (_startupRetried) so a host that genuinely can't start claude surfaces
455
- // the friendly reset reply (below) after EXACTLY one retry, never a loop.
456
- // Scoped to TMUX_SESSION_GONE only: CHANNELS_DIALOG_TIMEOUT is a real
457
- // blocking dialog (usage-limit / permission) a retry would just re-hit,
458
- // so it keeps its "please resend" copy.
459
- if (err.code === 'TMUX_SESSION_GONE' && !msg._startupRetried) {
450
+ // Retry once when startup fails before the bridge can deliver the user's
451
+ // message. TMUX_SESSION_GONE is poison-cleared above; TMUX_SPAWN_FAILED
452
+ // is already torn down by CliProcess's start-failure cleanup. Mid-turn
453
+ // failures and blocking dialogs are excluded because replay could
454
+ // duplicate work or immediately re-hit the same user decision.
455
+ const startupRetryable = err.code === 'TMUX_SESSION_GONE'
456
+ || err.code === 'TMUX_SPAWN_FAILED';
457
+ if (startupRetryable && !msg._startupRetried) {
460
458
  logEvent('startup-auto-retry', {
461
459
  chat_id: chatId, session_key: sessionKey, msg_id: msg?.message_id,
460
+ code: err.code,
462
461
  });
463
462
  // Re-dispatch a COPY carrying the one-shot marker — never mutate the
464
463
  // caller's msg (the boot-replay path shares/re-reads it). unref the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polygram",
3
- "version": "0.33.4",
3
+ "version": "0.33.5",
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": {