polygram 0.10.0-rc.44 → 0.10.0-rc.46
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.46",
|
|
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",
|
|
@@ -1569,9 +1569,26 @@ class TmuxProcess extends Process {
|
|
|
1569
1569
|
_heartbeat(turn, source) {
|
|
1570
1570
|
if (!turn) return;
|
|
1571
1571
|
turn.lastActivityAt = this._now();
|
|
1572
|
-
//
|
|
1573
|
-
//
|
|
1574
|
-
//
|
|
1572
|
+
// rc.45 (shumorobot main topic 2026-05-23): the reactor's
|
|
1573
|
+
// cascade timers (THINKING_DEEPER at 12 s, THINKING_DEEPEST at
|
|
1574
|
+
// 30 s, STALL at 45 s) were firing during long pure-thinking
|
|
1575
|
+
// turns because no signal reset the clock — hooks don't fire
|
|
1576
|
+
// during thinking, JSONL `assistant-chunk` doesn't fire either.
|
|
1577
|
+
// But capture-pane DOES see claude's continuous "esc to
|
|
1578
|
+
// interrupt" indicator throughout the thinking phase, and the
|
|
1579
|
+
// existing `_heartbeat(turn, 'capture:streaming')` call from
|
|
1580
|
+
// line 2620 already runs on every poll while claude is busy.
|
|
1581
|
+
// Route that signal to the reactor too — the cascade clock is
|
|
1582
|
+
// reset and the user sees a stable 🤔 instead of escalating to
|
|
1583
|
+
// 🥱 (STALL) on a healthy long-thinking turn.
|
|
1584
|
+
//
|
|
1585
|
+
// The SDK backend gets this for free via typed `thinking`
|
|
1586
|
+
// events that flow through onStreamChunk → reactor.heartbeat.
|
|
1587
|
+
// tmux had no equivalent until this hookup.
|
|
1588
|
+
const reactor = turn.context?.reactor;
|
|
1589
|
+
if (reactor && typeof reactor.heartbeat === 'function') {
|
|
1590
|
+
try { reactor.heartbeat(); } catch { /* swallow — heartbeat is best-effort */ }
|
|
1591
|
+
}
|
|
1575
1592
|
void source;
|
|
1576
1593
|
}
|
|
1577
1594
|
|
|
@@ -53,24 +53,43 @@ const SANITIZED_REPLACEMENT =
|
|
|
53
53
|
'_(the model returned no actual reply — try rephrasing or asking again)_';
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
* Inspect an outbound assistant text.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* substitution.
|
|
56
|
+
* Inspect an outbound assistant text. Replaces any occurrence of a
|
|
57
|
+
* known CLI-context canned string (as a SUBSTRING) with the honest
|
|
58
|
+
* fallback, and returns a `replaced` flag so the caller can log the
|
|
59
|
+
* substitution.
|
|
60
|
+
*
|
|
61
|
+
* Why substring-replace, not exact-match (rc.45 production discovery):
|
|
62
|
+
* claude can emit MULTIPLE assistant-message blocks within one turn,
|
|
63
|
+
* and polygram concatenates them into the final `parsed.text`. If
|
|
64
|
+
* claude's first block was a substantive reply and the second was
|
|
65
|
+
* the canned `No response requested.`, the combined `parsed.text`
|
|
66
|
+
* matches neither canned string exactly — so the previous exact-
|
|
67
|
+
* match sanitizer didn't fire and the canned string still reached
|
|
68
|
+
* Telegram as a separate bubble (shumorobot Music topic and main
|
|
69
|
+
* topic, 2026-05-23, msg 999).
|
|
70
|
+
*
|
|
71
|
+
* Substring replacement risk: a legitimate reply that DISCUSSES the
|
|
72
|
+
* canned phrase ("the model leaks 'No response requested.' here")
|
|
73
|
+
* will have the inner phrase replaced. Cost is cosmetic (slightly
|
|
74
|
+
* ugly italicised replacement embedded in prose), not catastrophic.
|
|
75
|
+
* The CANNED_STRINGS allowlist stays narrow to keep this rare.
|
|
60
76
|
*
|
|
61
77
|
* @param {string} text — the assistant text about to be sent.
|
|
62
78
|
* @returns {{ text: string, replaced: boolean, original?: string }}
|
|
63
79
|
*/
|
|
64
80
|
function sanitizeAssistantReply(text) {
|
|
65
81
|
if (typeof text !== 'string') return { text, replaced: false };
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
82
|
+
if (!text) return { text, replaced: false };
|
|
83
|
+
let mutated = text;
|
|
84
|
+
let firstHit = null;
|
|
85
|
+
for (const canned of CANNED_STRINGS) {
|
|
86
|
+
if (mutated.includes(canned)) {
|
|
87
|
+
if (firstHit == null) firstHit = canned;
|
|
88
|
+
mutated = mutated.split(canned).join(SANITIZED_REPLACEMENT);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (firstHit != null) {
|
|
92
|
+
return { text: mutated, replaced: true, original: firstHit };
|
|
74
93
|
}
|
|
75
94
|
return { text, replaced: false };
|
|
76
95
|
}
|
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.46",
|
|
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": {
|