polygram 0.10.0-rc.23 → 0.10.0-rc.24
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.10.0-rc.
|
|
4
|
+
"version": "0.10.0-rc.24",
|
|
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",
|
|
@@ -1363,6 +1363,40 @@ class TmuxProcess extends Process {
|
|
|
1363
1363
|
async _waitForReady() {
|
|
1364
1364
|
const deadline = this._now() + this.readyTimeoutMs;
|
|
1365
1365
|
let lastBuf = '';
|
|
1366
|
+
// B6 (shumorobot 2026-05-18, Music topic, twice): a slow
|
|
1367
|
+
// custom-agent spawn (`music-curation:music-curator` loading
|
|
1368
|
+
// several MCP servers) leaves the claude TUI mid-startup for
|
|
1369
|
+
// SECONDS — the production debug log shows MCP connections
|
|
1370
|
+
// spanning 14:45:31→14:45:40 (playwright 2.9s, context7 3.1s,
|
|
1371
|
+
// serena 3.8s, …) with the screen repainting hard the whole time
|
|
1372
|
+
// ("High write ratio: 100.0% writes"). Throughout that window the
|
|
1373
|
+
// TUI ALREADY renders its ready hint (`? for shortcuts` /
|
|
1374
|
+
// `bypass permissions on`) at the bottom of its startup banner.
|
|
1375
|
+
//
|
|
1376
|
+
// The old `_waitForReady` returned the INSTANT `READY_HINTS_RE`
|
|
1377
|
+
// matched — i.e. on the first poll, while MCP servers were still
|
|
1378
|
+
// loading. `start()` resolved early; the first `send()` pasted
|
|
1379
|
+
// the prompt into a TUI still ingesting startup, and the
|
|
1380
|
+
// submitted Enter was dropped → the prompt sat unsubmitted → the
|
|
1381
|
+
// turn never began (a fake THINKING→STALL followed). On a
|
|
1382
|
+
// no-agent TUI the startup window is sub-poll so it never bit; a
|
|
1383
|
+
// slow custom-agent spawn opens a multi-second window every time.
|
|
1384
|
+
//
|
|
1385
|
+
// The banner is NOT a usable "not ready" signal — it stays on the
|
|
1386
|
+
// pane indefinitely (the agent emits nothing pre-turn, so it
|
|
1387
|
+
// never scrolls into scrollback). The real discriminator is
|
|
1388
|
+
// QUIESCENCE: a genuinely-ready idle TUI produces a BYTE-STABLE
|
|
1389
|
+
// `capture-pane` between polls (static banner + empty input box +
|
|
1390
|
+
// ready hint), whereas a mid-startup TUI repaints every tick.
|
|
1391
|
+
//
|
|
1392
|
+
// Fix: require the ready hint to be present AND the captured pane
|
|
1393
|
+
// to be UNCHANGED across consecutive polls for `quiesceMs`
|
|
1394
|
+
// continuously before declaring ready — the same "must hold this
|
|
1395
|
+
// long" idea `_awaitTurnComplete` already uses for turn
|
|
1396
|
+
// completion. Bounded by `readyTimeoutMs`, so a genuinely wedged
|
|
1397
|
+
// spawn still throws TMUX_READY_TIMEOUT.
|
|
1398
|
+
let readySinceAt = null; // when the (hint + stable-pane) state began
|
|
1399
|
+
let prevBuf = null; // last poll's capture, for the stability compare
|
|
1366
1400
|
if (this.pollScheduler) this.pollScheduler.acquire();
|
|
1367
1401
|
try {
|
|
1368
1402
|
while (this._now() < deadline) {
|
|
@@ -1370,7 +1404,20 @@ class TmuxProcess extends Process {
|
|
|
1370
1404
|
// pane. Polling 1000 lines each tick is wasteful — cap at 80
|
|
1371
1405
|
// for a ~12× cheaper tmux subprocess.
|
|
1372
1406
|
lastBuf = await this.runner.captureWide(this.tmuxName, { lines: 80 });
|
|
1373
|
-
|
|
1407
|
+
// Ready ⇔ the hint is on the pane AND the pane is identical to
|
|
1408
|
+
// the previous poll (the MCP-loading repaint storm has
|
|
1409
|
+
// stopped). The first poll has no previous buffer to compare,
|
|
1410
|
+
// so it can never satisfy stability — readiness needs at
|
|
1411
|
+
// least two matching captures, which is the point.
|
|
1412
|
+
const hintPresent = READY_HINTS_RE.test(lastBuf);
|
|
1413
|
+
const paneStable = prevBuf !== null && lastBuf === prevBuf;
|
|
1414
|
+
if (hintPresent && paneStable) {
|
|
1415
|
+
if (readySinceAt == null) readySinceAt = this._now();
|
|
1416
|
+
if (this._now() - readySinceAt >= this.quiesceMs) return;
|
|
1417
|
+
} else {
|
|
1418
|
+
readySinceAt = null; // pane moved / hint gone → reset the clock
|
|
1419
|
+
}
|
|
1420
|
+
prevBuf = lastBuf;
|
|
1374
1421
|
await this._waitForNextTick();
|
|
1375
1422
|
}
|
|
1376
1423
|
} finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.10.0-rc.
|
|
3
|
+
"version": "0.10.0-rc.24",
|
|
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": {
|