cc-claw 0.29.2 → 0.29.3
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/dist/cli.js +253 -75
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var VERSION;
|
|
|
33
33
|
var init_version = __esm({
|
|
34
34
|
"src/version.ts"() {
|
|
35
35
|
"use strict";
|
|
36
|
-
VERSION = true ? "0.29.
|
|
36
|
+
VERSION = true ? "0.29.3" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -2813,6 +2813,7 @@ __export(chat_settings_exports, {
|
|
|
2813
2813
|
GLOBAL_SUMMARIZER_SENTINEL: () => GLOBAL_SUMMARIZER_SENTINEL,
|
|
2814
2814
|
clearAgentMode: () => clearAgentMode,
|
|
2815
2815
|
clearAllPaidSlots: () => clearAllPaidSlots,
|
|
2816
|
+
clearAllSummarizerOverrides: () => clearAllSummarizerOverrides,
|
|
2816
2817
|
clearChatPaidSlots: () => clearChatPaidSlots,
|
|
2817
2818
|
clearCwd: () => clearCwd,
|
|
2818
2819
|
clearExecMode: () => clearExecMode,
|
|
@@ -2820,6 +2821,7 @@ __export(chat_settings_exports, {
|
|
|
2820
2821
|
clearModelMap: () => clearModelMap,
|
|
2821
2822
|
clearSummarizer: () => clearSummarizer,
|
|
2822
2823
|
clearThinkingLevel: () => clearThinkingLevel,
|
|
2824
|
+
countSummarizerOverrides: () => countSummarizerOverrides,
|
|
2823
2825
|
deleteBookmark: () => deleteBookmark,
|
|
2824
2826
|
determineEscalationTarget: () => determineEscalationTarget,
|
|
2825
2827
|
findBookmarksByPrefix: () => findBookmarksByPrefix,
|
|
@@ -2840,6 +2842,7 @@ __export(chat_settings_exports, {
|
|
|
2840
2842
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
2841
2843
|
getSkillSuggestionsEnabled: () => getSkillSuggestionsEnabled,
|
|
2842
2844
|
getSummarizer: () => getSummarizer,
|
|
2845
|
+
getSummarizerWithSource: () => getSummarizerWithSource,
|
|
2843
2846
|
getThinkingLevel: () => getThinkingLevel,
|
|
2844
2847
|
getToolsMap: () => getToolsMap,
|
|
2845
2848
|
getVerboseLevel: () => getVerboseLevel,
|
|
@@ -3184,6 +3187,35 @@ function setSummarizer(chatId, backend2, model2) {
|
|
|
3184
3187
|
function clearSummarizer(chatId) {
|
|
3185
3188
|
getDb().prepare("DELETE FROM chat_summarizer WHERE chat_id = ?").run(chatId);
|
|
3186
3189
|
}
|
|
3190
|
+
function clearAllSummarizerOverrides() {
|
|
3191
|
+
const result = getDb().prepare(
|
|
3192
|
+
"DELETE FROM chat_summarizer WHERE chat_id != ?"
|
|
3193
|
+
).run(GLOBAL_SUMMARIZER_SENTINEL);
|
|
3194
|
+
return result.changes;
|
|
3195
|
+
}
|
|
3196
|
+
function getSummarizerWithSource(chatId) {
|
|
3197
|
+
const perChat = getDb().prepare(
|
|
3198
|
+
"SELECT backend, model FROM chat_summarizer WHERE chat_id = ?"
|
|
3199
|
+
).get(chatId);
|
|
3200
|
+
const globalRow = getDb().prepare(
|
|
3201
|
+
"SELECT backend, model FROM chat_summarizer WHERE chat_id = ?"
|
|
3202
|
+
).get(GLOBAL_SUMMARIZER_SENTINEL);
|
|
3203
|
+
const hasPerChat = perChat && (perChat.backend || perChat.model);
|
|
3204
|
+
const globalConfig = globalRow && (globalRow.backend || globalRow.model) ? globalRow : { backend: null, model: null };
|
|
3205
|
+
if (hasPerChat) {
|
|
3206
|
+
return { config: perChat, source: "per-chat", globalConfig };
|
|
3207
|
+
}
|
|
3208
|
+
if (globalConfig.backend || globalConfig.model) {
|
|
3209
|
+
return { config: globalConfig, source: "global", globalConfig };
|
|
3210
|
+
}
|
|
3211
|
+
return { config: { backend: null, model: null }, source: "auto", globalConfig };
|
|
3212
|
+
}
|
|
3213
|
+
function countSummarizerOverrides() {
|
|
3214
|
+
const row = getDb().prepare(
|
|
3215
|
+
"SELECT COUNT(*) as cnt FROM chat_summarizer WHERE chat_id != ?"
|
|
3216
|
+
).get(GLOBAL_SUMMARIZER_SENTINEL);
|
|
3217
|
+
return row.cnt;
|
|
3218
|
+
}
|
|
3187
3219
|
function getAgentMode(chatId) {
|
|
3188
3220
|
const row = getDb().prepare("SELECT mode FROM chat_agent_mode WHERE chat_id = ?").get(chatId);
|
|
3189
3221
|
return row?.mode ?? "auto";
|
|
@@ -3325,7 +3357,7 @@ function getUsage(chatId) {
|
|
|
3325
3357
|
}
|
|
3326
3358
|
function addUsage(chatId, input, output2, cacheRead, model2, backend2, contextSize) {
|
|
3327
3359
|
const db3 = getDb();
|
|
3328
|
-
const finalContextSize = contextSize ?? input + cacheRead;
|
|
3360
|
+
const finalContextSize = contextSize === null ? 0 : contextSize ?? input + cacheRead;
|
|
3329
3361
|
db3.prepare(`
|
|
3330
3362
|
INSERT INTO chat_usage (chat_id, input_tokens, output_tokens, cache_read_tokens, request_count, last_input_tokens, last_cache_read_tokens, context_size, updated_at)
|
|
3331
3363
|
VALUES (?, ?, ?, ?, 1, ?, ?, ?, datetime('now'))
|
|
@@ -4593,6 +4625,12 @@ var init_session_log = __esm({
|
|
|
4593
4625
|
});
|
|
4594
4626
|
|
|
4595
4627
|
// src/memory/api-context.ts
|
|
4628
|
+
var api_context_exports = {};
|
|
4629
|
+
__export(api_context_exports, {
|
|
4630
|
+
buildApiMessages: () => buildApiMessages,
|
|
4631
|
+
estimateContextUsage: () => estimateContextUsage,
|
|
4632
|
+
estimateTokens: () => estimateTokens
|
|
4633
|
+
});
|
|
4596
4634
|
import { getEncoding } from "js-tiktoken";
|
|
4597
4635
|
function estimateTokens(text) {
|
|
4598
4636
|
return enc.encode(text).length;
|
|
@@ -4621,7 +4659,7 @@ async function buildApiMessages(chatId, userMessage, systemPrompt, contextWindow
|
|
|
4621
4659
|
return { role: "assistant", content: entry.text };
|
|
4622
4660
|
});
|
|
4623
4661
|
const currentUserMessage = { role: "user", content: userMessage };
|
|
4624
|
-
const tokenBudget = Math.floor(contextWindow * 0.
|
|
4662
|
+
const tokenBudget = Math.floor(contextWindow * 0.95);
|
|
4625
4663
|
const fixedMessages = [systemMessage, currentUserMessage];
|
|
4626
4664
|
const fixedTokens = fixedMessages.reduce((sum, m) => sum + enc.encode(typeof m.content === "string" ? m.content : JSON.stringify(m.content)).length, 0);
|
|
4627
4665
|
const historyBudget = tokenBudget - fixedTokens;
|
|
@@ -4637,12 +4675,30 @@ async function buildApiMessages(chatId, userMessage, systemPrompt, contextWindow
|
|
|
4637
4675
|
}
|
|
4638
4676
|
return [systemMessage, ...truncatedHistory, currentUserMessage];
|
|
4639
4677
|
}
|
|
4640
|
-
|
|
4678
|
+
function estimateContextUsage(chatId, contextWindow) {
|
|
4679
|
+
const logEntries = getLog(chatId);
|
|
4680
|
+
if (logEntries.length === 0) {
|
|
4681
|
+
estimateCache.delete(chatId);
|
|
4682
|
+
return { estimatedTokens: 0, contextWindow, percentage: 0 };
|
|
4683
|
+
}
|
|
4684
|
+
const cached = estimateCache.get(chatId);
|
|
4685
|
+
if (cached && cached.logSize === logEntries.length) {
|
|
4686
|
+
const percentage2 = contextWindow > 0 ? cached.tokens / contextWindow * 100 : 0;
|
|
4687
|
+
return { estimatedTokens: cached.tokens, contextWindow, percentage: percentage2 };
|
|
4688
|
+
}
|
|
4689
|
+
const text = logEntries.map((e) => e.text).join("\n");
|
|
4690
|
+
const estimatedTokens = estimateTokens(text);
|
|
4691
|
+
estimateCache.set(chatId, { logSize: logEntries.length, tokens: estimatedTokens });
|
|
4692
|
+
const percentage = contextWindow > 0 ? estimatedTokens / contextWindow * 100 : 0;
|
|
4693
|
+
return { estimatedTokens, contextWindow, percentage };
|
|
4694
|
+
}
|
|
4695
|
+
var enc, estimateCache;
|
|
4641
4696
|
var init_api_context = __esm({
|
|
4642
4697
|
"src/memory/api-context.ts"() {
|
|
4643
4698
|
"use strict";
|
|
4644
4699
|
init_session_log();
|
|
4645
4700
|
enc = getEncoding("cl100k_base");
|
|
4701
|
+
estimateCache = /* @__PURE__ */ new Map();
|
|
4646
4702
|
}
|
|
4647
4703
|
});
|
|
4648
4704
|
|
|
@@ -4838,6 +4894,7 @@ __export(store_exports5, {
|
|
|
4838
4894
|
clearAgentMode: () => clearAgentMode,
|
|
4839
4895
|
clearAllPaidSlots: () => clearAllPaidSlots,
|
|
4840
4896
|
clearAllSessions: () => clearAllSessions,
|
|
4897
|
+
clearAllSummarizerOverrides: () => clearAllSummarizerOverrides,
|
|
4841
4898
|
clearBackendLimit: () => clearBackendLimit,
|
|
4842
4899
|
clearChatBackendSlot: () => clearChatBackendSlot,
|
|
4843
4900
|
clearChatGeminiSlot: () => clearChatGeminiSlot,
|
|
@@ -4852,6 +4909,7 @@ __export(store_exports5, {
|
|
|
4852
4909
|
clearThinkingLevel: () => clearThinkingLevel,
|
|
4853
4910
|
clearUsage: () => clearUsage,
|
|
4854
4911
|
completeJobRun: () => completeJobRun,
|
|
4912
|
+
countSummarizerOverrides: () => countSummarizerOverrides,
|
|
4855
4913
|
deleteBookmark: () => deleteBookmark,
|
|
4856
4914
|
deleteMemoryById: () => deleteMemoryById,
|
|
4857
4915
|
deleteSessionSummary: () => deleteSessionSummary,
|
|
@@ -4923,6 +4981,7 @@ __export(store_exports5, {
|
|
|
4923
4981
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
4924
4982
|
getSkillSuggestionsEnabled: () => getSkillSuggestionsEnabled,
|
|
4925
4983
|
getSummarizer: () => getSummarizer,
|
|
4984
|
+
getSummarizerWithSource: () => getSummarizerWithSource,
|
|
4926
4985
|
getThinkingLevel: () => getThinkingLevel,
|
|
4927
4986
|
getToolsMap: () => getToolsMap,
|
|
4928
4987
|
getUnsummarizedChatIds: () => getUnsummarizedChatIds,
|
|
@@ -7581,13 +7640,14 @@ function is429(err) {
|
|
|
7581
7640
|
function sleep(ms) {
|
|
7582
7641
|
return new Promise((r) => setTimeout(r, ms));
|
|
7583
7642
|
}
|
|
7584
|
-
var PER_DM_INTERVAL_MS, PER_GROUP_INTERVAL_MS, GLOBAL_INTERVAL_MS, MAX_RETRIES2, RETRY_DELAY_MS, MAX_QUEUE_SIZE, EDIT_PRESSURE_THRESHOLD, MAX_PER_CHAT_QUEUE, MAX_TOTAL_PAUSE_MS, CIRCUIT_TRIP_THRESHOLD, CIRCUIT_TRIP_WINDOW_MS, CIRCUIT_COOLDOWN_STEP_SEC, CIRCUIT_RESET_WINDOW_MS, CircuitState, Priority, _activeThrottle, TelegramThrottle;
|
|
7643
|
+
var PER_DM_INTERVAL_MS, PER_GROUP_INTERVAL_MS, P0_PACING_MS, GLOBAL_INTERVAL_MS, MAX_RETRIES2, RETRY_DELAY_MS, MAX_QUEUE_SIZE, EDIT_PRESSURE_THRESHOLD, MAX_PER_CHAT_QUEUE, MAX_TOTAL_PAUSE_MS, CIRCUIT_TRIP_THRESHOLD, CIRCUIT_TRIP_WINDOW_MS, CIRCUIT_COOLDOWN_STEP_SEC, CIRCUIT_RESET_WINDOW_MS, CircuitState, Priority, _activeThrottle, TelegramThrottle;
|
|
7585
7644
|
var init_telegram_throttle = __esm({
|
|
7586
7645
|
"src/channels/telegram-throttle.ts"() {
|
|
7587
7646
|
"use strict";
|
|
7588
7647
|
init_log();
|
|
7589
7648
|
PER_DM_INTERVAL_MS = 1e3;
|
|
7590
7649
|
PER_GROUP_INTERVAL_MS = 3500;
|
|
7650
|
+
P0_PACING_MS = 150;
|
|
7591
7651
|
GLOBAL_INTERVAL_MS = 100;
|
|
7592
7652
|
MAX_RETRIES2 = 2;
|
|
7593
7653
|
RETRY_DELAY_MS = 1e3;
|
|
@@ -7766,16 +7826,17 @@ var init_telegram_throttle = __esm({
|
|
|
7766
7826
|
while (this.queue.length > 0) {
|
|
7767
7827
|
while (this.isPaused()) {
|
|
7768
7828
|
if (this.pauseStartedAt > 0 && Date.now() - this.pauseStartedAt > MAX_TOTAL_PAUSE_MS) {
|
|
7769
|
-
warn(`[throttle] Max pause duration exceeded (${MAX_TOTAL_PAUSE_MS / 6e4}min), dropping ${this.queue.length} items`);
|
|
7829
|
+
warn(`[throttle] Max pause duration exceeded (${MAX_TOTAL_PAUSE_MS / 6e4}min), dropping ${this.queue.length} items (pause remains until ${new Date(this.pausedUntil).toISOString()})`);
|
|
7770
7830
|
this.flushQueueWithError("Telegram rate limit exceeded max wait time");
|
|
7771
|
-
this.pausedUntil = 0;
|
|
7772
|
-
this.pauseStartedAt = 0;
|
|
7773
7831
|
break;
|
|
7774
7832
|
}
|
|
7775
7833
|
const waitMs = Math.min(this.pausedUntil - Date.now(), 5e3);
|
|
7776
7834
|
if (waitMs > 0) await sleep(waitMs);
|
|
7777
7835
|
}
|
|
7778
7836
|
if (this.queue.length === 0) break;
|
|
7837
|
+
if (!this.isPaused() && this.pauseStartedAt > 0) {
|
|
7838
|
+
this.pauseStartedAt = 0;
|
|
7839
|
+
}
|
|
7779
7840
|
this.updateCircuitState();
|
|
7780
7841
|
const item = this.selectNextItem();
|
|
7781
7842
|
if (!item) {
|
|
@@ -7783,7 +7844,8 @@ var init_telegram_throttle = __esm({
|
|
|
7783
7844
|
continue;
|
|
7784
7845
|
}
|
|
7785
7846
|
const lastChat = this.lastSendPerChat.get(item.chatId) ?? 0;
|
|
7786
|
-
const
|
|
7847
|
+
const interval = item.priority === 0 /* P0_CRITICAL */ ? P0_PACING_MS : perChatInterval(item.chatId);
|
|
7848
|
+
const chatWait = interval - (Date.now() - lastChat);
|
|
7787
7849
|
if (chatWait > 0) await sleep(chatWait);
|
|
7788
7850
|
const globalWait = GLOBAL_INTERVAL_MS - (Date.now() - this.lastGlobalSend);
|
|
7789
7851
|
if (globalWait > 0) await sleep(globalWait);
|
|
@@ -7865,6 +7927,7 @@ var init_telegram_throttle = __esm({
|
|
|
7865
7927
|
return await fn();
|
|
7866
7928
|
} catch (err) {
|
|
7867
7929
|
if (is429(err)) throw err;
|
|
7930
|
+
if (err instanceof GrammyError && err.error_code >= 400 && err.error_code < 500) throw err;
|
|
7868
7931
|
if (attempt < MAX_RETRIES2 && err instanceof GrammyError) {
|
|
7869
7932
|
warn(`[throttle] ${label2} attempt ${attempt + 1}/${MAX_RETRIES2} failed (${err.error_code}), retrying`);
|
|
7870
7933
|
await sleep(RETRY_DELAY_MS);
|
|
@@ -13382,7 +13445,7 @@ async function summarizeWithFallbackChain(chatId, targetBackendId, excludeBacken
|
|
|
13382
13445
|
const cap = getOllamaTranscriptCap(ollamaModel);
|
|
13383
13446
|
const key = `${ollamaAdapter.id}:${ollamaModel}`;
|
|
13384
13447
|
tried.add(key);
|
|
13385
|
-
const directFn = (prompt) => ollamaAdapter.streamDirect(prompt, ollamaModel);
|
|
13448
|
+
const directFn = (prompt) => ollamaAdapter.streamDirect(prompt, ollamaModel, { thinkingLevel: "off" });
|
|
13386
13449
|
const result = await attemptSummarizeDirect(chatId, directFn, "ollama", ollamaModel, entries, cap);
|
|
13387
13450
|
if (result.success) {
|
|
13388
13451
|
await extractAndLogSignals(result.rawText, chatId, "ollama", ollamaModel);
|
|
@@ -13400,7 +13463,7 @@ async function summarizeWithFallbackChain(chatId, targetBackendId, excludeBacken
|
|
|
13400
13463
|
const key = `${targetAdapter.id}:${model2}`;
|
|
13401
13464
|
if (!tried.has(key)) {
|
|
13402
13465
|
tried.add(key);
|
|
13403
|
-
const result = targetAdapter.streamDirect ? await attemptSummarizeDirect(chatId, (p) => targetAdapter.streamDirect(p, model2), targetAdapter.id, model2, entries, getTranscriptCap(model2)) : await attemptSummarize(chatId, targetAdapter, model2, entries);
|
|
13466
|
+
const result = targetAdapter.streamDirect ? await attemptSummarizeDirect(chatId, (p) => targetAdapter.streamDirect(p, model2, { thinkingLevel: "off" }), targetAdapter.id, model2, entries, getTranscriptCap(model2)) : await attemptSummarize(chatId, targetAdapter, model2, entries);
|
|
13404
13467
|
if (result.success) {
|
|
13405
13468
|
await extractAndLogSignals(result.rawText, chatId, targetAdapter.id, model2);
|
|
13406
13469
|
if (clearLogAfter) clearLog(chatId);
|
|
@@ -13418,7 +13481,7 @@ async function summarizeWithFallbackChain(chatId, targetBackendId, excludeBacken
|
|
|
13418
13481
|
const key = `${adapter.id}:${model2}`;
|
|
13419
13482
|
if (!tried.has(key)) {
|
|
13420
13483
|
tried.add(key);
|
|
13421
|
-
const result = adapter.streamDirect ? await attemptSummarizeDirect(chatId, (p) => adapter.streamDirect(p, model2), adapter.id, model2, entries, adapter.id === "ollama" ? getOllamaTranscriptCap(model2) : getTranscriptCap(model2)) : await attemptSummarize(chatId, adapter, model2, entries);
|
|
13484
|
+
const result = adapter.streamDirect ? await attemptSummarizeDirect(chatId, (p) => adapter.streamDirect(p, model2, { thinkingLevel: "off" }), adapter.id, model2, entries, adapter.id === "ollama" ? getOllamaTranscriptCap(model2) : getTranscriptCap(model2)) : await attemptSummarize(chatId, adapter, model2, entries);
|
|
13422
13485
|
if (result.success) {
|
|
13423
13486
|
await extractAndLogSignals(result.rawText, chatId, adapter.id, model2);
|
|
13424
13487
|
if (clearLogAfter) clearLog(chatId);
|
|
@@ -13440,7 +13503,7 @@ async function summarizeWithFallbackChain(chatId, targetBackendId, excludeBacken
|
|
|
13440
13503
|
let result;
|
|
13441
13504
|
if (adapter.streamDirect) {
|
|
13442
13505
|
const cap = adapter.id === "ollama" ? getOllamaTranscriptCap(model2) : getTranscriptCap(model2);
|
|
13443
|
-
const directFn = (prompt) => adapter.streamDirect(prompt, model2);
|
|
13506
|
+
const directFn = (prompt) => adapter.streamDirect(prompt, model2, { thinkingLevel: "off" });
|
|
13444
13507
|
result = await attemptSummarizeDirect(chatId, directFn, adapter.id, model2, entries, cap);
|
|
13445
13508
|
} else {
|
|
13446
13509
|
result = await attemptSummarize(chatId, adapter, model2, entries);
|
|
@@ -13953,6 +14016,17 @@ function killProcessGroup(proc, signal = "SIGTERM") {
|
|
|
13953
14016
|
}
|
|
13954
14017
|
}
|
|
13955
14018
|
}
|
|
14019
|
+
function runCompaction(chatId, reason, onCompaction) {
|
|
14020
|
+
return summarizeWithFallbackChain(chatId).then((saved) => {
|
|
14021
|
+
if (saved) {
|
|
14022
|
+
clearSession(chatId);
|
|
14023
|
+
clearUsage(chatId);
|
|
14024
|
+
onCompaction?.(chatId);
|
|
14025
|
+
}
|
|
14026
|
+
}).catch((err) => {
|
|
14027
|
+
warn(`[agent] Compaction failed for ${chatId} (${reason}): ${err}`);
|
|
14028
|
+
});
|
|
14029
|
+
}
|
|
13956
14030
|
function sweepStaleChatEntries() {
|
|
13957
14031
|
for (const [chatId, state] of activeChats) {
|
|
13958
14032
|
if (state.process && state.process.exitCode !== null) {
|
|
@@ -14228,7 +14302,6 @@ function spawnQuery(adapter, config2, model2, cancelState, thinkingLevel, timeou
|
|
|
14228
14302
|
input += ev.usage.input;
|
|
14229
14303
|
output2 += ev.usage.output;
|
|
14230
14304
|
cacheRead += ev.usage.cacheRead;
|
|
14231
|
-
contextSize = ev.usage.input + (ev.usage.cacheRead ?? 0);
|
|
14232
14305
|
}
|
|
14233
14306
|
break;
|
|
14234
14307
|
case "result":
|
|
@@ -14246,7 +14319,6 @@ function spawnQuery(adapter, config2, model2, cancelState, thinkingLevel, timeou
|
|
|
14246
14319
|
input = ev.usage.input;
|
|
14247
14320
|
output2 = ev.usage.output;
|
|
14248
14321
|
cacheRead = ev.usage.cacheRead;
|
|
14249
|
-
contextSize = ev.usage.input + (ev.usage.cacheRead ?? 0);
|
|
14250
14322
|
}
|
|
14251
14323
|
if (adapter.shouldKillOnResult()) {
|
|
14252
14324
|
try {
|
|
@@ -14329,7 +14401,7 @@ Partial output: ${accumulatedText.slice(-500)}`;
|
|
|
14329
14401
|
return;
|
|
14330
14402
|
}
|
|
14331
14403
|
const cleanedResult = stripThinkingContent(resultText || accumulatedText);
|
|
14332
|
-
resolve3({ resultText: cleanedResult, thinkingText: accumulatedThinking, sessionId, input, output: output2, cacheRead, contextSize, sawToolEvents, sawResultEvent });
|
|
14404
|
+
resolve3({ resultText: cleanedResult, thinkingText: accumulatedThinking, sessionId, input, output: output2, cacheRead, contextSize: null, sawToolEvents, sawResultEvent });
|
|
14333
14405
|
});
|
|
14334
14406
|
});
|
|
14335
14407
|
}
|
|
@@ -14548,9 +14620,12 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
14548
14620
|
activeChats.set(chatId, cancelState2);
|
|
14549
14621
|
try {
|
|
14550
14622
|
let messageHistory;
|
|
14623
|
+
let apiContextSize;
|
|
14551
14624
|
if (adapter.type === "api") {
|
|
14552
14625
|
const contextWindow = adapter.contextWindow[resolvedModel2] ?? 8192;
|
|
14553
|
-
|
|
14626
|
+
const { buildApiMessages: buildMsgs, estimateContextUsage: estimateContextUsage2 } = await Promise.resolve().then(() => (init_api_context(), api_context_exports));
|
|
14627
|
+
messageHistory = await buildMsgs(chatId, userMessage, fullPrompt, contextWindow);
|
|
14628
|
+
apiContextSize = estimateContextUsage2(chatId, contextWindow).estimatedTokens;
|
|
14554
14629
|
}
|
|
14555
14630
|
const sdResult = await adapter.streamDirect(fullPrompt, resolvedModel2, {
|
|
14556
14631
|
timeoutMs: timeoutMs ?? 3e5,
|
|
@@ -14566,23 +14641,29 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
14566
14641
|
});
|
|
14567
14642
|
if (!isSyntheticChatId(chatId)) {
|
|
14568
14643
|
appendToLog(chatId, userMessage, sdResult.text, adapter.id, resolvedModel2, null);
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14644
|
+
if (apiContextSize && adapter.type === "api" && !compactionInFlight.has(chatId)) {
|
|
14645
|
+
const contextWindow = adapter.contextWindow[resolvedModel2] ?? 8192;
|
|
14646
|
+
const contextPct = apiContextSize / contextWindow * 100;
|
|
14647
|
+
if (contextPct >= 85) {
|
|
14648
|
+
compactionInFlight.add(chatId);
|
|
14649
|
+
log(`[agent] Context at ${contextPct.toFixed(0)}% for ${chatId} \u2014 triggering background compaction`);
|
|
14650
|
+
opts?.onCompaction?.(chatId, "triggered");
|
|
14651
|
+
runCompaction(chatId, "context-85%", opts?.onCompaction).finally(() => {
|
|
14652
|
+
compactionInFlight.delete(chatId);
|
|
14653
|
+
});
|
|
14654
|
+
}
|
|
14655
|
+
}
|
|
14656
|
+
if (adapter.type !== "api" || !compactionInFlight.has(chatId)) {
|
|
14657
|
+
const pairCount = profile !== "chat" ? getMessagePairCount(chatId) : 0;
|
|
14658
|
+
if (pairCount >= 30) {
|
|
14659
|
+
log(`[agent] Auto-summarizing chat ${chatId} after ${pairCount} turns`);
|
|
14660
|
+
runCompaction(chatId, "30-pair-threshold", opts?.onCompaction);
|
|
14661
|
+
}
|
|
14581
14662
|
}
|
|
14582
14663
|
}
|
|
14583
14664
|
const sdUsage = sdResult.usage ?? { input: 0, output: 0 };
|
|
14584
14665
|
if (sdUsage.input + sdUsage.output > 0) {
|
|
14585
|
-
addUsage(chatId, sdUsage.input, sdUsage.output, 0, resolvedModel2);
|
|
14666
|
+
addUsage(chatId, sdUsage.input, sdUsage.output, 0, resolvedModel2, adapter.id, apiContextSize);
|
|
14586
14667
|
}
|
|
14587
14668
|
if (cancelState2.cancelled) {
|
|
14588
14669
|
return { text: "Stopped.", usage: { input: sdUsage.input, output: sdUsage.output, cacheRead: 0 } };
|
|
@@ -14884,18 +14965,10 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
14884
14965
|
}
|
|
14885
14966
|
if (result.resultText && !isSyntheticChatId(chatId)) {
|
|
14886
14967
|
appendToLog(chatId, userMessage, result.resultText, adapter.id, model2 ?? null, result.sessionId ?? null);
|
|
14887
|
-
const AUTO_SUMMARIZE_THRESHOLD = 30;
|
|
14888
14968
|
const pairCount = profile !== "chat" ? getMessagePairCount(chatId) : 0;
|
|
14889
|
-
if (pairCount >=
|
|
14969
|
+
if (pairCount >= 30) {
|
|
14890
14970
|
log(`[agent] Auto-summarizing chat ${chatId} after ${pairCount} turns`);
|
|
14891
|
-
|
|
14892
|
-
if (saved) {
|
|
14893
|
-
clearSession(chatId);
|
|
14894
|
-
opts?.onCompaction?.(chatId);
|
|
14895
|
-
}
|
|
14896
|
-
}).catch((err) => {
|
|
14897
|
-
warn(`[agent] Auto-summarize failed for chat ${chatId}: ${err}`);
|
|
14898
|
-
});
|
|
14971
|
+
runCompaction(chatId, "30-pair-threshold", opts?.onCompaction);
|
|
14899
14972
|
}
|
|
14900
14973
|
}
|
|
14901
14974
|
return {
|
|
@@ -14923,7 +14996,7 @@ function injectMcpConfig(adapterId, args, mcpConfigPath) {
|
|
|
14923
14996
|
if (!flag) return args;
|
|
14924
14997
|
return [...args, ...flag, mcpConfigPath, "--strict-mcp-config"];
|
|
14925
14998
|
}
|
|
14926
|
-
var activeChats, staleSweepTimer, chatLocks, SPAWN_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_MS, CONTENT_SILENCE_TIMEOUT_MS, CONTENT_SILENCE_TIMEOUT_ERROR, FIRST_RESPONSE_TIMEOUT_ERROR, FREE_SLOTS_EXHAUSTED, GEMINI_FALLBACK_CHAIN, GEMINI_DOWNGRADE_MODELS, MCP_CONFIG_FLAG;
|
|
14999
|
+
var activeChats, compactionInFlight, staleSweepTimer, chatLocks, SPAWN_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_MS, CONTENT_SILENCE_TIMEOUT_MS, CONTENT_SILENCE_TIMEOUT_ERROR, FIRST_RESPONSE_TIMEOUT_ERROR, FREE_SLOTS_EXHAUSTED, GEMINI_FALLBACK_CHAIN, GEMINI_DOWNGRADE_MODELS, MCP_CONFIG_FLAG;
|
|
14927
15000
|
var init_agent = __esm({
|
|
14928
15001
|
"src/agent.ts"() {
|
|
14929
15002
|
"use strict";
|
|
@@ -14940,7 +15013,6 @@ var init_agent = __esm({
|
|
|
14940
15013
|
init_strip_thinking();
|
|
14941
15014
|
init_text_utils();
|
|
14942
15015
|
init_session_log();
|
|
14943
|
-
init_api_context();
|
|
14944
15016
|
init_summarize();
|
|
14945
15017
|
init_quota();
|
|
14946
15018
|
init_store5();
|
|
@@ -14951,6 +15023,7 @@ var init_agent = __esm({
|
|
|
14951
15023
|
init_unified_config();
|
|
14952
15024
|
init_mcp_config();
|
|
14953
15025
|
activeChats = /* @__PURE__ */ new Map();
|
|
15026
|
+
compactionInFlight = /* @__PURE__ */ new Set();
|
|
14954
15027
|
chatLocks = /* @__PURE__ */ new Map();
|
|
14955
15028
|
SPAWN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
14956
15029
|
FIRST_RESPONSE_TIMEOUT_MS = parseInt(process.env.GEMINI_FIRST_RESPONSE_TIMEOUT_MS ?? "30000", 10);
|
|
@@ -15118,7 +15191,9 @@ async function runWeeklySweep(chatId, channel, backendId, model2) {
|
|
|
15118
15191
|
buttons.push([{ label: "Review Now", data: "mem:opt:start", style: "success" }]);
|
|
15119
15192
|
}
|
|
15120
15193
|
buttons.push([{ label: "Dismiss", data: "mem:sweep:dismiss" }]);
|
|
15121
|
-
|
|
15194
|
+
if (channel) {
|
|
15195
|
+
await sendOrEditKeyboard(chatId, channel, void 0, lines.join("\n"), buttons);
|
|
15196
|
+
}
|
|
15122
15197
|
return { suggestionsCount, cleanedUp };
|
|
15123
15198
|
} catch (err) {
|
|
15124
15199
|
const msg = errorMessage(err);
|
|
@@ -22603,6 +22678,7 @@ var init_ollama2 = __esm({
|
|
|
22603
22678
|
async streamDirect(prompt, model2, opts) {
|
|
22604
22679
|
const cleanPrompt = stripForLocalModel(prompt);
|
|
22605
22680
|
let disableThinking = false;
|
|
22681
|
+
let modelContextWindow;
|
|
22606
22682
|
try {
|
|
22607
22683
|
const { OllamaStore } = (init_ollama(), __toCommonJS(ollama_exports));
|
|
22608
22684
|
const modelRecord = OllamaStore.getModelByName(model2);
|
|
@@ -22611,8 +22687,14 @@ var init_ollama2 = __esm({
|
|
|
22611
22687
|
} else if (opts?.thinkingLevel === "off") {
|
|
22612
22688
|
disableThinking = true;
|
|
22613
22689
|
}
|
|
22690
|
+
if (modelRecord?.contextWindow && modelRecord.contextWindow > 4096) {
|
|
22691
|
+
modelContextWindow = modelRecord.contextWindow;
|
|
22692
|
+
}
|
|
22614
22693
|
} catch {
|
|
22615
22694
|
}
|
|
22695
|
+
const ollamaProviderOpts = {};
|
|
22696
|
+
if (disableThinking) ollamaProviderOpts.think = false;
|
|
22697
|
+
if (modelContextWindow) ollamaProviderOpts.num_ctx = modelContextWindow;
|
|
22616
22698
|
const apiOpts = {
|
|
22617
22699
|
timeoutMs: opts?.timeoutMs,
|
|
22618
22700
|
onStream: opts?.onStream,
|
|
@@ -22621,7 +22703,7 @@ var init_ollama2 = __esm({
|
|
|
22621
22703
|
permMode: opts?.permMode,
|
|
22622
22704
|
thinkingLevel: opts?.thinkingLevel,
|
|
22623
22705
|
onThinking: opts?.onThinking,
|
|
22624
|
-
...
|
|
22706
|
+
...Object.keys(ollamaProviderOpts).length > 0 ? { providerOptions: { ollama: ollamaProviderOpts } } : {}
|
|
22625
22707
|
};
|
|
22626
22708
|
const result = await this.streamDirectWithHistory(
|
|
22627
22709
|
cleanPrompt,
|
|
@@ -22707,7 +22789,28 @@ var init_openrouter = __esm({
|
|
|
22707
22789
|
}
|
|
22708
22790
|
summarizerModel = DEFAULT_FREE_MODEL;
|
|
22709
22791
|
pricing = {};
|
|
22710
|
-
|
|
22792
|
+
_contextWindowCache = null;
|
|
22793
|
+
_contextWindowCacheSize = 0;
|
|
22794
|
+
get contextWindow() {
|
|
22795
|
+
try {
|
|
22796
|
+
const { getApiModels: getApiModels2 } = (init_api_models(), __toCommonJS(api_models_exports));
|
|
22797
|
+
const models = getApiModels2("openrouter");
|
|
22798
|
+
if (this._contextWindowCache && models.length === this._contextWindowCacheSize) {
|
|
22799
|
+
return this._contextWindowCache;
|
|
22800
|
+
}
|
|
22801
|
+
const result = {};
|
|
22802
|
+
for (const m of models) {
|
|
22803
|
+
if (m.contextWindow) {
|
|
22804
|
+
result[m.modelId] = m.contextWindow;
|
|
22805
|
+
}
|
|
22806
|
+
}
|
|
22807
|
+
this._contextWindowCache = result;
|
|
22808
|
+
this._contextWindowCacheSize = models.length;
|
|
22809
|
+
return result;
|
|
22810
|
+
} catch {
|
|
22811
|
+
return {};
|
|
22812
|
+
}
|
|
22813
|
+
}
|
|
22711
22814
|
// ── Vercel AI SDK provider ────────────────────────────────────────
|
|
22712
22815
|
/**
|
|
22713
22816
|
* Create the Vercel AI SDK LanguageModel for a given model ID.
|
|
@@ -24806,6 +24909,7 @@ var init_live_status = __esm({
|
|
|
24806
24909
|
/** Spinner frame counter — advances on each flush for animation. */
|
|
24807
24910
|
spinnerFrame = 0;
|
|
24808
24911
|
/** Timestamp of last successful edit — used for heartbeat force-through. */
|
|
24912
|
+
lastSuccessfulFlushAt = 0;
|
|
24809
24913
|
/** Callback to restart typing indicator as fallback. */
|
|
24810
24914
|
onTypingFallback;
|
|
24811
24915
|
/** Set a callback that restarts the typing indicator loop as a fallback. */
|
|
@@ -29358,6 +29462,7 @@ async function handleNewchatCommand(chatId, commandArgs, msg, channel) {
|
|
|
29358
29462
|
const summarized = await summarizeSession(chatId);
|
|
29359
29463
|
clearSession(chatId);
|
|
29360
29464
|
clearChatPaidSlots(chatId);
|
|
29465
|
+
clearUsage(chatId);
|
|
29361
29466
|
setSessionStartedAt(chatId);
|
|
29362
29467
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "New session started", detail: { field: "session", action: "reset", summarized } });
|
|
29363
29468
|
if (typeof channel.sendKeyboard === "function" && oldSessionId) {
|
|
@@ -29411,6 +29516,7 @@ async function handleClearCommand(chatId, _commandArgs, _msg, channel) {
|
|
|
29411
29516
|
stopAllSideQuests(chatId);
|
|
29412
29517
|
clearSession(chatId);
|
|
29413
29518
|
clearChatPaidSlots(chatId);
|
|
29519
|
+
clearUsage(chatId);
|
|
29414
29520
|
setSessionStartedAt(chatId);
|
|
29415
29521
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "Session cleared (no summary)", detail: { field: "session", action: "clear" } });
|
|
29416
29522
|
await channel.sendText(chatId, "\u{1F9FD} Session cleared. No summary saved.", { parseMode: "plain", priority: 0 /* P0_CRITICAL */ });
|
|
@@ -29487,6 +29593,17 @@ async function handleSummarizeCommand(chatId, commandArgs, msg, channel) {
|
|
|
29487
29593
|
}
|
|
29488
29594
|
}
|
|
29489
29595
|
}
|
|
29596
|
+
function formatSummarizerLabel(backend2, model2, fallbackModel) {
|
|
29597
|
+
if (backend2 === "off") return "Off";
|
|
29598
|
+
if (backend2) return `${backend2}: ${model2 ?? "default"}`;
|
|
29599
|
+
return `Auto (${fallbackModel ?? "default"})`;
|
|
29600
|
+
}
|
|
29601
|
+
function summarizerStatusLine(chatId, adapter) {
|
|
29602
|
+
const { config: config2, source } = getSummarizerWithSource(chatId);
|
|
29603
|
+
const label2 = formatSummarizerLabel(config2.backend, config2.model, adapter?.summarizerModel);
|
|
29604
|
+
if (source === "auto") return label2.toLowerCase();
|
|
29605
|
+
return `${label2} (${source === "global" ? "global" : "per-chat"})`;
|
|
29606
|
+
}
|
|
29490
29607
|
async function handleStatusCommand(chatId, commandArgs, msg, channel) {
|
|
29491
29608
|
const sessionId = getSessionId(chatId);
|
|
29492
29609
|
const cwd = getCwd(chatId);
|
|
@@ -29503,12 +29620,21 @@ async function handleStatusCommand(chatId, commandArgs, msg, channel) {
|
|
|
29503
29620
|
const thinking2 = getThinkingLevel(chatId);
|
|
29504
29621
|
const mode = getMode(chatId);
|
|
29505
29622
|
const modelSig = getModelSignature(chatId);
|
|
29506
|
-
|
|
29507
|
-
|
|
29508
|
-
|
|
29509
|
-
|
|
29510
|
-
|
|
29511
|
-
|
|
29623
|
+
let contextLine;
|
|
29624
|
+
if (adapter?.type === "api") {
|
|
29625
|
+
const { estimateContextUsage: estimateContextUsage2 } = await Promise.resolve().then(() => (init_api_context(), api_context_exports));
|
|
29626
|
+
const contextMax = adapter.contextWindow[model2] ?? 8192;
|
|
29627
|
+
const ctxEst = estimateContextUsage2(chatId, contextMax);
|
|
29628
|
+
const ctxBar = buildBar(ctxEst.percentage);
|
|
29629
|
+
const usedK = (ctxEst.estimatedTokens / 1e3).toFixed(1);
|
|
29630
|
+
const maxK = (contextMax / 1e3).toFixed(0);
|
|
29631
|
+
contextLine = `\u{1F4D0} Context: ${ctxBar} ${usedK}K/${maxK}K (${ctxEst.percentage.toFixed(1)}%) \xB7 compacts at 85%`;
|
|
29632
|
+
} else {
|
|
29633
|
+
const pairCount = getMessagePairCount(chatId);
|
|
29634
|
+
const threshold = 30;
|
|
29635
|
+
const remaining = Math.max(0, threshold - pairCount);
|
|
29636
|
+
contextLine = `\u{1F4D0} Session: ${pairCount}/${threshold} messages \xB7 compacts in ${remaining}`;
|
|
29637
|
+
}
|
|
29512
29638
|
const bootRow = getDb().prepare("SELECT value FROM meta WHERE key = 'boot_time'").get();
|
|
29513
29639
|
let uptimeStr = "unknown";
|
|
29514
29640
|
if (bootRow) {
|
|
@@ -29571,11 +29697,12 @@ async function handleStatusCommand(chatId, commandArgs, msg, channel) {
|
|
|
29571
29697
|
`\u{1F4AD} Think: ${thinking2} \xB7 Mode: ${mode}`,
|
|
29572
29698
|
`\u{1F916} Agents: ${getAgentMode(chatId)}`,
|
|
29573
29699
|
`\u{1F507} Voice: ${voice2 ? "on" : "off"} \xB7 Sig: ${modelSig}`,
|
|
29700
|
+
`\u{1F4DD} Summarizer: ${summarizerStatusLine(chatId, adapter)}`,
|
|
29574
29701
|
``,
|
|
29575
29702
|
buildSectionHeader("Session"),
|
|
29576
29703
|
`\u{1F4CB} ${sessionId ?? "no active session"}`,
|
|
29577
29704
|
`\u{1F4C1} ${cwd ?? "default workspace"}`,
|
|
29578
|
-
|
|
29705
|
+
contextLine,
|
|
29579
29706
|
...sqCount > 0 ? [`\u{1F5FA} Side quests: ${sqCount} active`] : [],
|
|
29580
29707
|
``,
|
|
29581
29708
|
buildSectionHeader("Usage"),
|
|
@@ -29986,8 +30113,17 @@ async function handleSummarizerCommand(chatId, commandArgs, msg, channel) {
|
|
|
29986
30113
|
} catch {
|
|
29987
30114
|
adapter = null;
|
|
29988
30115
|
}
|
|
29989
|
-
const current =
|
|
29990
|
-
const
|
|
30116
|
+
const { config: current, source, globalConfig } = getSummarizerWithSource(chatId);
|
|
30117
|
+
const overrideCount = countSummarizerOverrides();
|
|
30118
|
+
const currentLabel = formatSummarizerLabel(current.backend, current.model, adapter?.summarizerModel);
|
|
30119
|
+
const sourceTag = source === "per-chat" ? "per-chat override" : source === "global" ? "global default" : "auto";
|
|
30120
|
+
const headerLines = [`Summarizer: ${currentLabel} (${sourceTag})`];
|
|
30121
|
+
if (globalConfig.backend) {
|
|
30122
|
+
headerLines.push(`Global default: ${formatSummarizerLabel(globalConfig.backend, globalConfig.model)}`);
|
|
30123
|
+
}
|
|
30124
|
+
if (overrideCount > 0) {
|
|
30125
|
+
headerLines.push(`${overrideCount} chat${overrideCount === 1 ? "" : "s"} with per-chat overrides`);
|
|
30126
|
+
}
|
|
29991
30127
|
if (typeof channel.sendKeyboard === "function") {
|
|
29992
30128
|
const isAuto = !current.backend && current.backend !== "off";
|
|
29993
30129
|
const isOff = current.backend === "off";
|
|
@@ -30035,7 +30171,14 @@ async function handleSummarizerCommand(chatId, commandArgs, msg, channel) {
|
|
|
30035
30171
|
}]);
|
|
30036
30172
|
}
|
|
30037
30173
|
}
|
|
30038
|
-
|
|
30174
|
+
if (overrideCount > 0) {
|
|
30175
|
+
buttons.push([{
|
|
30176
|
+
label: `Clear All Overrides (${overrideCount})`,
|
|
30177
|
+
data: "summarizer:clearall",
|
|
30178
|
+
style: "danger"
|
|
30179
|
+
}]);
|
|
30180
|
+
}
|
|
30181
|
+
await channel.sendKeyboard(chatId, headerLines.join("\n"), buttons);
|
|
30039
30182
|
} else {
|
|
30040
30183
|
await channel.sendText(chatId, `Summarizer: ${currentLabel}
|
|
30041
30184
|
|
|
@@ -31558,14 +31701,40 @@ ${value ? "Full tool inputs/results will be saved to ~/.cc-claw/logs/sessions/"
|
|
|
31558
31701
|
if (rest === "auto") {
|
|
31559
31702
|
clearSummarizer(chatId);
|
|
31560
31703
|
await channel.sendText(chatId, "Summarizer set to auto (uses active backend).", { parseMode: "plain" });
|
|
31561
|
-
} else if (rest === "
|
|
31562
|
-
|
|
31563
|
-
await channel.sendText(chatId, "
|
|
31704
|
+
} else if (rest === "clearall") {
|
|
31705
|
+
const cleared = clearAllSummarizerOverrides();
|
|
31706
|
+
await channel.sendText(chatId, `Cleared ${cleared} per-chat override${cleared === 1 ? "" : "s"}. All chats now use the global default.`, { parseMode: "plain" });
|
|
31707
|
+
} else if (rest.startsWith("promote:")) {
|
|
31708
|
+
const promoteValue = rest.slice(8);
|
|
31709
|
+
const db3 = getDb();
|
|
31710
|
+
const promote = db3.transaction(() => {
|
|
31711
|
+
if (promoteValue === "off") {
|
|
31712
|
+
setGlobalSummarizer("off", null);
|
|
31713
|
+
} else {
|
|
31714
|
+
const [bk, ...modelParts] = promoteValue.split(":");
|
|
31715
|
+
setGlobalSummarizer(bk, modelParts.join(":") || null);
|
|
31716
|
+
}
|
|
31717
|
+
return clearAllSummarizerOverrides();
|
|
31718
|
+
});
|
|
31719
|
+
const cleared = promote();
|
|
31720
|
+
const label2 = promoteValue === "off" ? "Off" : promoteValue;
|
|
31721
|
+
const clearedNote = cleared > 0 ? ` Cleared ${cleared} per-chat override${cleared === 1 ? "" : "s"}.` : "";
|
|
31722
|
+
await channel.sendText(chatId, `Global summarizer set to ${label2}.${clearedNote} All chats now use this default.`, { parseMode: "plain" });
|
|
31564
31723
|
} else {
|
|
31565
|
-
const
|
|
31566
|
-
const
|
|
31724
|
+
const isOff = rest === "off";
|
|
31725
|
+
const bk = isOff ? "off" : rest.split(":")[0];
|
|
31726
|
+
const mdl = isOff ? null : rest.split(":").slice(1).join(":") || null;
|
|
31567
31727
|
setSummarizer(chatId, bk, mdl);
|
|
31568
|
-
|
|
31728
|
+
const displayLabel = isOff ? "Off" : `${bk}:${mdl ?? "default"}`;
|
|
31729
|
+
const confirmMsg = isOff ? "Session summarization disabled for this chat." : `Summarizer pinned to ${displayLabel} for this chat.`;
|
|
31730
|
+
const promoteData = `summarizer:promote:${rest}`;
|
|
31731
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
31732
|
+
await channel.sendKeyboard(chatId, confirmMsg, [
|
|
31733
|
+
[{ label: "Set as Global Default", data: promoteData }]
|
|
31734
|
+
]);
|
|
31735
|
+
} else {
|
|
31736
|
+
await channel.sendText(chatId, confirmMsg, { parseMode: "plain" });
|
|
31737
|
+
}
|
|
31569
31738
|
}
|
|
31570
31739
|
} else if (data.startsWith("perms:")) {
|
|
31571
31740
|
let chosen = data.slice(6);
|
|
@@ -34564,6 +34733,8 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
34564
34733
|
return;
|
|
34565
34734
|
}
|
|
34566
34735
|
getTypingManager().acquire(chatId, channel);
|
|
34736
|
+
let stopDraftTimer = () => {
|
|
34737
|
+
};
|
|
34567
34738
|
try {
|
|
34568
34739
|
const tMode = settings.getMode();
|
|
34569
34740
|
const tVerbose = settings.getVerboseLevel();
|
|
@@ -34623,7 +34794,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
34623
34794
|
draftState.dirty = true;
|
|
34624
34795
|
};
|
|
34625
34796
|
}
|
|
34626
|
-
|
|
34797
|
+
stopDraftTimer = () => {
|
|
34627
34798
|
if (draftState?.flushTimer) {
|
|
34628
34799
|
clearInterval(draftState.flushTimer);
|
|
34629
34800
|
draftState.flushTimer = null;
|
|
@@ -34659,9 +34830,14 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
34659
34830
|
} catch {
|
|
34660
34831
|
}
|
|
34661
34832
|
},
|
|
34662
|
-
onCompaction: (cid) => {
|
|
34663
|
-
|
|
34664
|
-
|
|
34833
|
+
onCompaction: (cid, phase) => {
|
|
34834
|
+
if (phase === "triggered") {
|
|
34835
|
+
channel.sendText(cid, "\u{1F4BE} Context compaction triggered \u2014 saving conversation to memory...").catch(() => {
|
|
34836
|
+
});
|
|
34837
|
+
} else {
|
|
34838
|
+
channel.sendText(cid, "\u{1F4BE} Context saved to memory.").catch(() => {
|
|
34839
|
+
});
|
|
34840
|
+
}
|
|
34665
34841
|
},
|
|
34666
34842
|
onSlotRotation: (cid, from, to) => {
|
|
34667
34843
|
const slots = getGeminiSlots();
|
|
@@ -34679,7 +34855,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
34679
34855
|
});
|
|
34680
34856
|
}
|
|
34681
34857
|
});
|
|
34682
|
-
|
|
34858
|
+
stopDraftTimer();
|
|
34683
34859
|
const elapsedMs = Date.now() - sigT0;
|
|
34684
34860
|
const elapsedSec = (elapsedMs / 1e3).toFixed(1);
|
|
34685
34861
|
if (liveStatus && response.thinkingText?.trim()) {
|
|
@@ -36269,7 +36445,7 @@ var init_telegram2 = __esm({
|
|
|
36269
36445
|
};
|
|
36270
36446
|
}
|
|
36271
36447
|
async start(handler) {
|
|
36272
|
-
await this.bot.api.setMyCommands([
|
|
36448
|
+
await this.throttle.send(this.primaryChatId, "setMyCommands", () => this.bot.api.setMyCommands([
|
|
36273
36449
|
// Core
|
|
36274
36450
|
{ command: "menu", description: "Home screen \u2014 quick-access keyboard" },
|
|
36275
36451
|
{ command: "m", description: "Home screen (alias for /menu)" },
|
|
@@ -36347,7 +36523,7 @@ var init_telegram2 = __esm({
|
|
|
36347
36523
|
// Context & info
|
|
36348
36524
|
{ command: "info", description: "Current chat context (ID, topic, sender, settings)" },
|
|
36349
36525
|
{ command: "council", description: "Multi-model debate (select models, anonymous rounds)" }
|
|
36350
|
-
]);
|
|
36526
|
+
]));
|
|
36351
36527
|
this.bot.on("message", async (ctx) => {
|
|
36352
36528
|
const chatId = ctx.chat.id.toString();
|
|
36353
36529
|
const senderId = ctx.from?.id?.toString() ?? "";
|
|
@@ -36393,15 +36569,13 @@ var init_telegram2 = __esm({
|
|
|
36393
36569
|
const chatId = ctx.callbackQuery.message?.chat?.id?.toString() ?? userId;
|
|
36394
36570
|
log(`[telegram] Callback from user ${userId} in chat ${chatId}: ${ctx.callbackQuery.data}`);
|
|
36395
36571
|
if (!this.isAuthorized(userId) && !this.isAuthorized(chatId)) {
|
|
36396
|
-
ctx.answerCallbackQuery("Unauthorized")
|
|
36397
|
-
});
|
|
36572
|
+
this.throttle.tryBestEffort(chatId, "answerCallbackQuery:unauth", () => ctx.answerCallbackQuery("Unauthorized"));
|
|
36398
36573
|
return;
|
|
36399
36574
|
}
|
|
36400
36575
|
const data = ctx.callbackQuery.data;
|
|
36401
36576
|
const messageId = ctx.callbackQuery.message?.message_id?.toString();
|
|
36402
36577
|
const threadId = ctx.callbackQuery.message?.message_thread_id;
|
|
36403
|
-
|
|
36404
|
-
});
|
|
36578
|
+
this.throttle.tryBestEffort(chatId, "answerCallbackQuery", () => ctx.answerCallbackQuery());
|
|
36405
36579
|
(async () => {
|
|
36406
36580
|
let ch = this;
|
|
36407
36581
|
if (threadId) {
|
|
@@ -36450,7 +36624,7 @@ var init_telegram2 = __esm({
|
|
|
36450
36624
|
this.keepaliveInterval = setInterval(async () => {
|
|
36451
36625
|
if (!this.pollingExpected) return;
|
|
36452
36626
|
try {
|
|
36453
|
-
await this.bot.api.getMe();
|
|
36627
|
+
await this.throttle.tryBestEffort(this.primaryChatId, "getMe:keepalive", () => this.bot.api.getMe());
|
|
36454
36628
|
this.lastPollingCheckAt = Date.now();
|
|
36455
36629
|
} catch (err) {
|
|
36456
36630
|
error("[telegram] Keepalive ping failed:", err);
|
|
@@ -36590,7 +36764,7 @@ var init_telegram2 = __esm({
|
|
|
36590
36764
|
);
|
|
36591
36765
|
}
|
|
36592
36766
|
async downloadFile(fileId) {
|
|
36593
|
-
const file = await this.bot.api.getFile(fileId);
|
|
36767
|
+
const file = await this.throttle.send(this.primaryChatId, "getFile", () => this.bot.api.getFile(fileId));
|
|
36594
36768
|
const fileUrl = `https://api.telegram.org/file/bot${process.env.TELEGRAM_BOT_TOKEN}/${file.file_path}`;
|
|
36595
36769
|
const response = await fetch(fileUrl);
|
|
36596
36770
|
return Buffer.from(await response.arrayBuffer());
|
|
@@ -36879,7 +37053,11 @@ var init_telegram2 = __esm({
|
|
|
36879
37053
|
}
|
|
36880
37054
|
}
|
|
36881
37055
|
}
|
|
36882
|
-
await
|
|
37056
|
+
await this.throttle.tryBestEffort(
|
|
37057
|
+
this.primaryChatId,
|
|
37058
|
+
"answerInlineQuery",
|
|
37059
|
+
() => ctx.answerInlineQuery(results.slice(0, 10), { cache_time: 30 })
|
|
37060
|
+
);
|
|
36883
37061
|
}
|
|
36884
37062
|
trackAgentMessage(messageId, chatId) {
|
|
36885
37063
|
if (this.agentMessageIds.size >= 1e4) {
|
package/package.json
CHANGED