polygram 0.8.0-rc.35 → 0.8.0-rc.37
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/.claude-plugin/plugin.json +1 -1
- package/lib/autosteer-buffer.js +13 -1
- package/lib/status-reactions.js +18 -7
- package/package.json +1 -1
- package/polygram.js +12 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "polygram",
|
|
4
|
-
"version": "0.8.0-rc.
|
|
4
|
+
"version": "0.8.0-rc.37",
|
|
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 and a history skill.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"telegram",
|
package/lib/autosteer-buffer.js
CHANGED
|
@@ -91,10 +91,18 @@ function createAutosteerBuffer() {
|
|
|
91
91
|
* non-empty output, with kind='autosteer-hook-drained'.
|
|
92
92
|
* @param {string|null} [opts.chatId] — for the logEvent payload only.
|
|
93
93
|
* @param {object} [opts.logger] — for error logging (must have .error).
|
|
94
|
+
* @param {(sessionKey: string, drainedCount: number) => void} [opts.onDrained]
|
|
95
|
+
* — fired AFTER the hook successfully injects additionalContext.
|
|
96
|
+
* rc.37 wires this to clearAutosteeredReactions so the ✍ reaction
|
|
97
|
+
* fades the moment the agent absorbs the follow-up — not at SDK
|
|
98
|
+
* turn-end, which under autosteer can stretch tens of minutes
|
|
99
|
+
* (one SDK turn keeps absorbing follow-ups via additionalContext
|
|
100
|
+
* and never emits result, so the old turn-end-only cleanup left
|
|
101
|
+
* ✍ stuck across many user messages).
|
|
94
102
|
*
|
|
95
103
|
* @returns {async () => Promise<HookJSONOutput>}
|
|
96
104
|
*/
|
|
97
|
-
function makePostToolBatchHook({ buffer, sessionKey, logEvent = null, chatId = null, logger = console } = {}) {
|
|
105
|
+
function makePostToolBatchHook({ buffer, sessionKey, logEvent = null, chatId = null, logger = console, onDrained = null } = {}) {
|
|
98
106
|
if (!buffer) throw new TypeError('buffer required');
|
|
99
107
|
if (!sessionKey) throw new TypeError('sessionKey required');
|
|
100
108
|
return async () => {
|
|
@@ -111,6 +119,10 @@ function makePostToolBatchHook({ buffer, sessionKey, logEvent = null, chatId = n
|
|
|
111
119
|
});
|
|
112
120
|
} catch { /* logger errors must not break the hook */ }
|
|
113
121
|
}
|
|
122
|
+
if (typeof onDrained === 'function') {
|
|
123
|
+
try { onDrained(sessionKey, drained.length); }
|
|
124
|
+
catch (err) { logger?.error?.(`[${sessionKey}] onDrained: ${err?.message || err}`); }
|
|
125
|
+
}
|
|
114
126
|
return {
|
|
115
127
|
continue: true,
|
|
116
128
|
hookSpecificOutput: {
|
package/lib/status-reactions.js
CHANGED
|
@@ -39,7 +39,13 @@ const STATES = {
|
|
|
39
39
|
// All three emoji on Telegram's curated standard reaction list.
|
|
40
40
|
THINKING: { label: 'thinking', chain: ['🤔'] },
|
|
41
41
|
THINKING_DEEPER: { label: 'thinking-deeper', chain: ['🤨', '🤔'] },
|
|
42
|
-
|
|
42
|
+
// rc.37: 🧐 (face with monocle) is REACTION_INVALID for bots — only
|
|
43
|
+
// Telegram Premium users can pick arbitrary emoji; bots are limited
|
|
44
|
+
// to ~70 standard reactions and 🧐 isn't on the list. Production
|
|
45
|
+
// log: `reaction apply failed (THINKING_DEEPEST → 🧐): 400: Bad
|
|
46
|
+
// Request: REACTION_INVALID`. 🤓 (nerd face, intellectual focus) is
|
|
47
|
+
// on the list and reads as "deeper than skeptical-eyebrow".
|
|
48
|
+
THINKING_DEEPEST: { label: 'thinking-deepest', chain: ['🤓', '🤔'] },
|
|
43
49
|
CODING: { label: 'coding', chain: ['👨💻', '✍', '🤔'] },
|
|
44
50
|
WEB: { label: 'web', chain: ['⚡', '🔥', '🤔'] },
|
|
45
51
|
TOOL: { label: 'tool', chain: ['🔥', '🤔'] },
|
|
@@ -81,12 +87,17 @@ const DEFAULT_STALL_MS = 45_000;
|
|
|
81
87
|
const DEFAULT_FREEZE_MS = 180_000;
|
|
82
88
|
// rc.32: thinking-deepening cascade thresholds. Calibrated to Ivan DM
|
|
83
89
|
// 14-day production data (445 turns) — 8% finish <5s, 33% in 5-15s,
|
|
84
|
-
// 25% in 15-30s.
|
|
85
|
-
//
|
|
90
|
+
// 25% in 15-30s. rc.35 bump: 8s→12s, 20s→30s. User feedback after
|
|
91
|
+
// rc.32 deploy was that the cascade kicked in too eagerly — most
|
|
92
|
+
// 5-15s turns showed 🤨 briefly before resolving, and the resulting
|
|
93
|
+
// emoji churn felt noisy rather than informative. Bumping deeper to
|
|
94
|
+
// 12s lets the entire 5-15s bracket (33%) resolve on plain 🤔, and
|
|
95
|
+
// deepest to 30s lets the 15-30s bracket (25%) resolve on 🤨 without
|
|
96
|
+
// cascading. STALL still fires at 45s for the genuinely-long 17%.
|
|
86
97
|
// CODING / TOOL / WEB / WRITING reset the cascade (any state-change
|
|
87
98
|
// in setState clears the deepening timers).
|
|
88
|
-
const DEFAULT_THINKING_DEEPER_MS =
|
|
89
|
-
const DEFAULT_THINKING_DEEPEST_MS =
|
|
99
|
+
const DEFAULT_THINKING_DEEPER_MS = 12_000;
|
|
100
|
+
const DEFAULT_THINKING_DEEPEST_MS = 30_000;
|
|
90
101
|
|
|
91
102
|
// Tool name → state classifier. Case-insensitive substring match so we
|
|
92
103
|
// don't have to enumerate every existing or future tool. Order matters:
|
|
@@ -219,8 +230,8 @@ function createReactionManager({
|
|
|
219
230
|
};
|
|
220
231
|
|
|
221
232
|
// rc.32: thinking-deepening cascade. When state is THINKING, schedule
|
|
222
|
-
// auto-promotion at
|
|
223
|
-
//
|
|
233
|
+
// auto-promotion at 12s (→ THINKING_DEEPER, 🤨) and 30s (→ THINKING_DEEPEST,
|
|
234
|
+
// 🤓). Any other setState (CODING / TOOL / WEB / WRITING / terminal) clears
|
|
224
235
|
// these. heartbeat() does NOT re-arm them — heartbeat is for keeping
|
|
225
236
|
// STALL/TIMEOUT at bay during silent activity, not for resetting
|
|
226
237
|
// visible deepening progression.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polygram",
|
|
3
|
-
"version": "0.8.0-rc.
|
|
3
|
+
"version": "0.8.0-rc.37",
|
|
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": {
|
package/polygram.js
CHANGED
|
@@ -931,6 +931,18 @@ function buildSdkOptions(sessionKey, ctx) {
|
|
|
931
931
|
chatId: ctx?.chatId ?? null,
|
|
932
932
|
logEvent,
|
|
933
933
|
logger: console,
|
|
934
|
+
// rc.37: clear ✍ reactions when the hook ABSORBS follow-ups, not
|
|
935
|
+
// at SDK turn-end. Under autosteer one SDK "turn" can stretch
|
|
936
|
+
// tens of minutes — every drain feeds more user text via
|
|
937
|
+
// additionalContext, the agent keeps reasoning, no `result` event
|
|
938
|
+
// fires, inFlight stays true, ✍ stays stuck on every drained
|
|
939
|
+
// follow-up. Clearing at drain time matches user perception
|
|
940
|
+
// ("the bot got my message → ✍ goes away").
|
|
941
|
+
onDrained: (key) => {
|
|
942
|
+
clearAutosteeredReactions(key).catch((err) => {
|
|
943
|
+
console.error(`[${BOT_NAME}] autosteer-hook clearReactions: ${err.message}`);
|
|
944
|
+
});
|
|
945
|
+
},
|
|
934
946
|
});
|
|
935
947
|
|
|
936
948
|
// 0.8.0-rc.21: SessionStart hook preloads recent polygram-DB
|