claude-telegram-bot 0.3.31 β 0.3.34
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/bot.mjs +62 -10
- package/package.json +1 -1
package/bot.mjs
CHANGED
|
@@ -150,6 +150,7 @@ const STR = {
|
|
|
150
150
|
compactOk: "ποΈ Context compacted. The conversation continues with a summary.",
|
|
151
151
|
compactFail: (m) => `β οΈ Compact failed: ${m}`,
|
|
152
152
|
compactNoSession: "No active session to compact. Just send a message to start one.",
|
|
153
|
+
autoCompact: "ποΈ Auto-compacted context (conversation was getting long).",
|
|
153
154
|
testFallbackDisabled: "β οΈ Ollama fallback is not enabled. Set `\"ollamaFallback\": true` in config.json.",
|
|
154
155
|
testFallbackFail: (m) => `β οΈ Ollama test failed: ${m}`,
|
|
155
156
|
ollamaOn: "π Ollama mode on. Messages will now go to Ollama. Your Claude session is preserved.",
|
|
@@ -292,6 +293,7 @@ const STR = {
|
|
|
292
293
|
compactOk: "ποΈ μ»¨ν
μ€νΈλ₯Ό μμΆνμ΅λλ€. λνκ° μμ½λ³ΈμΌλ‘ μ΄μ΄μ§λλ€.",
|
|
293
294
|
compactFail: (m) => `β οΈ compact μ€ν¨: ${m}`,
|
|
294
295
|
compactNoSession: "μμΆν νμ± μΈμ
μ΄ μμ΅λλ€. λ©μμ§λ₯Ό λ³΄λ΄ μΈμ
μ μμνμΈμ.",
|
|
296
|
+
autoCompact: "ποΈ λνκ° κΈΈμ΄μ Έ 컨ν
μ€νΈλ₯Ό μλ μμΆνμ΅λλ€.",
|
|
295
297
|
contextTooLong: "β οΈ ν둬ννΈκ° λ무 κΉλλ€. `/compact` λ‘ μ»¨ν
μ€νΈλ₯Ό μμΆνκ±°λ `/new` λ‘ μ μΈμ
μ μμνμΈμ.",
|
|
296
298
|
testFallbackDisabled: "β οΈ Ollama ν΄λ°±μ΄ λΉνμ±ν μνμ
λλ€. config.jsonμ `\"ollamaFallback\": true` λ₯Ό μΆκ°νμΈμ.",
|
|
297
299
|
testFallbackFail: (m) => `β οΈ Ollama ν
μ€νΈ μ€ν¨: ${m}`,
|
|
@@ -570,15 +572,33 @@ function classifyClaudeError(raw, code) {
|
|
|
570
572
|
return `Execution error (exit ${code}):\n${raw}`;
|
|
571
573
|
}
|
|
572
574
|
|
|
575
|
+
// ββ 컀μ€ν
λͺ
λ Ήμ΄ μ€ν¬λ¦½νΈ μ€ν ββββββββββββββββββββββββββββββββββββββββββ
|
|
576
|
+
function runCustomCommand(run, args) {
|
|
577
|
+
return new Promise((resolve) => {
|
|
578
|
+
const cmd = args ? `${run} ${args}` : run;
|
|
579
|
+
const child = spawn(cmd, [], {
|
|
580
|
+
shell: true,
|
|
581
|
+
cwd: cfg.projectDir,
|
|
582
|
+
env: { ...process.env, ...(cfg.env || {}) },
|
|
583
|
+
});
|
|
584
|
+
let out = "", err = "";
|
|
585
|
+
child.stdout.on("data", (d) => (out += d));
|
|
586
|
+
child.stderr.on("data", (d) => (err += d));
|
|
587
|
+
child.on("close", (code) => {
|
|
588
|
+
const text = (out + (err ? `\n[stderr]\n${err}` : "")).trim() || "(no output)";
|
|
589
|
+
resolve({ ok: code === 0, text, code });
|
|
590
|
+
});
|
|
591
|
+
child.on("error", (e) => resolve({ ok: false, text: e.message, code: -1 }));
|
|
592
|
+
setTimeout(() => { try { child.kill(); } catch {} resolve({ ok: false, text: "timeout (60s)", code: -1 }); }, 60_000);
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
573
596
|
// ββ Claude μ€ν βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
574
597
|
function runClaude(prompt, sessionId, opts = {}) {
|
|
575
598
|
return new Promise((resolve) => {
|
|
576
599
|
const args = [
|
|
577
|
-
"-
|
|
578
|
-
"--
|
|
579
|
-
"json",
|
|
580
|
-
"--permission-mode",
|
|
581
|
-
cfg.permissionMode || "acceptEdits",
|
|
600
|
+
"--output-format", "json",
|
|
601
|
+
"--permission-mode", cfg.permissionMode || "acceptEdits",
|
|
582
602
|
];
|
|
583
603
|
const model = state.model || cfg.model; // /model λ‘ λ°κΎΈλ©΄ state.model μ°μ
|
|
584
604
|
const brevity =
|
|
@@ -596,8 +616,9 @@ function runClaude(prompt, sessionId, opts = {}) {
|
|
|
596
616
|
if (appendSys) args.push("--append-system-prompt", appendSys);
|
|
597
617
|
if (model) args.push("--model", model);
|
|
598
618
|
if (sessionId) args.push("--resume", sessionId);
|
|
599
|
-
// ν둬ννΈλ
|
|
600
|
-
|
|
619
|
+
// -pμ ν둬ννΈλ 맨 λμ β ν°λ―Έλ ν
μ€νΈμμ κ²μ¦λ μμ
|
|
620
|
+
// `--` ꡬλΆμλ‘ `-`λ‘ μμνλ ν둬ννΈλ μ΅μ
μΌλ‘ μ€ν΄ μ ν¨
|
|
621
|
+
args.push("-p", "--", prompt);
|
|
601
622
|
|
|
602
623
|
const child = spawn(cfg.claudeBin || "claude", args, {
|
|
603
624
|
cwd: cfg.projectDir,
|
|
@@ -625,7 +646,8 @@ function runClaude(prompt, sessionId, opts = {}) {
|
|
|
625
646
|
const text = j.is_error ? classifyClaudeError(rawErr, code) : (rawErr || "(empty response)");
|
|
626
647
|
const resetAt = j.is_error ? parseResetTime(rawErr) : null;
|
|
627
648
|
const canFallback = j.is_error && isFallbackError(rawErr, code);
|
|
628
|
-
|
|
649
|
+
const cacheTokens = j.usage?.cache_read_input_tokens || 0;
|
|
650
|
+
resolve({ ok: !j.is_error, text, sessionId: j.session_id, cost: j.total_cost_usd, cacheTokens, resetAt, canFallback });
|
|
629
651
|
} catch {
|
|
630
652
|
const raw = (err || out || "no output").slice(0, 3500);
|
|
631
653
|
resolve({ ok: false, text: classifyClaudeError(raw, code), resetAt: parseResetTime(raw), canFallback: isFallbackError(raw, code) });
|
|
@@ -1125,6 +1147,22 @@ async function handle(msg) {
|
|
|
1125
1147
|
return;
|
|
1126
1148
|
}
|
|
1127
1149
|
|
|
1150
|
+
// 컀μ€ν
λͺ
λ Ήμ΄ (config.commands) β Claudeμ λ
립 μ€ν
|
|
1151
|
+
if (text.startsWith("/")) {
|
|
1152
|
+
const cmdName = text.slice(1).split(" ")[0];
|
|
1153
|
+
const def = (cfg.commands || {})[cmdName];
|
|
1154
|
+
if (def) {
|
|
1155
|
+
const run = typeof def === "object" ? def.run : null;
|
|
1156
|
+
if (run) {
|
|
1157
|
+
const args = text.length > cmdName.length + 1 ? text.slice(cmdName.length + 2) : "";
|
|
1158
|
+
const res = await runCustomCommand(run, args || undefined);
|
|
1159
|
+
const out = res.text.length > 4000 ? res.text.slice(0, 3990) + "\nβ¦(truncated)" : res.text;
|
|
1160
|
+
await send(chatId, `${res.ok ? "" : "β οΈ "}${out}`);
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1128
1166
|
if (busy) {
|
|
1129
1167
|
msgQueue.push({ msg, receivedAt: Date.now() });
|
|
1130
1168
|
await send(chatId, t(l, "queued", msgQueue.length));
|
|
@@ -1214,6 +1252,15 @@ async function handle(msg) {
|
|
|
1214
1252
|
} else {
|
|
1215
1253
|
const footer = `\n\nβ ${secs}s${res.cost ? ` Β· $${res.cost.toFixed(4)}` : ""}`;
|
|
1216
1254
|
if (!stopping) await send(chatId, res.text + footer);
|
|
1255
|
+
// μλ μ»΄ν©μ
: cache_read_input_tokens κ° μκ³κ° μ΄κ³Ό μ μλ /compact
|
|
1256
|
+
const compactThreshold = cfg.autoCompactThreshold ?? 100000;
|
|
1257
|
+
if (compactThreshold > 0 && res.cacheTokens > compactThreshold && state.sessionId && !stopping) {
|
|
1258
|
+
try {
|
|
1259
|
+
const cr = await runClaude("/compact", state.sessionId);
|
|
1260
|
+
if (cr.sessionId) { state.sessionId = cr.sessionId; saveState(state); }
|
|
1261
|
+
if (cr.ok !== false) await send(chatId, t(l, "autoCompact"));
|
|
1262
|
+
} catch {}
|
|
1263
|
+
}
|
|
1217
1264
|
}
|
|
1218
1265
|
} catch (e) {
|
|
1219
1266
|
if (!stopping) await send(chatId, t(l, "botError", e.message));
|
|
@@ -1274,9 +1321,14 @@ async function main() {
|
|
|
1274
1321
|
}
|
|
1275
1322
|
// ν
λ κ·Έλ¨ λͺ
λ Ήμ΄ μλμμ±(/ μ
λ ₯ μ λ¨λ λ©λ΄) λ±λ‘. μ§μ νμ±κ³Ό λ³κ°λ‘ ν λ² μλ €μ€μΌ ν¨.
|
|
1276
1323
|
// κΈ°λ³Έ λͺ©λ‘(BOT_LANG) + νκ΅μ΄ λ³ν(language_code: ko) β ko ν΄λΌμ΄μΈνΈλ νκ΅μ΄, κ·Έ μΈ κΈ°λ³Έ.
|
|
1277
|
-
|
|
1324
|
+
// config.commands μ μ μλ 컀μ€ν
λͺ
λ Ήμ΄λ λͺ©λ‘μ μΆκ°.
|
|
1325
|
+
const customCmdEntries = Object.entries(cfg.commands || {}).map(([name, def]) => ({
|
|
1326
|
+
command: name,
|
|
1327
|
+
description: (typeof def === "object" ? (def.description || name) : name).slice(0, 256),
|
|
1328
|
+
}));
|
|
1329
|
+
tg("setMyCommands", { commands: [...(COMMANDS[BOT_LANG] || COMMANDS.en), ...customCmdEntries] }).catch(() => {});
|
|
1278
1330
|
if (!FORCE_LANG) {
|
|
1279
|
-
tg("setMyCommands", { commands: COMMANDS.ko, language_code: "ko" }).catch(() => {});
|
|
1331
|
+
tg("setMyCommands", { commands: [...COMMANDS.ko, ...customCmdEntries], language_code: "ko" }).catch(() => {});
|
|
1280
1332
|
}
|
|
1281
1333
|
|
|
1282
1334
|
// μμ μ λ°λ¦° λ©μμ§ κ±΄λλ°κΈ°
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-telegram-bot",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.34",
|
|
4
4
|
"description": "Drive Claude Code from Telegram β messages run headless `claude -p` in a project dir and replies come back to the chat. Zero dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|