polygram 0.12.0-rc.10 → 0.12.0-rc.11
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/lib/process/cli-process.js +43 -3
- package/package.json +1 -1
|
@@ -118,6 +118,16 @@ const STREAMING_HINT_RE = /esc to interrupt/i;
|
|
|
118
118
|
// — false positives surface as no-op telemetry, false negatives surface
|
|
119
119
|
// as the idle-ceiling timeout (~10min).
|
|
120
120
|
const UNKNOWN_PROMPT_HEURISTIC_RE = /(\?\s*$|\(y\/N\)|Yes\/No|❯\s|^\s*[12345]\.\s)/im;
|
|
121
|
+
// Dead-bridge signal. Claude Code prints "<source> no MCP server configured
|
|
122
|
+
// with that name" when a channel source references an MCP server that isn't
|
|
123
|
+
// registered. Music topic incident (2026-06-01): seen mid-turn after an
|
|
124
|
+
// auto-/compact of a large resumed session redrew the TUI and dropped the
|
|
125
|
+
// `server:polygram-bridge` binding — the turn could no longer deliver its
|
|
126
|
+
// reply and hung. The bridge name precedes the error on the same line, so
|
|
127
|
+
// anchor on it: matching the bare phrase risks a false hit on prose that
|
|
128
|
+
// merely quotes the error, while the healthy "polygram-bridge: <polygram-info>
|
|
129
|
+
// …" connection line never contains "no MCP server configured".
|
|
130
|
+
const BRIDGE_DEAD_RE = /polygram-bridge[^\n]*no MCP server configured/i;
|
|
121
131
|
// Per-pattern rate limit so a dialog that lingers across multiple polls
|
|
122
132
|
// doesn't spam sendControl/event emissions. Aligned with the 5s poll cadence.
|
|
123
133
|
const MID_TURN_DEDUP_WINDOW_MS = 30_000;
|
|
@@ -1848,11 +1858,11 @@ class CliProcess extends Process {
|
|
|
1848
1858
|
* landing just before the disconnect would otherwise leave a stray
|
|
1849
1859
|
* timer on the dead instance).
|
|
1850
1860
|
*/
|
|
1851
|
-
_handleBridgeDisconnected() {
|
|
1861
|
+
_handleBridgeDisconnected(reason = 'socket-close') {
|
|
1852
1862
|
this.bridgeReady = false;
|
|
1853
1863
|
this.mcpReady = false;
|
|
1854
1864
|
if (this.closed) return;
|
|
1855
|
-
this.logger.warn?.(`[${this.label}] channels: bridge disconnected unexpectedly`);
|
|
1865
|
+
this.logger.warn?.(`[${this.label}] channels: bridge disconnected unexpectedly (${reason})`);
|
|
1856
1866
|
// L6: clear the interrupt grace timer alongside the rest of the lifecycle.
|
|
1857
1867
|
if (this._interruptGraceTimer) {
|
|
1858
1868
|
clearTimeout(this._interruptGraceTimer);
|
|
@@ -1875,7 +1885,7 @@ class CliProcess extends Process {
|
|
|
1875
1885
|
this.pendingQueue.length = 0;
|
|
1876
1886
|
this.inFlight = false;
|
|
1877
1887
|
this.emit('bridge-disconnected');
|
|
1878
|
-
this._logEvent('bridge-disconnected', { reason
|
|
1888
|
+
this._logEvent('bridge-disconnected', { reason });
|
|
1879
1889
|
}
|
|
1880
1890
|
|
|
1881
1891
|
async _doKill(reason) {
|
|
@@ -2328,6 +2338,36 @@ class CliProcess extends Process {
|
|
|
2328
2338
|
}
|
|
2329
2339
|
if (!pane) return;
|
|
2330
2340
|
|
|
2341
|
+
// Wedge recovery (Music topic incident, 2026-06-01). Claude Code's
|
|
2342
|
+
// channel source can lose its MCP-server registration mid-turn — most
|
|
2343
|
+
// often after an auto-/compact of a large resumed session redraws the
|
|
2344
|
+
// TUI and the `server:polygram-bridge` binding fails to re-resolve
|
|
2345
|
+
// ("polygram-bridge no MCP server configured with that name"). The
|
|
2346
|
+
// bridge SOCKET stays up, so the socket-close path
|
|
2347
|
+
// (bridgeServer 'bridge-disconnected' → _handleBridgeDisconnected) never
|
|
2348
|
+
// fires — but claude can no longer deliver the reply, so the turn
|
|
2349
|
+
// orphans and would hang until the wall-clock cap while this watchdog
|
|
2350
|
+
// logged cli-mid-turn-unknown-prompt every 30s and recovered nothing.
|
|
2351
|
+
// Detect it from the pane and route through the SAME recovery as a real
|
|
2352
|
+
// socket disconnect: reject pending turns (user gets the 🔌 resend
|
|
2353
|
+
// message via BRIDGE_DISCONNECTED) and emit 'bridge-disconnected' so
|
|
2354
|
+
// process-manager kills + lazy-respawns the dead instance (next msg
|
|
2355
|
+
// recovers the conversation via `claude --resume`). Gated on
|
|
2356
|
+
// pendingTurns.size>0 by the early return above, so it can't fire on an
|
|
2357
|
+
// idle session that merely has the string in scrollback.
|
|
2358
|
+
if (BRIDGE_DEAD_RE.test(pane)) {
|
|
2359
|
+
this.logger.warn?.(
|
|
2360
|
+
`[${this.label}] cli: channels MCP registration lost mid-turn ` +
|
|
2361
|
+
`(pane-detected) — recovering ${this.pendingTurns.size} orphaned turn(s)`,
|
|
2362
|
+
);
|
|
2363
|
+
this._logEvent('cli-bridge-detached-midturn', {
|
|
2364
|
+
pending_count: this.pendingTurns.size,
|
|
2365
|
+
session_id: this.claudeSessionId,
|
|
2366
|
+
});
|
|
2367
|
+
this._handleBridgeDisconnected('mcp-registration-lost');
|
|
2368
|
+
return;
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2331
2371
|
const now = Date.now();
|
|
2332
2372
|
|
|
2333
2373
|
// 0.12 Phase 3.2: liveness heartbeat. The TUI prints "esc to interrupt"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.12.0-rc.
|
|
3
|
+
"version": "0.12.0-rc.11",
|
|
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": {
|