polygram 0.8.0-rc.21 β 0.8.0-rc.23
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/package.json +1 -1
- package/polygram.js +60 -2
|
@@ -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.23",
|
|
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/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.23",
|
|
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
|
@@ -1987,6 +1987,51 @@ async function handleMessage(sessionKey, chatId, msg, bot) {
|
|
|
1987
1987
|
}
|
|
1988
1988
|
return;
|
|
1989
1989
|
}
|
|
1990
|
+
// 0.8.0-rc.22: /compact <preserve text> β manual SDK compaction with
|
|
1991
|
+
// user-supplied preservation instructions. The SDK's CLI binary
|
|
1992
|
+
// recognises "/compact" as a slash command via streamInput.push
|
|
1993
|
+
// (verified by scripts/spikes/compact-via-streaminput.mjs: PreCompact
|
|
1994
|
+
// hook fires with trigger:'manual', compact_boundary event lands).
|
|
1995
|
+
// We push the raw text "/compact <instructions>" through the SDK's
|
|
1996
|
+
// input controller; the SDK handles parsing + compaction internally.
|
|
1997
|
+
if (botAllowsCommands && text.startsWith('/compact')) {
|
|
1998
|
+
if (!pm.isSdkFor(sessionKey)) {
|
|
1999
|
+
await sendReply('ποΈ /compact requires the SDK pm. This chat is on the CLI pm path.');
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
if (!pm.has(sessionKey)) {
|
|
2003
|
+
await sendReply('ποΈ No active session β /compact only works once a turn has started.');
|
|
2004
|
+
return;
|
|
2005
|
+
}
|
|
2006
|
+
const entry = pm.get(sessionKey);
|
|
2007
|
+
if (!entry?.inputController?.push) {
|
|
2008
|
+
await sendReply('ποΈ Session not ready for /compact (no input controller).');
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
// Push the literal "/compact ..." text into the input stream.
|
|
2012
|
+
// The SDK parses leading "/" as a slash command and triggers
|
|
2013
|
+
// manual compaction; user's preserve instructions land in
|
|
2014
|
+
// PreCompactHookInput.custom_instructions.
|
|
2015
|
+
try {
|
|
2016
|
+
entry.inputController.push({
|
|
2017
|
+
type: 'user',
|
|
2018
|
+
message: { role: 'user', content: text },
|
|
2019
|
+
parent_tool_use_id: null,
|
|
2020
|
+
});
|
|
2021
|
+
logEvent('compact-command', {
|
|
2022
|
+
chat_id: chatId, text_len: text.length,
|
|
2023
|
+
user: cmdUser, user_id: cmdUserId,
|
|
2024
|
+
});
|
|
2025
|
+
const hasHint = text.length > '/compact'.length + 1;
|
|
2026
|
+
await sendReply(hasHint
|
|
2027
|
+
? 'ποΈ Compacting with your hintβ¦'
|
|
2028
|
+
: 'ποΈ Compactingβ¦');
|
|
2029
|
+
} catch (err) {
|
|
2030
|
+
console.error(`[${label}] /compact push: ${err.message}`);
|
|
2031
|
+
await sendReply(`ποΈ Couldn't trigger compact: ${err.message}`);
|
|
2032
|
+
}
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
1990
2035
|
if (botAllowsCommands && (text === '/new' || text === '/reset')) {
|
|
1991
2036
|
let drained = 0;
|
|
1992
2037
|
const target = pm.pickFor(sessionKey);
|
|
@@ -2603,9 +2648,22 @@ async function handleMessage(sessionKey, chatId, msg, bot) {
|
|
|
2603
2648
|
// context (and fired below the intended 85% threshold).
|
|
2604
2649
|
const pct = usage?.percentage ?? 0;
|
|
2605
2650
|
if (pct < 85) return;
|
|
2651
|
+
// rc.22: three-choice hint. The original "send /new"
|
|
2652
|
+
// message implied the only path forward was a hard
|
|
2653
|
+
// reset. Now offer all three options the user actually
|
|
2654
|
+
// has β start fresh, compact with their preserve
|
|
2655
|
+
// instructions, or keep going (auto-compact eventually
|
|
2656
|
+
// fires).
|
|
2657
|
+
const text = [
|
|
2658
|
+
`π Context window ${pct.toFixed(0)}% full. Three options:`,
|
|
2659
|
+
'',
|
|
2660
|
+
'β’ `/new` β start fresh; this conversation ends.',
|
|
2661
|
+
'β’ `/compact` β summarise older messages. Add a hint after the command (e.g. `/compact keep the Q3 commission decisions`) and that becomes the compactor\'s guidance.',
|
|
2662
|
+
'β’ Keep chatting β I\'ll auto-compact when needed; key context is preserved automatically.',
|
|
2663
|
+
].join('\n');
|
|
2606
2664
|
return tg(bot, 'sendMessage', {
|
|
2607
2665
|
chat_id: chatId,
|
|
2608
|
-
text
|
|
2666
|
+
text,
|
|
2609
2667
|
...(threadId ? { message_thread_id: threadId } : {}),
|
|
2610
2668
|
}, { source: 'context-full-hint', botName: BOT_NAME });
|
|
2611
2669
|
}).catch((err) => {
|
|
@@ -2868,7 +2926,7 @@ function createBot(token) {
|
|
|
2868
2926
|
// Cached once @botUsername is known β was recompiling per inbound msg.
|
|
2869
2927
|
let mentionRe = null;
|
|
2870
2928
|
// Hoisted admin-command matcher; was re-allocated per message.
|
|
2871
|
-
const ADMIN_CMD_RE = /^\/(model|effort|config|pair-code|pairings|unpair|new|reset|context)(\s|$)/;
|
|
2929
|
+
const ADMIN_CMD_RE = /^\/(model|effort|config|pair-code|pairings|unpair|new|reset|context|compact)(\s|$)/;
|
|
2872
2930
|
const PAIR_CLAIM_RE = /^\/pair\s+\S+/;
|
|
2873
2931
|
|
|
2874
2932
|
// The filter in main() guarantees config.chats only contains chats owned
|