polygram 0.12.0-rc.27 → 0.12.0-rc.29
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 +61 -0
- package/package.json +1 -1
|
@@ -690,6 +690,22 @@ class CliProcess extends Process {
|
|
|
690
690
|
'as normal — only the FINAL user-visible message needs to go through',
|
|
691
691
|
'the reply tool.',
|
|
692
692
|
'',
|
|
693
|
+
// TEMPORARY mitigation (2026-06-08 Shumabit@UMI wedge): AskUserQuestion opens
|
|
694
|
+
// a blocking TUI selection widget the channel can't answer → the session
|
|
695
|
+
// parks until manually Esc'd. REMOVE this whole rule when the rich
|
|
696
|
+
// question→Telegram-keyboard feature ships (see docs design); claude should
|
|
697
|
+
// then use the native question tool again. Tracked so it isn't forgotten.
|
|
698
|
+
'### Asking the user a question / offering choices — HARD RULE',
|
|
699
|
+
'',
|
|
700
|
+
'NEVER use the AskUserQuestion tool or any interactive menu / selection',
|
|
701
|
+
'widget. They open a blocking terminal prompt the user on Telegram CANNOT',
|
|
702
|
+
'see or navigate — it silently wedges the entire session until it is manually',
|
|
703
|
+
'cleared. (Rich tap-to-answer choices are coming; until then this is a hard rule.)',
|
|
704
|
+
'',
|
|
705
|
+
'To ask a multiple-choice question, write the options as a numbered list',
|
|
706
|
+
'inside your `mcp__polygram-bridge__reply` text and ask the user to reply with',
|
|
707
|
+
'the number (or free text). Do the same for yes/no and any selection.',
|
|
708
|
+
'',
|
|
693
709
|
'### Sending FILES (tracks, images, docs) to the user',
|
|
694
710
|
'',
|
|
695
711
|
'The `mcp__polygram-bridge__reply` tool takes an optional `files` array of',
|
|
@@ -1207,6 +1223,42 @@ class CliProcess extends Process {
|
|
|
1207
1223
|
}
|
|
1208
1224
|
}
|
|
1209
1225
|
|
|
1226
|
+
/**
|
|
1227
|
+
* Keep a turn alive while claude is still TOOL-working (2026-06-08 Shumabit@UMI
|
|
1228
|
+
* WA-topic incident). The per-turn reply-quiet window (`quietTimer`, armed in
|
|
1229
|
+
* _recordReplyForPendingTurn) is reset ONLY by reply tool calls. So a turn that
|
|
1230
|
+
* replied and then kept working with NON-reply tools — claude read a follow-up
|
|
1231
|
+
* screenshot, ran a Bash API check, then replied again 90s later, all inside ONE
|
|
1232
|
+
* claude turn (no Stop hook until the very end) — resolved on the reply-quiet
|
|
1233
|
+
* window WHILE claude was still active. Its reactor + typing tore down at the
|
|
1234
|
+
* premature resolve, and the late reply fell through to the orphan
|
|
1235
|
+
* autonomous-assistant-message path (no pending turn).
|
|
1236
|
+
*
|
|
1237
|
+
* claude's Stop hook is the AUTHORITATIVE turn-end; until it lands, a PreToolUse/
|
|
1238
|
+
* PostToolUse hook means claude is still working — so push the reply-quiet window
|
|
1239
|
+
* (and the idle ceiling) out. The absoluteTimer (30-min runaway cap) is left
|
|
1240
|
+
* untouched as the hard backstop, and Stop still resolves normally. Turns that
|
|
1241
|
+
* reply then truly stop (no intervening tool hooks) are unaffected — there's no
|
|
1242
|
+
* tool activity to extend on.
|
|
1243
|
+
*/
|
|
1244
|
+
_extendQuietOnToolActivity() {
|
|
1245
|
+
for (const [turnId, pending] of this.pendingTurns) {
|
|
1246
|
+
if (pending._stopGracePending) continue; // already finalizing — don't revive
|
|
1247
|
+
// Idle ceiling: tool activity IS activity (mirrors the per-reply reset at
|
|
1248
|
+
// _recordReplyForPendingTurn so a long tool-heavy turn isn't idle-killed).
|
|
1249
|
+
if (pending.hardTimer) {
|
|
1250
|
+
clearTimeout(pending.hardTimer);
|
|
1251
|
+
pending.hardTimer = setTimeout(() => pending._fireTimeout?.('idle'), this.turnTimeoutMs);
|
|
1252
|
+
}
|
|
1253
|
+
// Reply-quiet window: only armed AFTER the first reply — that's exactly the
|
|
1254
|
+
// post-reply-still-tooling case this fixes.
|
|
1255
|
+
if (pending.quietTimer) {
|
|
1256
|
+
clearTimeout(pending.quietTimer);
|
|
1257
|
+
pending.quietTimer = setTimeout(() => this._resolveTurn(turnId), this.turnQuietMs);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1210
1262
|
// 0.12 Phase 1.7 (Finding 0.1.A): two-step turn resolution.
|
|
1211
1263
|
// _resolveTurn — entry point called by channel-result OR quiet-window
|
|
1212
1264
|
// expiry. Schedules a stopGraceMs window during which
|
|
@@ -1799,6 +1851,15 @@ class CliProcess extends Process {
|
|
|
1799
1851
|
});
|
|
1800
1852
|
}
|
|
1801
1853
|
|
|
1854
|
+
// 2026-06-08 (WA-topic incident): a tool hook means claude is STILL working,
|
|
1855
|
+
// so keep its turn(s) alive — the reply-quiet window must not resolve a turn
|
|
1856
|
+
// mid-work just because the last *reply* was a few seconds ago. See
|
|
1857
|
+
// _extendQuietOnToolActivity. Reply tool calls are handled separately (their
|
|
1858
|
+
// own reset in _recordReplyForPendingTurn); covering them here too is a no-op.
|
|
1859
|
+
if (ev.type === 'PreToolUse' || ev.type === 'PostToolUse') {
|
|
1860
|
+
this._extendQuietOnToolActivity();
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1802
1863
|
switch (ev.type) {
|
|
1803
1864
|
case 'UserPromptSubmit':
|
|
1804
1865
|
this.emit('turn-start', {
|
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.29",
|
|
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": {
|