cc-claw 0.10.1 → 0.11.0
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 +774 -422
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -72,7 +72,7 @@ var VERSION;
|
|
|
72
72
|
var init_version = __esm({
|
|
73
73
|
"src/version.ts"() {
|
|
74
74
|
"use strict";
|
|
75
|
-
VERSION = true ? "0.
|
|
75
|
+
VERSION = true ? "0.11.0" : (() => {
|
|
76
76
|
try {
|
|
77
77
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
78
78
|
} catch {
|
|
@@ -4556,7 +4556,7 @@ function searchContext(userMessage) {
|
|
|
4556
4556
|
}
|
|
4557
4557
|
return null;
|
|
4558
4558
|
}
|
|
4559
|
-
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode) {
|
|
4559
|
+
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext) {
|
|
4560
4560
|
const sections = [];
|
|
4561
4561
|
if (Date.now() - lastSyncMs >= 5e3) {
|
|
4562
4562
|
syncNativeCliFiles();
|
|
@@ -4580,9 +4580,12 @@ ${ctx}`);
|
|
|
4580
4580
|
}
|
|
4581
4581
|
}
|
|
4582
4582
|
if (chatId && tier !== "slim" && tier !== "chat") {
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
sections.push(bridge);
|
|
4583
|
+
if (sideQuestContext) {
|
|
4584
|
+
const bridge = buildContextBridge(sideQuestContext.parentChatId, 15);
|
|
4585
|
+
if (bridge) sections.push(bridge);
|
|
4586
|
+
} else {
|
|
4587
|
+
const bridge = consumeContextBridge(chatId);
|
|
4588
|
+
if (bridge) sections.push(bridge);
|
|
4586
4589
|
}
|
|
4587
4590
|
}
|
|
4588
4591
|
if (tier !== "slim") {
|
|
@@ -4620,6 +4623,23 @@ ${ctx}`);
|
|
|
4620
4623
|
"[React] Start your response with [REACT:emoji] \u2014 one emoji from the Telegram allowed set matching the message tone. Examples: \u{1F914} question, \u{1FAE1} task/request, \u{1F525} exciting, \u{1F923} funny, \u{1F622} sad, \u{1F4AF} agree, \u{1F389} celebrate, \u{1F468}\u200D\u{1F4BB} coding, \u{1F92F} mind-blown, \u{1F440} interesting, \u{1F91D} thanks, \u{1F60E} chill."
|
|
4621
4624
|
);
|
|
4622
4625
|
}
|
|
4626
|
+
if (sideQuestContext) {
|
|
4627
|
+
const { getInFlightMessage: getInFlightMessage3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
4628
|
+
const inFlightMsg = getInFlightMessage3(sideQuestContext.parentChatId);
|
|
4629
|
+
const preamble = [
|
|
4630
|
+
`[Side quest context]`,
|
|
4631
|
+
`You are handling a side request while the user's main agent works on another task.`
|
|
4632
|
+
];
|
|
4633
|
+
if (inFlightMsg) {
|
|
4634
|
+
preamble.push(`The main agent is currently working on: "${inFlightMsg}"`);
|
|
4635
|
+
}
|
|
4636
|
+
preamble.push(
|
|
4637
|
+
`The user's recent conversation history is included above for context.`,
|
|
4638
|
+
`Focus specifically on what the user is asking in THIS message.`,
|
|
4639
|
+
`[End side quest context]`
|
|
4640
|
+
);
|
|
4641
|
+
sections.push(preamble.join("\n"));
|
|
4642
|
+
}
|
|
4623
4643
|
sections.push(userMessage);
|
|
4624
4644
|
const result = sections.join("\n\n");
|
|
4625
4645
|
log(`[bootstrap] Assembled prompt: tier=${tier}, sections=${sections.length}, totalChars=${result.length}`);
|
|
@@ -6772,19 +6792,26 @@ async function spawnAnalysis(adapter, model2, prompt) {
|
|
|
6772
6792
|
if (!resultText) resultText = accumulatedText;
|
|
6773
6793
|
return resultText;
|
|
6774
6794
|
}
|
|
6775
|
-
async function runAnalysis(chatId) {
|
|
6795
|
+
async function runAnalysis(chatId, opts = {}) {
|
|
6776
6796
|
const db3 = getDb();
|
|
6777
|
-
const
|
|
6778
|
-
if (
|
|
6779
|
-
|
|
6780
|
-
|
|
6797
|
+
const { force = false } = opts;
|
|
6798
|
+
if (!force) {
|
|
6799
|
+
const status = getReflectionStatus(db3, chatId);
|
|
6800
|
+
if (status === "frozen") {
|
|
6801
|
+
log(`[reflection] Skipping analysis for ${chatId} \u2014 reflection is frozen`);
|
|
6802
|
+
return [];
|
|
6803
|
+
}
|
|
6781
6804
|
}
|
|
6782
6805
|
const signals = getUnprocessedSignals(db3, chatId);
|
|
6783
|
-
if (signals.length === 0) {
|
|
6806
|
+
if (!force && signals.length === 0) {
|
|
6784
6807
|
log(`[reflection] No unprocessed signals for ${chatId}`);
|
|
6785
6808
|
return [];
|
|
6786
6809
|
}
|
|
6787
6810
|
const conversations = getTodayConversations(chatId);
|
|
6811
|
+
if (signals.length === 0 && !conversations) {
|
|
6812
|
+
log(`[reflection] No signals and no conversations for ${chatId} \u2014 nothing to analyze`);
|
|
6813
|
+
return [];
|
|
6814
|
+
}
|
|
6788
6815
|
const soulMd = readIdentityFile("SOUL.md");
|
|
6789
6816
|
const userMd = readIdentityFile("USER.md");
|
|
6790
6817
|
const applied = getAppliedInsights(db3, chatId);
|
|
@@ -6819,7 +6846,7 @@ async function runAnalysis(chatId) {
|
|
|
6819
6846
|
return [];
|
|
6820
6847
|
}
|
|
6821
6848
|
const { adapter, model: model2 } = resolved;
|
|
6822
|
-
log(`[reflection] Running analysis via ${adapter.id}:${model2} for chat ${chatId} (${signals.length} signals)`);
|
|
6849
|
+
log(`[reflection] Running analysis via ${adapter.id}:${model2} for chat ${chatId} (${signals.length} signals, force=${force})`);
|
|
6823
6850
|
let rawOutput;
|
|
6824
6851
|
try {
|
|
6825
6852
|
rawOutput = await spawnAnalysis(adapter, model2, prompt);
|
|
@@ -6829,13 +6856,12 @@ async function runAnalysis(chatId) {
|
|
|
6829
6856
|
}
|
|
6830
6857
|
if (!rawOutput || rawOutput.includes("NO_INSIGHTS")) {
|
|
6831
6858
|
log(`[reflection] Analysis returned no insights for ${chatId}`);
|
|
6832
|
-
markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6859
|
+
if (signals.length > 0) markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6833
6860
|
return [];
|
|
6834
6861
|
}
|
|
6835
6862
|
const parsed = parseAnalysisOutput(rawOutput);
|
|
6836
|
-
const signalIdStr = signals.map((s) => s.id).join(",");
|
|
6863
|
+
const signalIdStr = signals.length > 0 ? signals.map((s) => s.id).join(",") : "manual";
|
|
6837
6864
|
for (const insight of parsed) {
|
|
6838
|
-
const insightStatus = insight.category === "codebase" ? "recommendation" : "pending";
|
|
6839
6865
|
let conflictsWithId = null;
|
|
6840
6866
|
if (insight.conflictsWith && insight.conflictsWith !== "none") {
|
|
6841
6867
|
const parsed_id = parseInt(insight.conflictsWith, 10);
|
|
@@ -6856,19 +6882,20 @@ async function runAnalysis(chatId) {
|
|
|
6856
6882
|
model: model2
|
|
6857
6883
|
});
|
|
6858
6884
|
}
|
|
6859
|
-
markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6885
|
+
if (signals.length > 0) markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6860
6886
|
aggregateDailyMetrics(db3, chatId);
|
|
6861
6887
|
logActivity(db3, {
|
|
6862
6888
|
chatId,
|
|
6863
6889
|
source: "agent",
|
|
6864
6890
|
eventType: "reflection_triggered",
|
|
6865
|
-
summary: `Reflection analysis produced ${parsed.length} insight(s) from ${signals.length} signal(s)`,
|
|
6891
|
+
summary: `Reflection analysis produced ${parsed.length} insight(s) from ${signals.length} signal(s)${force ? " (manual)" : ""}`,
|
|
6866
6892
|
detail: {
|
|
6867
6893
|
signalCount: signals.length,
|
|
6868
6894
|
insightCount: parsed.length,
|
|
6869
6895
|
backend: adapter.id,
|
|
6870
6896
|
model: model2,
|
|
6871
|
-
categories: parsed.map((p) => p.category)
|
|
6897
|
+
categories: parsed.map((p) => p.category),
|
|
6898
|
+
forced: force
|
|
6872
6899
|
}
|
|
6873
6900
|
});
|
|
6874
6901
|
log(`[reflection] Analysis complete for ${chatId}: ${parsed.length} insight(s) from ${signals.length} signal(s)`);
|
|
@@ -8446,11 +8473,19 @@ var init_detect = __esm({
|
|
|
8446
8473
|
var agent_exports = {};
|
|
8447
8474
|
__export(agent_exports, {
|
|
8448
8475
|
askAgent: () => askAgent,
|
|
8476
|
+
getInFlightMessage: () => getInFlightMessage,
|
|
8449
8477
|
isChatBusy: () => isChatBusy,
|
|
8478
|
+
isSyntheticChatId: () => isSyntheticChatId,
|
|
8450
8479
|
stopAgent: () => stopAgent
|
|
8451
8480
|
});
|
|
8452
8481
|
import { spawn as spawn5 } from "child_process";
|
|
8453
8482
|
import { createInterface as createInterface4 } from "readline";
|
|
8483
|
+
function isSyntheticChatId(chatId) {
|
|
8484
|
+
return chatId.startsWith("sq:") || chatId.startsWith("cron:");
|
|
8485
|
+
}
|
|
8486
|
+
function getInFlightMessage(chatId) {
|
|
8487
|
+
return activeChats.get(chatId)?.userMessage;
|
|
8488
|
+
}
|
|
8454
8489
|
function killProcessGroup(proc, signal = "SIGTERM") {
|
|
8455
8490
|
try {
|
|
8456
8491
|
if (proc.pid) process.kill(-proc.pid, signal);
|
|
@@ -8650,12 +8685,16 @@ function spawnQuery(adapter, config2, model2, cancelState, thinkingLevel, timeou
|
|
|
8650
8685
|
});
|
|
8651
8686
|
});
|
|
8652
8687
|
}
|
|
8653
|
-
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation) {
|
|
8688
|
+
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation, parentChatId) {
|
|
8654
8689
|
const geminiAdapter = adapter;
|
|
8655
8690
|
const slots = getEligibleGeminiSlots(rotationMode);
|
|
8656
8691
|
if (slots.length === 0) {
|
|
8657
8692
|
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
8658
8693
|
}
|
|
8694
|
+
if (parentChatId) {
|
|
8695
|
+
const { env } = geminiAdapter.getEnvForSlot(parentChatId, void 0, rotationMode);
|
|
8696
|
+
return await spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, { ...opts, envOverride: env });
|
|
8697
|
+
}
|
|
8659
8698
|
const maxAttempts = Math.min(slots.length, 10);
|
|
8660
8699
|
let lastError;
|
|
8661
8700
|
for (let i = 0; i < maxAttempts; i++) {
|
|
@@ -8716,17 +8755,19 @@ function askAgent(chatId, userMessage, opts) {
|
|
|
8716
8755
|
return withChatLock(chatId, () => askAgentImpl(chatId, userMessage, opts));
|
|
8717
8756
|
}
|
|
8718
8757
|
async function askAgentImpl(chatId, userMessage, opts) {
|
|
8719
|
-
const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, agentMode: optsAgentMode, onSubagentActivity } = opts ?? {};
|
|
8720
|
-
const
|
|
8721
|
-
const
|
|
8722
|
-
const
|
|
8723
|
-
const
|
|
8758
|
+
const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId } = opts ?? {};
|
|
8759
|
+
const settingsChat = settingsSourceChatId ?? chatId;
|
|
8760
|
+
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
8761
|
+
const mode = permMode ?? getMode(settingsChat);
|
|
8762
|
+
const responseStyle = getResponseStyle(settingsChat);
|
|
8763
|
+
const thinkingLevel = getThinkingLevel(settingsChat);
|
|
8724
8764
|
const resolvedCwd = cwd ?? WORKSPACE_PATH;
|
|
8725
8765
|
const tier = bootstrapTier ?? "full";
|
|
8726
|
-
const effectiveAgentMode = optsAgentMode ?? getAgentMode(
|
|
8727
|
-
const
|
|
8728
|
-
const
|
|
8729
|
-
const
|
|
8766
|
+
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
8767
|
+
const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
|
|
8768
|
+
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx);
|
|
8769
|
+
const existingSessionId = getSessionId(settingsChat);
|
|
8770
|
+
const allowedTools = getEnabledTools(settingsChat);
|
|
8730
8771
|
const mcpConfigPath = tier !== "slim" && effectiveAgentMode !== "native" && MCP_CONFIG_FLAG[adapter.id] ? getMcpConfigPath(chatId) : null;
|
|
8731
8772
|
const baseConfig = adapter.buildSpawnConfig({
|
|
8732
8773
|
prompt: fullPrompt,
|
|
@@ -8756,7 +8797,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8756
8797
|
}
|
|
8757
8798
|
return cfg;
|
|
8758
8799
|
})() : baseConfig;
|
|
8759
|
-
const cancelState = { cancelled: false };
|
|
8800
|
+
const cancelState = { cancelled: false, userMessage };
|
|
8760
8801
|
activeChats.set(chatId, cancelState);
|
|
8761
8802
|
const spawnOpts = { onStream, onToolAction, onSubagentActivity };
|
|
8762
8803
|
const resolvedModel = model2 ?? adapter.defaultModel;
|
|
@@ -8766,7 +8807,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8766
8807
|
try {
|
|
8767
8808
|
if (useGeminiRotation) {
|
|
8768
8809
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
8769
|
-
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb);
|
|
8810
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId);
|
|
8770
8811
|
} else {
|
|
8771
8812
|
result = await spawnQuery(adapter, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts);
|
|
8772
8813
|
}
|
|
@@ -8777,7 +8818,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8777
8818
|
clearSession(chatId);
|
|
8778
8819
|
if (useGeminiRotation) {
|
|
8779
8820
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
8780
|
-
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb);
|
|
8821
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId);
|
|
8781
8822
|
} else {
|
|
8782
8823
|
result = await spawnQuery(adapter, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts);
|
|
8783
8824
|
}
|
|
@@ -8802,7 +8843,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8802
8843
|
if (cancelState.cancelled) {
|
|
8803
8844
|
return { text: "Stopped.", usage: { input: result.input, output: result.output, cacheRead: result.cacheRead } };
|
|
8804
8845
|
}
|
|
8805
|
-
if (result.sessionId) {
|
|
8846
|
+
if (result.sessionId && !isSyntheticChatId(chatId)) {
|
|
8806
8847
|
setSessionId(chatId, result.sessionId);
|
|
8807
8848
|
}
|
|
8808
8849
|
if (!result.resultText && result.sawToolEvents) {
|
|
@@ -8813,7 +8854,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8813
8854
|
await summarizeSession(chatId);
|
|
8814
8855
|
clearSession(chatId);
|
|
8815
8856
|
}
|
|
8816
|
-
if (result.resultText) {
|
|
8857
|
+
if (result.resultText && !isSyntheticChatId(chatId)) {
|
|
8817
8858
|
appendToLog(chatId, userMessage, result.resultText, adapter.id, model2 ?? null, result.sessionId ?? null);
|
|
8818
8859
|
const AUTO_SUMMARIZE_THRESHOLD = 30;
|
|
8819
8860
|
const pairCount = tier !== "chat" ? getMessagePairCount(chatId) : 0;
|
|
@@ -8944,7 +8985,7 @@ ${responseText.slice(0, 500)}`);
|
|
|
8944
8985
|
if (!cleanText) return true;
|
|
8945
8986
|
if (channelName === "telegram") {
|
|
8946
8987
|
const parsed = parseTelegramTarget(targetChatId);
|
|
8947
|
-
await channel.sendText(parsed.chatId, cleanText,
|
|
8988
|
+
await channel.sendText(parsed.chatId, cleanText, { threadId: parsed.threadId });
|
|
8948
8989
|
} else {
|
|
8949
8990
|
await channel.sendText(targetChatId, cleanText);
|
|
8950
8991
|
}
|
|
@@ -8990,7 +9031,7 @@ async function notifyJobFailure(job, errorMessage2, retryInfo) {
|
|
|
8990
9031
|
const lines = [`Scheduled job #${job.id} failed: ${errorMessage2}`];
|
|
8991
9032
|
if (retryInfo) lines.push(retryInfo);
|
|
8992
9033
|
try {
|
|
8993
|
-
await channel.sendText(notifyTarget, lines.join("\n"), "plain");
|
|
9034
|
+
await channel.sendText(notifyTarget, lines.join("\n"), { parseMode: "plain" });
|
|
8994
9035
|
} catch {
|
|
8995
9036
|
}
|
|
8996
9037
|
}
|
|
@@ -9002,7 +9043,7 @@ async function notifyJobAutoPaused(job) {
|
|
|
9002
9043
|
await channel.sendText(
|
|
9003
9044
|
job.chatId,
|
|
9004
9045
|
`Job #${job.id} ("${job.description}") has been auto-paused after ${job.consecutiveFailures} consecutive failures. Use /resume ${job.id} to re-enable.`,
|
|
9005
|
-
"plain"
|
|
9046
|
+
{ parseMode: "plain" }
|
|
9006
9047
|
);
|
|
9007
9048
|
} catch {
|
|
9008
9049
|
}
|
|
@@ -10022,6 +10063,9 @@ var init_telegram = __esm({
|
|
|
10022
10063
|
// src/channels/telegram.ts
|
|
10023
10064
|
import { Bot, InlineKeyboard, InputFile } from "grammy";
|
|
10024
10065
|
function numericChatId(chatId) {
|
|
10066
|
+
if (chatId.startsWith("sq:") || chatId.startsWith("cron:")) {
|
|
10067
|
+
throw new Error(`Synthetic chatId "${chatId}" passed to Telegram API`);
|
|
10068
|
+
}
|
|
10025
10069
|
const raw = chatId.includes(":") ? chatId.split(":").pop() : chatId;
|
|
10026
10070
|
return parseInt(raw);
|
|
10027
10071
|
}
|
|
@@ -10156,7 +10200,7 @@ var init_telegram2 = __esm({
|
|
|
10156
10200
|
error("[telegram] Handler error:", err);
|
|
10157
10201
|
});
|
|
10158
10202
|
} else {
|
|
10159
|
-
this.sendText(chatId, "I can handle text, voice, photos, documents, and videos. This message type isn't supported yet.", "plain").catch(() => {
|
|
10203
|
+
this.sendText(chatId, "I can handle text, voice, photos, documents, and videos. This message type isn't supported yet.", { parseMode: "plain" }).catch(() => {
|
|
10160
10204
|
});
|
|
10161
10205
|
}
|
|
10162
10206
|
});
|
|
@@ -10219,12 +10263,14 @@ var init_telegram2 = __esm({
|
|
|
10219
10263
|
async sendTyping(chatId) {
|
|
10220
10264
|
await this.bot.api.sendChatAction(numericChatId(chatId), "typing");
|
|
10221
10265
|
}
|
|
10222
|
-
async sendText(chatId, text,
|
|
10266
|
+
async sendText(chatId, text, opts) {
|
|
10267
|
+
const { parseMode, threadId, replyToMessageId } = opts ?? {};
|
|
10223
10268
|
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
10269
|
+
const replyOpts = replyToMessageId ? { reply_parameters: { message_id: replyToMessageId } } : {};
|
|
10224
10270
|
if (parseMode === "plain") {
|
|
10225
10271
|
const plainChunks = splitMessage(text);
|
|
10226
10272
|
for (const chunk of plainChunks) {
|
|
10227
|
-
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, { ...threadOpts });
|
|
10273
|
+
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, { ...threadOpts, ...replyOpts });
|
|
10228
10274
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10229
10275
|
}
|
|
10230
10276
|
return;
|
|
@@ -10235,14 +10281,15 @@ var init_telegram2 = __esm({
|
|
|
10235
10281
|
try {
|
|
10236
10282
|
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, {
|
|
10237
10283
|
parse_mode: "HTML",
|
|
10238
|
-
...threadOpts
|
|
10284
|
+
...threadOpts,
|
|
10285
|
+
...replyOpts
|
|
10239
10286
|
});
|
|
10240
10287
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10241
10288
|
} catch {
|
|
10242
10289
|
const sent = await this.bot.api.sendMessage(
|
|
10243
10290
|
numericChatId(chatId),
|
|
10244
10291
|
chunk.replace(/<[^>]+>/g, ""),
|
|
10245
|
-
{ ...threadOpts }
|
|
10292
|
+
{ ...threadOpts, ...replyOpts }
|
|
10246
10293
|
);
|
|
10247
10294
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10248
10295
|
}
|
|
@@ -10818,7 +10865,7 @@ function hasActiveProfile(chatId) {
|
|
|
10818
10865
|
}
|
|
10819
10866
|
async function startProfileWizard(chatId, channel) {
|
|
10820
10867
|
activeProfiles.set(chatId, { step: "name" });
|
|
10821
|
-
await channel.sendText(chatId, "Let's set up your profile! I'll ask a few quick questions.\n\nWhat's your name?", "plain");
|
|
10868
|
+
await channel.sendText(chatId, "Let's set up your profile! I'll ask a few quick questions.\n\nWhat's your name?", { parseMode: "plain" });
|
|
10822
10869
|
}
|
|
10823
10870
|
async function handleProfileText(chatId, text, channel) {
|
|
10824
10871
|
const state = activeProfiles.get(chatId);
|
|
@@ -10833,9 +10880,9 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10833
10880
|
[{ label: "UTC", data: "profile:tz:UTC" }, { label: "Israel", data: "profile:tz:Asia/Jerusalem" }],
|
|
10834
10881
|
[{ label: "Europe/London", data: "profile:tz:Europe/London" }, { label: "Asia/Tokyo", data: "profile:tz:Asia/Tokyo" }]
|
|
10835
10882
|
]);
|
|
10836
|
-
await channel.sendText(chatId, "Or type your timezone (e.g. America/Chicago):", "plain");
|
|
10883
|
+
await channel.sendText(chatId, "Or type your timezone (e.g. America/Chicago):", { parseMode: "plain" });
|
|
10837
10884
|
} else {
|
|
10838
|
-
await channel.sendText(chatId, `Hi ${state.name}! What's your timezone? (e.g. America/New_York, UTC, Asia/Jerusalem)`, "plain");
|
|
10885
|
+
await channel.sendText(chatId, `Hi ${state.name}! What's your timezone? (e.g. America/New_York, UTC, Asia/Jerusalem)`, { parseMode: "plain" });
|
|
10839
10886
|
}
|
|
10840
10887
|
break;
|
|
10841
10888
|
case "timezone":
|
|
@@ -10843,7 +10890,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10843
10890
|
Intl.DateTimeFormat(void 0, { timeZone: text.trim() });
|
|
10844
10891
|
state.timezone = text.trim();
|
|
10845
10892
|
} catch {
|
|
10846
|
-
await channel.sendText(chatId, "Invalid timezone. Try again (e.g. America/New_York):", "plain");
|
|
10893
|
+
await channel.sendText(chatId, "Invalid timezone. Try again (e.g. America/New_York):", { parseMode: "plain" });
|
|
10847
10894
|
return;
|
|
10848
10895
|
}
|
|
10849
10896
|
state.step = "style";
|
|
@@ -10853,7 +10900,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10853
10900
|
[{ label: "Casual", data: "profile:style:casual" }, { label: "Formal", data: "profile:style:formal" }]
|
|
10854
10901
|
]);
|
|
10855
10902
|
} else {
|
|
10856
|
-
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", "plain");
|
|
10903
|
+
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", { parseMode: "plain" });
|
|
10857
10904
|
}
|
|
10858
10905
|
break;
|
|
10859
10906
|
case "style":
|
|
@@ -10865,7 +10912,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10865
10912
|
[{ label: "Personal assistant", data: "profile:use:personal" }, { label: "All of the above", data: "profile:use:all" }]
|
|
10866
10913
|
]);
|
|
10867
10914
|
} else {
|
|
10868
|
-
await channel.sendText(chatId, "Primary use? (coding / research / personal / all)", "plain");
|
|
10915
|
+
await channel.sendText(chatId, "Primary use? (coding / research / personal / all)", { parseMode: "plain" });
|
|
10869
10916
|
}
|
|
10870
10917
|
break;
|
|
10871
10918
|
case "use_case":
|
|
@@ -10880,14 +10927,14 @@ async function handleProfileCallback(chatId, data, channel) {
|
|
|
10880
10927
|
if (data.startsWith("profile:tz:")) {
|
|
10881
10928
|
state.timezone = data.slice(11);
|
|
10882
10929
|
state.step = "style";
|
|
10883
|
-
await channel.sendText(chatId, `Timezone: ${state.timezone}`, "plain");
|
|
10930
|
+
await channel.sendText(chatId, `Timezone: ${state.timezone}`, { parseMode: "plain" });
|
|
10884
10931
|
if (typeof channel.sendKeyboard === "function") {
|
|
10885
10932
|
await channel.sendKeyboard(chatId, "How should I communicate?", [
|
|
10886
10933
|
[{ label: "Concise", data: "profile:style:concise" }, { label: "Detailed", data: "profile:style:detailed" }],
|
|
10887
10934
|
[{ label: "Casual", data: "profile:style:casual" }, { label: "Formal", data: "profile:style:formal" }]
|
|
10888
10935
|
]);
|
|
10889
10936
|
} else {
|
|
10890
|
-
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", "plain");
|
|
10937
|
+
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", { parseMode: "plain" });
|
|
10891
10938
|
}
|
|
10892
10939
|
} else if (data.startsWith("profile:style:")) {
|
|
10893
10940
|
state.style = data.slice(14);
|
|
@@ -10928,7 +10975,7 @@ Style: ${state.style}
|
|
|
10928
10975
|
Use: ${state.useCase}
|
|
10929
10976
|
|
|
10930
10977
|
You can edit ~/.cc-claw/identity/USER.md anytime or run /setup-profile again.`,
|
|
10931
|
-
"plain"
|
|
10978
|
+
{ parseMode: "plain" }
|
|
10932
10979
|
);
|
|
10933
10980
|
}
|
|
10934
10981
|
function extractUserUpdates(text) {
|
|
@@ -11743,9 +11790,9 @@ async function startWizard(chatId, input, channel) {
|
|
|
11743
11790
|
lines.push(' "every Monday at 10:30am"');
|
|
11744
11791
|
lines.push(' "every 5 minutes"');
|
|
11745
11792
|
lines.push(' or a raw cron: "0 9 * * 1-5"');
|
|
11746
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
11793
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
11747
11794
|
} else {
|
|
11748
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
11795
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
11749
11796
|
await promptTimezone(chatId, channel);
|
|
11750
11797
|
}
|
|
11751
11798
|
}
|
|
@@ -11758,7 +11805,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11758
11805
|
const trimmed = text.trim();
|
|
11759
11806
|
if (trimmed.toLowerCase() === "keep" && pending.cron) {
|
|
11760
11807
|
pending.step = "timezone";
|
|
11761
|
-
await channel.sendText(chatId, `Keeping schedule: ${pending.cron}`, "plain");
|
|
11808
|
+
await channel.sendText(chatId, `Keeping schedule: ${pending.cron}`, { parseMode: "plain" });
|
|
11762
11809
|
await promptTimezone(chatId, channel);
|
|
11763
11810
|
return;
|
|
11764
11811
|
}
|
|
@@ -11766,7 +11813,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11766
11813
|
pending.cron = trimmed;
|
|
11767
11814
|
pending.scheduleType = "cron";
|
|
11768
11815
|
pending.step = "timezone";
|
|
11769
|
-
await channel.sendText(chatId, `Schedule set: ${trimmed}`, "plain");
|
|
11816
|
+
await channel.sendText(chatId, `Schedule set: ${trimmed}`, { parseMode: "plain" });
|
|
11770
11817
|
await promptTimezone(chatId, channel);
|
|
11771
11818
|
return;
|
|
11772
11819
|
}
|
|
@@ -11776,13 +11823,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11776
11823
|
pending.scheduleType = "cron";
|
|
11777
11824
|
if (parsed.task && parsed.task !== text) pending.task = parsed.task;
|
|
11778
11825
|
pending.step = "timezone";
|
|
11779
|
-
await channel.sendText(chatId, `Schedule: ${pending.cron}`, "plain");
|
|
11826
|
+
await channel.sendText(chatId, `Schedule: ${pending.cron}`, { parseMode: "plain" });
|
|
11780
11827
|
await promptTimezone(chatId, channel);
|
|
11781
11828
|
} else {
|
|
11782
11829
|
await channel.sendText(chatId, `Couldn't parse that schedule. Try something like:
|
|
11783
11830
|
"every day at 9am"
|
|
11784
11831
|
"every 5 minutes"
|
|
11785
|
-
or a raw cron expression like "0 9 * * 1-5"`, "plain");
|
|
11832
|
+
or a raw cron expression like "0 9 * * 1-5"`, { parseMode: "plain" });
|
|
11786
11833
|
}
|
|
11787
11834
|
break;
|
|
11788
11835
|
}
|
|
@@ -11795,7 +11842,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11795
11842
|
pending.step = "backend";
|
|
11796
11843
|
await promptBackend(chatId, channel);
|
|
11797
11844
|
} catch {
|
|
11798
|
-
await channel.sendText(chatId, `"${tz}" is not a valid timezone. Try again or tap a button.`, "plain");
|
|
11845
|
+
await channel.sendText(chatId, `"${tz}" is not a valid timezone. Try again or tap a button.`, { parseMode: "plain" });
|
|
11799
11846
|
}
|
|
11800
11847
|
break;
|
|
11801
11848
|
}
|
|
@@ -11806,7 +11853,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11806
11853
|
pending.step = "model";
|
|
11807
11854
|
await promptModel(chatId, channel);
|
|
11808
11855
|
} else {
|
|
11809
|
-
await channel.sendText(chatId, `Unknown backend. Available: ${getAvailableBackendIds().join(", ")}`, "plain");
|
|
11856
|
+
await channel.sendText(chatId, `Unknown backend. Available: ${getAvailableBackendIds().join(", ")}`, { parseMode: "plain" });
|
|
11810
11857
|
}
|
|
11811
11858
|
break;
|
|
11812
11859
|
}
|
|
@@ -11819,7 +11866,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11819
11866
|
pending.step = "thinking";
|
|
11820
11867
|
await promptThinking(chatId, channel);
|
|
11821
11868
|
} else {
|
|
11822
|
-
await channel.sendText(chatId, `Unknown model. Choose: ${Object.keys(adapter.availableModels).join(", ")}`, "plain");
|
|
11869
|
+
await channel.sendText(chatId, `Unknown model. Choose: ${Object.keys(adapter.availableModels).join(", ")}`, { parseMode: "plain" });
|
|
11823
11870
|
}
|
|
11824
11871
|
break;
|
|
11825
11872
|
}
|
|
@@ -11837,7 +11884,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11837
11884
|
pending.step = "session";
|
|
11838
11885
|
await promptSession(chatId, channel);
|
|
11839
11886
|
} else if (isNaN(val) || val < TIMEOUT_MIN_SECONDS || val > TIMEOUT_MAX_SECONDS) {
|
|
11840
|
-
await channel.sendText(chatId, `Invalid timeout. Enter a value between ${TIMEOUT_MIN_SECONDS} and ${TIMEOUT_MAX_SECONDS} seconds, or "default" for ${TIMEOUT_DEFAULT_SECONDS}s.`, "plain");
|
|
11887
|
+
await channel.sendText(chatId, `Invalid timeout. Enter a value between ${TIMEOUT_MIN_SECONDS} and ${TIMEOUT_MAX_SECONDS} seconds, or "default" for ${TIMEOUT_DEFAULT_SECONDS}s.`, { parseMode: "plain" });
|
|
11841
11888
|
} else {
|
|
11842
11889
|
pending.timeout = val;
|
|
11843
11890
|
pending.step = "session";
|
|
@@ -11852,7 +11899,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11852
11899
|
pending.step = "delivery";
|
|
11853
11900
|
await promptDelivery(chatId, channel);
|
|
11854
11901
|
} else {
|
|
11855
|
-
await channel.sendText(chatId, "Choose: isolated or main", "plain");
|
|
11902
|
+
await channel.sendText(chatId, "Choose: isolated or main", { parseMode: "plain" });
|
|
11856
11903
|
}
|
|
11857
11904
|
break;
|
|
11858
11905
|
}
|
|
@@ -11865,13 +11912,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11865
11912
|
await promptTarget(chatId, channel);
|
|
11866
11913
|
} else if (dm === "webhook") {
|
|
11867
11914
|
pending.step = "target";
|
|
11868
|
-
await channel.sendText(chatId, "Enter the webhook URL:", "plain");
|
|
11915
|
+
await channel.sendText(chatId, "Enter the webhook URL:", { parseMode: "plain" });
|
|
11869
11916
|
} else {
|
|
11870
11917
|
pending.step = "confirm";
|
|
11871
11918
|
await promptConfirm(chatId, channel);
|
|
11872
11919
|
}
|
|
11873
11920
|
} else {
|
|
11874
|
-
await channel.sendText(chatId, "Choose: announce, webhook, or none", "plain");
|
|
11921
|
+
await channel.sendText(chatId, "Choose: announce, webhook, or none", { parseMode: "plain" });
|
|
11875
11922
|
}
|
|
11876
11923
|
break;
|
|
11877
11924
|
}
|
|
@@ -11889,13 +11936,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11889
11936
|
break;
|
|
11890
11937
|
}
|
|
11891
11938
|
default:
|
|
11892
|
-
await channel.sendText(chatId, "Please use the buttons to select an option, or type 'cancel' to abort.", "plain");
|
|
11939
|
+
await channel.sendText(chatId, "Please use the buttons to select an option, or type 'cancel' to abort.", { parseMode: "plain" });
|
|
11893
11940
|
}
|
|
11894
11941
|
}
|
|
11895
11942
|
async function handleWizardCallback(chatId, data, channel) {
|
|
11896
11943
|
const pending = pendingJobs.get(chatId);
|
|
11897
11944
|
if (!pending) {
|
|
11898
|
-
await channel.sendText(chatId, "No active scheduling wizard. Use /schedule to start one.", "plain");
|
|
11945
|
+
await channel.sendText(chatId, "No active scheduling wizard. Use /schedule to start one.", { parseMode: "plain" });
|
|
11899
11946
|
return;
|
|
11900
11947
|
}
|
|
11901
11948
|
resetWizardTimeout(chatId);
|
|
@@ -11903,20 +11950,20 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11903
11950
|
const tz = data.slice(9);
|
|
11904
11951
|
pending.timezone = COMMON_TIMEZONES[tz] ?? tz;
|
|
11905
11952
|
pending.step = "backend";
|
|
11906
|
-
await channel.sendText(chatId, `Timezone: ${pending.timezone}`, "plain");
|
|
11953
|
+
await channel.sendText(chatId, `Timezone: ${pending.timezone}`, { parseMode: "plain" });
|
|
11907
11954
|
await promptBackend(chatId, channel);
|
|
11908
11955
|
} else if (data.startsWith("sched:backend:")) {
|
|
11909
11956
|
const backend2 = data.slice(14);
|
|
11910
11957
|
pending.backend = backend2;
|
|
11911
11958
|
pending.step = "model";
|
|
11912
11959
|
const adapter = getAdapter(backend2);
|
|
11913
|
-
await channel.sendText(chatId, `Backend: ${adapter.displayName}`, "plain");
|
|
11960
|
+
await channel.sendText(chatId, `Backend: ${adapter.displayName}`, { parseMode: "plain" });
|
|
11914
11961
|
await promptModel(chatId, channel);
|
|
11915
11962
|
} else if (data.startsWith("sched:model:")) {
|
|
11916
11963
|
const model2 = data.slice(12);
|
|
11917
11964
|
pending.model = model2;
|
|
11918
11965
|
pending.step = "thinking";
|
|
11919
|
-
await channel.sendText(chatId, `Model: ${model2}`, "plain");
|
|
11966
|
+
await channel.sendText(chatId, `Model: ${model2}`, { parseMode: "plain" });
|
|
11920
11967
|
await promptThinking(chatId, channel);
|
|
11921
11968
|
} else if (data.startsWith("sched:thinking:")) {
|
|
11922
11969
|
pending.thinking = data.slice(15);
|
|
@@ -11931,7 +11978,7 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11931
11978
|
}
|
|
11932
11979
|
pending.step = "session";
|
|
11933
11980
|
const label2 = pending.timeout ? `${pending.timeout}s (${Math.round(pending.timeout / 60)} min)` : `Default (${TIMEOUT_DEFAULT_SECONDS}s)`;
|
|
11934
|
-
await channel.sendText(chatId, `Timeout: ${label2}`, "plain");
|
|
11981
|
+
await channel.sendText(chatId, `Timeout: ${label2}`, { parseMode: "plain" });
|
|
11935
11982
|
await promptSession(chatId, channel);
|
|
11936
11983
|
} else if (data.startsWith("sched:session:")) {
|
|
11937
11984
|
pending.sessionType = data.slice(14);
|
|
@@ -11944,7 +11991,7 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11944
11991
|
await promptTarget(chatId, channel);
|
|
11945
11992
|
} else if (pending.deliveryMode === "webhook") {
|
|
11946
11993
|
pending.step = "target";
|
|
11947
|
-
await channel.sendText(chatId, "Enter the webhook URL:", "plain");
|
|
11994
|
+
await channel.sendText(chatId, "Enter the webhook URL:", { parseMode: "plain" });
|
|
11948
11995
|
} else {
|
|
11949
11996
|
pending.step = "confirm";
|
|
11950
11997
|
await promptConfirm(chatId, channel);
|
|
@@ -11953,21 +12000,21 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11953
12000
|
pending.target = chatId;
|
|
11954
12001
|
pending.channel = "telegram";
|
|
11955
12002
|
pending.step = "confirm";
|
|
11956
|
-
await channel.sendText(chatId, "Delivery: this chat", "plain");
|
|
12003
|
+
await channel.sendText(chatId, "Delivery: this chat", { parseMode: "plain" });
|
|
11957
12004
|
await promptConfirm(chatId, channel);
|
|
11958
12005
|
} else if (data === "sched:confirm") {
|
|
11959
12006
|
await finalizeJob(chatId, channel);
|
|
11960
12007
|
} else if (data === "sched:edit") {
|
|
11961
12008
|
pending.step = "schedule";
|
|
11962
|
-
await channel.sendText(chatId, "Starting over. When should this run?\nSend a schedule or raw cron expression:", "plain");
|
|
12009
|
+
await channel.sendText(chatId, "Starting over. When should this run?\nSend a schedule or raw cron expression:", { parseMode: "plain" });
|
|
11963
12010
|
} else if (data === "sched:cancel") {
|
|
11964
12011
|
pendingJobs.delete(chatId);
|
|
11965
|
-
await channel.sendText(chatId, "Scheduling cancelled.", "plain");
|
|
12012
|
+
await channel.sendText(chatId, "Scheduling cancelled.", { parseMode: "plain" });
|
|
11966
12013
|
}
|
|
11967
12014
|
}
|
|
11968
12015
|
async function promptTimezone(chatId, channel) {
|
|
11969
12016
|
if (typeof channel.sendKeyboard !== "function") {
|
|
11970
|
-
await channel.sendText(chatId, "Enter a timezone (e.g. America/New_York, UTC, Asia/Jerusalem):", "plain");
|
|
12017
|
+
await channel.sendText(chatId, "Enter a timezone (e.g. America/New_York, UTC, Asia/Jerusalem):", { parseMode: "plain" });
|
|
11971
12018
|
return;
|
|
11972
12019
|
}
|
|
11973
12020
|
const tzButtons = [];
|
|
@@ -11983,7 +12030,7 @@ async function promptTimezone(chatId, channel) {
|
|
|
11983
12030
|
}
|
|
11984
12031
|
async function promptBackend(chatId, channel) {
|
|
11985
12032
|
if (typeof channel.sendKeyboard !== "function") {
|
|
11986
|
-
await channel.sendText(chatId, `Enter backend (${getAvailableBackendIds().join(", ")}):`, "plain");
|
|
12033
|
+
await channel.sendText(chatId, `Enter backend (${getAvailableBackendIds().join(", ")}):`, { parseMode: "plain" });
|
|
11987
12034
|
return;
|
|
11988
12035
|
}
|
|
11989
12036
|
const adapters2 = getAvailableAdapters();
|
|
@@ -11999,7 +12046,7 @@ async function promptModel(chatId, channel) {
|
|
|
11999
12046
|
const adapter = getAdapter(pending.backend);
|
|
12000
12047
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12001
12048
|
const models = Object.keys(adapter.availableModels).join(", ");
|
|
12002
|
-
await channel.sendText(chatId, `Enter model (${models}):`, "plain");
|
|
12049
|
+
await channel.sendText(chatId, `Enter model (${models}):`, { parseMode: "plain" });
|
|
12003
12050
|
return;
|
|
12004
12051
|
}
|
|
12005
12052
|
const buttons = Object.entries(adapter.availableModels).map(([id, info]) => [{
|
|
@@ -12015,7 +12062,7 @@ async function promptThinking(chatId, channel) {
|
|
|
12015
12062
|
const modelInfo = adapter.availableModels[pending.model];
|
|
12016
12063
|
if (modelInfo?.thinking === "adjustable" && modelInfo.thinkingLevels) {
|
|
12017
12064
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12018
|
-
await channel.sendText(chatId, `Enter thinking level (${modelInfo.thinkingLevels.join(", ")}):`, "plain");
|
|
12065
|
+
await channel.sendText(chatId, `Enter thinking level (${modelInfo.thinkingLevels.join(", ")}):`, { parseMode: "plain" });
|
|
12019
12066
|
return;
|
|
12020
12067
|
}
|
|
12021
12068
|
const buttons = modelInfo.thinkingLevels.map((level) => [{
|
|
@@ -12031,7 +12078,7 @@ async function promptThinking(chatId, channel) {
|
|
|
12031
12078
|
}
|
|
12032
12079
|
async function promptTimeout(chatId, channel) {
|
|
12033
12080
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12034
|
-
await channel.sendText(chatId, `Job timeout in seconds (${TIMEOUT_MIN_SECONDS}-${TIMEOUT_MAX_SECONDS}), or "default" for ${TIMEOUT_DEFAULT_SECONDS}s:`, "plain");
|
|
12081
|
+
await channel.sendText(chatId, `Job timeout in seconds (${TIMEOUT_MIN_SECONDS}-${TIMEOUT_MAX_SECONDS}), or "default" for ${TIMEOUT_DEFAULT_SECONDS}s:`, { parseMode: "plain" });
|
|
12035
12082
|
return;
|
|
12036
12083
|
}
|
|
12037
12084
|
await channel.sendKeyboard(chatId, "Maximum runtime for this job?", [
|
|
@@ -12048,7 +12095,7 @@ async function promptTimeout(chatId, channel) {
|
|
|
12048
12095
|
}
|
|
12049
12096
|
async function promptSession(chatId, channel) {
|
|
12050
12097
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12051
|
-
await channel.sendText(chatId, "Session type: isolated (fresh, no history) or main (uses conversation context)?", "plain");
|
|
12098
|
+
await channel.sendText(chatId, "Session type: isolated (fresh, no history) or main (uses conversation context)?", { parseMode: "plain" });
|
|
12052
12099
|
return;
|
|
12053
12100
|
}
|
|
12054
12101
|
await channel.sendKeyboard(chatId, "Session type for this job?", [
|
|
@@ -12058,7 +12105,7 @@ async function promptSession(chatId, channel) {
|
|
|
12058
12105
|
}
|
|
12059
12106
|
async function promptDelivery(chatId, channel) {
|
|
12060
12107
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12061
|
-
await channel.sendText(chatId, "Delivery mode: announce (send to chat), webhook (HTTP POST), or none (silent)?", "plain");
|
|
12108
|
+
await channel.sendText(chatId, "Delivery mode: announce (send to chat), webhook (HTTP POST), or none (silent)?", { parseMode: "plain" });
|
|
12062
12109
|
return;
|
|
12063
12110
|
}
|
|
12064
12111
|
await channel.sendKeyboard(chatId, "How should results be delivered?", [
|
|
@@ -12069,13 +12116,13 @@ async function promptDelivery(chatId, channel) {
|
|
|
12069
12116
|
}
|
|
12070
12117
|
async function promptTarget(chatId, channel) {
|
|
12071
12118
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12072
|
-
await channel.sendText(chatId, "Enter the chat ID or group ID for delivery (or send 'this' for this chat):", "plain");
|
|
12119
|
+
await channel.sendText(chatId, "Enter the chat ID or group ID for delivery (or send 'this' for this chat):", { parseMode: "plain" });
|
|
12073
12120
|
return;
|
|
12074
12121
|
}
|
|
12075
12122
|
await channel.sendKeyboard(chatId, "Where should results be sent?", [
|
|
12076
12123
|
[{ label: "This chat", data: "sched:target:this" }]
|
|
12077
12124
|
]);
|
|
12078
|
-
await channel.sendText(chatId, "Or send a chat/group ID (e.g. -100123456789 or -100123456789:topic:42):", "plain");
|
|
12125
|
+
await channel.sendText(chatId, "Or send a chat/group ID (e.g. -100123456789 or -100123456789:topic:42):", { parseMode: "plain" });
|
|
12079
12126
|
}
|
|
12080
12127
|
async function promptConfirm(chatId, channel) {
|
|
12081
12128
|
const pending = pendingJobs.get(chatId);
|
|
@@ -12106,7 +12153,7 @@ async function promptConfirm(chatId, channel) {
|
|
|
12106
12153
|
[{ label: "Edit", data: "sched:edit" }, { label: "Cancel", data: "sched:cancel" }]
|
|
12107
12154
|
]);
|
|
12108
12155
|
} else {
|
|
12109
|
-
await channel.sendText(chatId, lines.join("\n") + "\n\nSend 'confirm' to create or 'cancel' to abort.", "plain");
|
|
12156
|
+
await channel.sendText(chatId, lines.join("\n") + "\n\nSend 'confirm' to create or 'cancel' to abort.", { parseMode: "plain" });
|
|
12110
12157
|
}
|
|
12111
12158
|
}
|
|
12112
12159
|
async function finalizeJob(chatId, channel) {
|
|
@@ -12144,7 +12191,7 @@ async function finalizeJob(chatId, channel) {
|
|
|
12144
12191
|
Task: ${jobParams.description}
|
|
12145
12192
|
Schedule: ${jobParams.cron ?? "N/A"}
|
|
12146
12193
|
Timezone: ${jobParams.timezone}`,
|
|
12147
|
-
"plain"
|
|
12194
|
+
{ parseMode: "plain" }
|
|
12148
12195
|
);
|
|
12149
12196
|
} else {
|
|
12150
12197
|
const job = insertJob({ ...jobParams, chatId });
|
|
@@ -12159,17 +12206,17 @@ Task: ${job.description}
|
|
|
12159
12206
|
Schedule: ${job.cron ?? "N/A"}
|
|
12160
12207
|
Timezone: ${job.timezone}
|
|
12161
12208
|
Next run will be at the scheduled time.`,
|
|
12162
|
-
"plain"
|
|
12209
|
+
{ parseMode: "plain" }
|
|
12163
12210
|
);
|
|
12164
12211
|
}
|
|
12165
12212
|
} catch (err) {
|
|
12166
|
-
await channel.sendText(chatId, `Failed to ${editJobId ? "update" : "create"} job: ${errorMessage(err)}`, "plain");
|
|
12213
|
+
await channel.sendText(chatId, `Failed to ${editJobId ? "update" : "create"} job: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
12167
12214
|
}
|
|
12168
12215
|
}
|
|
12169
12216
|
async function startEditWizard(chatId, jobId, channel) {
|
|
12170
12217
|
const job = getJobById(jobId);
|
|
12171
12218
|
if (!job) {
|
|
12172
|
-
await channel.sendText(chatId, `Job #${jobId} not found.`, "plain");
|
|
12219
|
+
await channel.sendText(chatId, `Job #${jobId} not found.`, { parseMode: "plain" });
|
|
12173
12220
|
return;
|
|
12174
12221
|
}
|
|
12175
12222
|
const pending = {
|
|
@@ -12201,7 +12248,7 @@ Current schedule: ${schedule2}
|
|
|
12201
12248
|
Current task: ${job.description}
|
|
12202
12249
|
|
|
12203
12250
|
Send a new schedule, or type 'keep' to keep the current one:`,
|
|
12204
|
-
"plain"
|
|
12251
|
+
{ parseMode: "plain" }
|
|
12205
12252
|
);
|
|
12206
12253
|
}
|
|
12207
12254
|
var WIZARD_TIMEOUT_MS, wizardTimers, pendingJobs;
|
|
@@ -12521,22 +12568,22 @@ async function handleBackendCommand(command, chatId, channel) {
|
|
|
12521
12568
|
try {
|
|
12522
12569
|
adapter = getAdapterForChat(chatId);
|
|
12523
12570
|
} catch {
|
|
12524
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
12571
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
12525
12572
|
return;
|
|
12526
12573
|
}
|
|
12527
12574
|
const sessionId = getSessionId(chatId);
|
|
12528
12575
|
if (!sessionId) {
|
|
12529
|
-
await channel.sendText(chatId, "No active session. Start a conversation first.", "plain");
|
|
12576
|
+
await channel.sendText(chatId, "No active session. Start a conversation first.", { parseMode: "plain" });
|
|
12530
12577
|
return;
|
|
12531
12578
|
}
|
|
12532
12579
|
const cwd = getCwd(chatId) ?? `${process.env.HOME ?? "/tmp"}/.cc-claw/workspace`;
|
|
12533
12580
|
try {
|
|
12534
12581
|
const output2 = await spawnBackendCommand(adapter, command, sessionId, cwd);
|
|
12535
12582
|
const formatted = buildNativeResponse(adapter.id, command, output2);
|
|
12536
|
-
await channel.sendText(chatId, formatted, "html");
|
|
12583
|
+
await channel.sendText(chatId, formatted, { parseMode: "html" });
|
|
12537
12584
|
} catch (err) {
|
|
12538
12585
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12539
|
-
await channel.sendText(chatId, `Backend command failed: ${msg}`, "plain");
|
|
12586
|
+
await channel.sendText(chatId, `Backend command failed: ${msg}`, { parseMode: "plain" });
|
|
12540
12587
|
}
|
|
12541
12588
|
}
|
|
12542
12589
|
function spawnBackendCommand(adapter, command, sessionId, cwd) {
|
|
@@ -12620,6 +12667,7 @@ var init_pagination = __esm({
|
|
|
12620
12667
|
var propose_exports = {};
|
|
12621
12668
|
__export(propose_exports, {
|
|
12622
12669
|
buildEvolveMenuKeyboard: () => buildEvolveMenuKeyboard,
|
|
12670
|
+
buildEvolveOnboardingKeyboard: () => buildEvolveOnboardingKeyboard,
|
|
12623
12671
|
buildModelKeyboard: () => buildModelKeyboard,
|
|
12624
12672
|
buildProposalKeyboard: () => buildProposalKeyboard,
|
|
12625
12673
|
buildUndoKeyboard: () => buildUndoKeyboard,
|
|
@@ -12699,20 +12747,27 @@ function buildProposalKeyboard(insightId, category) {
|
|
|
12699
12747
|
]
|
|
12700
12748
|
];
|
|
12701
12749
|
}
|
|
12702
|
-
function
|
|
12750
|
+
function buildEvolveOnboardingKeyboard() {
|
|
12751
|
+
return [
|
|
12752
|
+
[{ label: "\u2705 Enable Self-Learning", data: "evolve:toggle", style: "success" }],
|
|
12753
|
+
[{ label: "One-Time Analysis", data: "evolve:analyze" }]
|
|
12754
|
+
];
|
|
12755
|
+
}
|
|
12756
|
+
function buildEvolveMenuKeyboard(ctx) {
|
|
12757
|
+
const reviewLabel = ctx.pendingProposals > 0 ? `Review (${ctx.pendingProposals})` : "Review";
|
|
12703
12758
|
return [
|
|
12704
12759
|
[
|
|
12705
|
-
{ label: "Analyze Now", data: "evolve:analyze", style: "success" },
|
|
12706
|
-
{ label: "
|
|
12760
|
+
{ label: "\u{1F50D} Analyze Now", data: "evolve:analyze", style: "success" },
|
|
12761
|
+
ctx.pendingProposals > 0 ? { label: reviewLabel, data: "evolve:review", style: "primary" } : { label: reviewLabel, data: "evolve:review" }
|
|
12707
12762
|
],
|
|
12708
12763
|
[
|
|
12709
12764
|
{ label: "Stats", data: "evolve:stats" },
|
|
12710
12765
|
{ label: "History", data: "evolve:history" }
|
|
12711
12766
|
],
|
|
12712
12767
|
[
|
|
12713
|
-
{ label: "
|
|
12768
|
+
{ label: "Model", data: "evolve:model" },
|
|
12714
12769
|
{ label: "Undo", data: "evolve:undo", style: "danger" },
|
|
12715
|
-
{ label: "
|
|
12770
|
+
{ label: "\u23F8 Disable", data: "evolve:toggle", style: "danger" }
|
|
12716
12771
|
]
|
|
12717
12772
|
];
|
|
12718
12773
|
}
|
|
@@ -12743,6 +12798,7 @@ var init_propose = __esm({
|
|
|
12743
12798
|
|
|
12744
12799
|
// src/router.ts
|
|
12745
12800
|
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
|
|
12801
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
12746
12802
|
import { resolve as resolvePath, join as join19 } from "path";
|
|
12747
12803
|
function parseMcpListOutput(output2) {
|
|
12748
12804
|
const results = [];
|
|
@@ -12941,7 +12997,7 @@ async function sendUnifiedUsage(chatId, channel, view) {
|
|
|
12941
12997
|
];
|
|
12942
12998
|
await channel.sendKeyboard(chatId, lines.join("\n"), buttons);
|
|
12943
12999
|
} else {
|
|
12944
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13000
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
12945
13001
|
}
|
|
12946
13002
|
}
|
|
12947
13003
|
async function sendUsageLimits(chatId, channel) {
|
|
@@ -12975,7 +13031,7 @@ async function sendUsageLimits(chatId, channel) {
|
|
|
12975
13031
|
]);
|
|
12976
13032
|
await channel.sendKeyboard(chatId, lines.join("\n"), rows);
|
|
12977
13033
|
} else {
|
|
12978
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13034
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
12979
13035
|
}
|
|
12980
13036
|
}
|
|
12981
13037
|
function getMediaRetentionMs() {
|
|
@@ -13034,6 +13090,22 @@ function pickFallbackEmoji(userMessage) {
|
|
|
13034
13090
|
}
|
|
13035
13091
|
return "\u{1F44D}";
|
|
13036
13092
|
}
|
|
13093
|
+
function parseSideQuestPrefix(text) {
|
|
13094
|
+
const match = text.match(/^(?:sq|btw):\s*/i);
|
|
13095
|
+
if (match) return { isSideQuest: true, cleanText: text.slice(match[0].length) };
|
|
13096
|
+
return { isSideQuest: false, cleanText: text };
|
|
13097
|
+
}
|
|
13098
|
+
function getActiveSideQuestCount(chatId) {
|
|
13099
|
+
return activeSideQuests.get(chatId)?.size ?? 0;
|
|
13100
|
+
}
|
|
13101
|
+
function stopAllSideQuests(chatId) {
|
|
13102
|
+
const active = activeSideQuests.get(chatId);
|
|
13103
|
+
if (active) {
|
|
13104
|
+
for (const sqId of active) {
|
|
13105
|
+
stopAgent(sqId);
|
|
13106
|
+
}
|
|
13107
|
+
}
|
|
13108
|
+
}
|
|
13037
13109
|
async function handleResponseExhaustion(responseText, chatId, msg, channel) {
|
|
13038
13110
|
const raw = responseText.replace(/\n\n🧠 \[.+$/, "").trim();
|
|
13039
13111
|
if (raw.length > 300 || !isExhaustedMessage(raw)) return false;
|
|
@@ -13122,7 +13194,7 @@ async function handleCommand(msg, channel) {
|
|
|
13122
13194
|
([cat, cmds]) => `${cat}:
|
|
13123
13195
|
${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
13124
13196
|
).join("\n\n"),
|
|
13125
|
-
"plain"
|
|
13197
|
+
{ parseMode: "plain" }
|
|
13126
13198
|
);
|
|
13127
13199
|
}
|
|
13128
13200
|
break;
|
|
@@ -13141,17 +13213,18 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13141
13213
|
await channel.sendText(
|
|
13142
13214
|
chatId,
|
|
13143
13215
|
"CC-Claw Menu:\n/newchat \xB7 /status \xB7 /backend \xB7 /model\n/jobs \xB7 /memory \xB7 /history \xB7 /help",
|
|
13144
|
-
"plain"
|
|
13216
|
+
{ parseMode: "plain" }
|
|
13145
13217
|
);
|
|
13146
13218
|
}
|
|
13147
13219
|
break;
|
|
13148
13220
|
}
|
|
13149
13221
|
case "stop": {
|
|
13150
13222
|
const stopped = stopAgent(chatId);
|
|
13223
|
+
stopAllSideQuests(chatId);
|
|
13151
13224
|
await channel.sendText(
|
|
13152
13225
|
chatId,
|
|
13153
13226
|
stopped ? "Stopping current task..." : "Nothing is running.",
|
|
13154
|
-
"plain"
|
|
13227
|
+
{ parseMode: "plain" }
|
|
13155
13228
|
);
|
|
13156
13229
|
if (stopped && typeof channel.sendKeyboard === "function") {
|
|
13157
13230
|
await channel.sendKeyboard(chatId, "", [
|
|
@@ -13174,7 +13247,7 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13174
13247
|
for (const [id, label2] of Object.entries(PERM_MODES)) {
|
|
13175
13248
|
lines.push(`${id === currentMode ? "\u2713 " : " "}/permissions ${id} \u2014 ${label2}`);
|
|
13176
13249
|
}
|
|
13177
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13250
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13178
13251
|
}
|
|
13179
13252
|
break;
|
|
13180
13253
|
}
|
|
@@ -13191,7 +13264,7 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13191
13264
|
const lines = Object.entries(VERBOSE_LEVELS).map(
|
|
13192
13265
|
([id, label2]) => `${id === currentVerbose ? "\u2713 " : " "}${id} \u2014 ${label2}`
|
|
13193
13266
|
);
|
|
13194
|
-
await channel.sendText(chatId, ["Tool visibility:", "", ...lines].join("\n"), "plain");
|
|
13267
|
+
await channel.sendText(chatId, ["Tool visibility:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13195
13268
|
}
|
|
13196
13269
|
break;
|
|
13197
13270
|
}
|
|
@@ -13218,12 +13291,13 @@ Tap to toggle:`,
|
|
|
13218
13291
|
);
|
|
13219
13292
|
} else {
|
|
13220
13293
|
const lines = ALL_TOOLS.map((t) => `${toolsMap[t] ? "[on] " : "[off]"} ${t}`);
|
|
13221
|
-
await channel.sendText(chatId, ["Allowed tools:", "", ...lines].join("\n"), "plain");
|
|
13294
|
+
await channel.sendText(chatId, ["Allowed tools:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13222
13295
|
}
|
|
13223
13296
|
break;
|
|
13224
13297
|
}
|
|
13225
13298
|
case "new":
|
|
13226
13299
|
case "newchat": {
|
|
13300
|
+
stopAllSideQuests(chatId);
|
|
13227
13301
|
const oldSessionId = getSessionId(chatId);
|
|
13228
13302
|
const exchangeCount = getMessagePairCount(chatId);
|
|
13229
13303
|
const summarized = await summarizeSession(chatId);
|
|
@@ -13247,7 +13321,7 @@ Tap to toggle:`,
|
|
|
13247
13321
|
}
|
|
13248
13322
|
} else {
|
|
13249
13323
|
const msg2 = summarized ? "Session summarized and saved. Fresh conversation started!" : "Fresh conversation started. What's on your mind?";
|
|
13250
|
-
await channel.sendText(chatId, msg2, "plain");
|
|
13324
|
+
await channel.sendText(chatId, msg2, { parseMode: "plain" });
|
|
13251
13325
|
}
|
|
13252
13326
|
break;
|
|
13253
13327
|
}
|
|
@@ -13255,12 +13329,12 @@ Tap to toggle:`,
|
|
|
13255
13329
|
if (commandArgs?.toLowerCase() === "all") {
|
|
13256
13330
|
const pendingIds = getLoggedChatIds();
|
|
13257
13331
|
if (pendingIds.length === 0) {
|
|
13258
|
-
await channel.sendText(chatId, "No pending sessions to summarize.", "plain");
|
|
13332
|
+
await channel.sendText(chatId, "No pending sessions to summarize.", { parseMode: "plain" });
|
|
13259
13333
|
break;
|
|
13260
13334
|
}
|
|
13261
|
-
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, "plain");
|
|
13335
|
+
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, { parseMode: "plain" });
|
|
13262
13336
|
await summarizeAllPending();
|
|
13263
|
-
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, "plain");
|
|
13337
|
+
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, { parseMode: "plain" });
|
|
13264
13338
|
} else {
|
|
13265
13339
|
const pairs = getMessagePairCount(chatId);
|
|
13266
13340
|
if (pairs < 2) {
|
|
@@ -13268,16 +13342,16 @@ Tap to toggle:`,
|
|
|
13268
13342
|
await channel.sendText(
|
|
13269
13343
|
chatId,
|
|
13270
13344
|
"Session log was cleared (auto-compact or service restart). Your conversation history is preserved in episodic memory. Continue chatting normally, or use /newchat to start fresh.",
|
|
13271
|
-
"plain"
|
|
13345
|
+
{ parseMode: "plain" }
|
|
13272
13346
|
);
|
|
13273
13347
|
} else {
|
|
13274
|
-
await channel.sendText(chatId, "Not enough conversation to summarize (need at least 2 exchanges).", "plain");
|
|
13348
|
+
await channel.sendText(chatId, "Not enough conversation to summarize (need at least 2 exchanges).", { parseMode: "plain" });
|
|
13275
13349
|
}
|
|
13276
13350
|
break;
|
|
13277
13351
|
}
|
|
13278
13352
|
const progressMsgId = await channel.sendTextReturningId?.(chatId, `Summarizing ${pairs} exchanges...`, "plain");
|
|
13279
13353
|
if (!progressMsgId) {
|
|
13280
|
-
await channel.sendText(chatId, `Summarizing ${pairs} exchanges...`, "plain");
|
|
13354
|
+
await channel.sendText(chatId, `Summarizing ${pairs} exchanges...`, { parseMode: "plain" });
|
|
13281
13355
|
}
|
|
13282
13356
|
const success2 = await summarizeSession(chatId);
|
|
13283
13357
|
if (success2) {
|
|
@@ -13311,14 +13385,14 @@ Tap to toggle:`,
|
|
|
13311
13385
|
}
|
|
13312
13386
|
}
|
|
13313
13387
|
} else {
|
|
13314
|
-
await channel.sendText(chatId, doneText, "plain");
|
|
13388
|
+
await channel.sendText(chatId, doneText, { parseMode: "plain" });
|
|
13315
13389
|
}
|
|
13316
13390
|
} else {
|
|
13317
13391
|
const failText = "Summarization failed. Session log preserved for retry.";
|
|
13318
13392
|
if (progressMsgId) {
|
|
13319
13393
|
await channel.editText?.(chatId, progressMsgId, failText, "plain");
|
|
13320
13394
|
} else {
|
|
13321
|
-
await channel.sendText(chatId, failText, "plain");
|
|
13395
|
+
await channel.sendText(chatId, failText, { parseMode: "plain" });
|
|
13322
13396
|
}
|
|
13323
13397
|
}
|
|
13324
13398
|
}
|
|
@@ -13383,6 +13457,7 @@ Tap to toggle:`,
|
|
|
13383
13457
|
const iQuick = iStats.chat;
|
|
13384
13458
|
const iDeep = iStats.agentic;
|
|
13385
13459
|
const intentLine = iTotal > 0 ? `\u26A1 ${iTotal} messages: ${iQuick} quick, ${iDeep} deep` : `\u26A1 No messages classified yet`;
|
|
13460
|
+
const sqCount = getActiveSideQuestCount(chatId);
|
|
13386
13461
|
const lines = [
|
|
13387
13462
|
`\u{1F43E} CC-Claw v${VERSION}`,
|
|
13388
13463
|
`\u23F1 Uptime: ${uptimeStr}`,
|
|
@@ -13397,6 +13472,7 @@ Tap to toggle:`,
|
|
|
13397
13472
|
`\u{1F4CB} ${sessionId ? sessionId.slice(0, 12) + "..." : "no active session"}`,
|
|
13398
13473
|
`\u{1F4C1} ${cwd ?? "default workspace"}`,
|
|
13399
13474
|
`\u{1F4D0} Context: ${ctxBar} ${usedK}K/${maxK}K (${contextPct.toFixed(1)}%)`,
|
|
13475
|
+
...sqCount > 0 ? [`\u{1F5FA} Side quests: ${sqCount} active`] : [],
|
|
13400
13476
|
``,
|
|
13401
13477
|
buildSectionHeader("Usage"),
|
|
13402
13478
|
`\u{1F4E8} ${usage2.request_count} requests \xB7 ${(usage2.input_tokens / 1e3).toFixed(0)}K in \xB7 ${(usage2.output_tokens / 1e3).toFixed(0)}K out`,
|
|
@@ -13418,7 +13494,7 @@ Tap to toggle:`,
|
|
|
13418
13494
|
]
|
|
13419
13495
|
]);
|
|
13420
13496
|
} else {
|
|
13421
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13497
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13422
13498
|
}
|
|
13423
13499
|
break;
|
|
13424
13500
|
}
|
|
@@ -13441,7 +13517,7 @@ Tap to toggle:`,
|
|
|
13441
13517
|
const lines = adapters2.map(
|
|
13442
13518
|
(a) => `${a.id === currentBackend ? "\u2713 " : " "}${a.displayName} (/backend ${a.id})`
|
|
13443
13519
|
);
|
|
13444
|
-
await channel.sendText(chatId, ["Available backends:", "", ...lines].join("\n"), "plain");
|
|
13520
|
+
await channel.sendText(chatId, ["Available backends:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13445
13521
|
}
|
|
13446
13522
|
break;
|
|
13447
13523
|
}
|
|
@@ -13452,14 +13528,14 @@ Tap to toggle:`,
|
|
|
13452
13528
|
if (getAllBackendIds().includes(backendId)) {
|
|
13453
13529
|
await sendBackendSwitchConfirmation(chatId, backendId, channel);
|
|
13454
13530
|
} else {
|
|
13455
|
-
await channel.sendText(chatId, `Backend "${command}" is not available.`, "plain");
|
|
13531
|
+
await channel.sendText(chatId, `Backend "${command}" is not available.`, { parseMode: "plain" });
|
|
13456
13532
|
}
|
|
13457
13533
|
break;
|
|
13458
13534
|
}
|
|
13459
13535
|
case "gemini_accounts": {
|
|
13460
13536
|
const slots = getGeminiSlots();
|
|
13461
13537
|
if (slots.length === 0) {
|
|
13462
|
-
await channel.sendText(chatId, "No Gemini credentials configured.\nAdd with: <code>cc-claw gemini add-key</code> or <code>cc-claw gemini add-account</code>", "html");
|
|
13538
|
+
await channel.sendText(chatId, "No Gemini credentials configured.\nAdd with: <code>cc-claw gemini add-key</code> or <code>cc-claw gemini add-account</code>", { parseMode: "html" });
|
|
13463
13539
|
break;
|
|
13464
13540
|
}
|
|
13465
13541
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13493,7 +13569,7 @@ Tap to toggle:`,
|
|
|
13493
13569
|
${list}
|
|
13494
13570
|
|
|
13495
13571
|
Rotation mode: ${currentMode}
|
|
13496
|
-
Use: /gemini_accounts <name> to pin`, "plain");
|
|
13572
|
+
Use: /gemini_accounts <name> to pin`, { parseMode: "plain" });
|
|
13497
13573
|
}
|
|
13498
13574
|
break;
|
|
13499
13575
|
}
|
|
@@ -13502,7 +13578,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13502
13578
|
if (getAllBackendIds().includes(backendId)) {
|
|
13503
13579
|
await sendBackendSwitchConfirmation(chatId, backendId, channel);
|
|
13504
13580
|
} else {
|
|
13505
|
-
await channel.sendText(chatId, `Backend "${command}" is not available.`, "plain");
|
|
13581
|
+
await channel.sendText(chatId, `Backend "${command}" is not available.`, { parseMode: "plain" });
|
|
13506
13582
|
}
|
|
13507
13583
|
break;
|
|
13508
13584
|
}
|
|
@@ -13511,7 +13587,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13511
13587
|
try {
|
|
13512
13588
|
adapter = getAdapterForChat(chatId);
|
|
13513
13589
|
} catch {
|
|
13514
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
13590
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
13515
13591
|
break;
|
|
13516
13592
|
}
|
|
13517
13593
|
const models = adapter.availableModels;
|
|
@@ -13530,7 +13606,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13530
13606
|
const lines = Object.entries(models).map(
|
|
13531
13607
|
([id, info]) => `${id === current ? "\u2713 " : " "}${id} \u2014 ${info.label}`
|
|
13532
13608
|
);
|
|
13533
|
-
await channel.sendText(chatId, [`Models (${adapter.displayName}):`, "", ...lines].join("\n"), "plain");
|
|
13609
|
+
await channel.sendText(chatId, [`Models (${adapter.displayName}):`, "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13534
13610
|
}
|
|
13535
13611
|
break;
|
|
13536
13612
|
}
|
|
@@ -13562,7 +13638,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13562
13638
|
} else {
|
|
13563
13639
|
await channel.sendText(chatId, `Summarizer: ${currentLabel}
|
|
13564
13640
|
|
|
13565
|
-
Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain");
|
|
13641
|
+
Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, { parseMode: "plain" });
|
|
13566
13642
|
}
|
|
13567
13643
|
break;
|
|
13568
13644
|
}
|
|
@@ -13574,24 +13650,24 @@ Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain
|
|
|
13574
13650
|
if (parts.length >= 3) {
|
|
13575
13651
|
const [bk, win, val] = parts;
|
|
13576
13652
|
if (!getAllBackendIds().includes(bk)) {
|
|
13577
|
-
await channel.sendText(chatId, `Unknown backend: ${bk}. Available: ${getAllBackendIds().join(", ")}`, "plain");
|
|
13653
|
+
await channel.sendText(chatId, `Unknown backend: ${bk}. Available: ${getAllBackendIds().join(", ")}`, { parseMode: "plain" });
|
|
13578
13654
|
break;
|
|
13579
13655
|
}
|
|
13580
13656
|
if (!["hourly", "daily", "weekly"].includes(win)) {
|
|
13581
|
-
await channel.sendText(chatId, "Window must be: hourly, daily, or weekly", "plain");
|
|
13657
|
+
await channel.sendText(chatId, "Window must be: hourly, daily, or weekly", { parseMode: "plain" });
|
|
13582
13658
|
break;
|
|
13583
13659
|
}
|
|
13584
13660
|
if (val === "off") {
|
|
13585
13661
|
clearBackendLimit(bk, win);
|
|
13586
|
-
await channel.sendText(chatId, `Limit removed for ${bk} (${win}).`, "plain");
|
|
13662
|
+
await channel.sendText(chatId, `Limit removed for ${bk} (${win}).`, { parseMode: "plain" });
|
|
13587
13663
|
} else {
|
|
13588
13664
|
const tokens = parseInt(val, 10);
|
|
13589
13665
|
if (isNaN(tokens) || tokens <= 0) {
|
|
13590
|
-
await channel.sendText(chatId, "Token limit must be a positive number.", "plain");
|
|
13666
|
+
await channel.sendText(chatId, "Token limit must be a positive number.", { parseMode: "plain" });
|
|
13591
13667
|
break;
|
|
13592
13668
|
}
|
|
13593
13669
|
setBackendLimit(bk, win, tokens);
|
|
13594
|
-
await channel.sendText(chatId, `Limit set: ${bk} (${win}) = ${(tokens / 1e3).toFixed(0)}K input tokens`, "plain");
|
|
13670
|
+
await channel.sendText(chatId, `Limit set: ${bk} (${win}) = ${(tokens / 1e3).toFixed(0)}K input tokens`, { parseMode: "plain" });
|
|
13595
13671
|
}
|
|
13596
13672
|
break;
|
|
13597
13673
|
}
|
|
@@ -13609,7 +13685,7 @@ Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain
|
|
|
13609
13685
|
current ? `Working directory: ${current}
|
|
13610
13686
|
|
|
13611
13687
|
No saved bookmarks yet. Set a directory with /cwd <path> to auto-save.` : "No working directory set. Usage: /cwd ~/projects/my-app",
|
|
13612
|
-
"plain"
|
|
13688
|
+
{ parseMode: "plain" }
|
|
13613
13689
|
);
|
|
13614
13690
|
return;
|
|
13615
13691
|
}
|
|
@@ -13622,46 +13698,46 @@ Recent directories:` : "Recent directories:";
|
|
|
13622
13698
|
} else {
|
|
13623
13699
|
const list = recents.map((r) => ` ${r.alias} \u2192 ${r.path}`).join("\n");
|
|
13624
13700
|
await channel.sendText(chatId, `${text}
|
|
13625
|
-
${list}`, "plain");
|
|
13701
|
+
${list}`, { parseMode: "plain" });
|
|
13626
13702
|
}
|
|
13627
13703
|
return;
|
|
13628
13704
|
}
|
|
13629
13705
|
if (commandArgs === "reset" || commandArgs === "clear") {
|
|
13630
13706
|
clearCwd(chatId);
|
|
13631
|
-
await channel.sendText(chatId, "Working directory cleared. Using default.", "plain");
|
|
13707
|
+
await channel.sendText(chatId, "Working directory cleared. Using default.", { parseMode: "plain" });
|
|
13632
13708
|
return;
|
|
13633
13709
|
}
|
|
13634
13710
|
if (commandArgs === "aliases") {
|
|
13635
13711
|
const all = getAllBookmarks(chatId);
|
|
13636
13712
|
if (all.length === 0) {
|
|
13637
|
-
await channel.sendText(chatId, "No bookmarks saved yet.", "plain");
|
|
13713
|
+
await channel.sendText(chatId, "No bookmarks saved yet.", { parseMode: "plain" });
|
|
13638
13714
|
return;
|
|
13639
13715
|
}
|
|
13640
13716
|
const lines = all.map((b) => ` ${b.manual ? "[manual]" : "[auto]"} ${b.alias} \u2192 ${b.path}`);
|
|
13641
13717
|
await channel.sendText(chatId, `Directory bookmarks:
|
|
13642
|
-
${lines.join("\n")}`, "plain");
|
|
13718
|
+
${lines.join("\n")}`, { parseMode: "plain" });
|
|
13643
13719
|
return;
|
|
13644
13720
|
}
|
|
13645
13721
|
if (commandArgs.startsWith("unalias ")) {
|
|
13646
13722
|
const aliasName = commandArgs.slice(8).trim();
|
|
13647
13723
|
if (!aliasName) {
|
|
13648
|
-
await channel.sendText(chatId, "Usage: /cwd unalias <name>", "plain");
|
|
13724
|
+
await channel.sendText(chatId, "Usage: /cwd unalias <name>", { parseMode: "plain" });
|
|
13649
13725
|
return;
|
|
13650
13726
|
}
|
|
13651
13727
|
const deleted = deleteBookmark(chatId, aliasName);
|
|
13652
|
-
await channel.sendText(chatId, deleted ? `Bookmark '${aliasName}' removed.` : `Bookmark '${aliasName}' not found.`, "plain");
|
|
13728
|
+
await channel.sendText(chatId, deleted ? `Bookmark '${aliasName}' removed.` : `Bookmark '${aliasName}' not found.`, { parseMode: "plain" });
|
|
13653
13729
|
return;
|
|
13654
13730
|
}
|
|
13655
13731
|
if (commandArgs.startsWith("alias ")) {
|
|
13656
13732
|
const parts = commandArgs.slice(6).trim().split(/\s+/);
|
|
13657
13733
|
if (parts.length < 2) {
|
|
13658
|
-
await channel.sendText(chatId, "Usage: /cwd alias <name> <path>", "plain");
|
|
13734
|
+
await channel.sendText(chatId, "Usage: /cwd alias <name> <path>", { parseMode: "plain" });
|
|
13659
13735
|
return;
|
|
13660
13736
|
}
|
|
13661
13737
|
const [aliasName, ...pathParts] = parts;
|
|
13662
13738
|
const aliasPath = pathParts.join(" ").replace(/^~/, process.env.HOME ?? "");
|
|
13663
13739
|
upsertBookmark(chatId, aliasName, aliasPath, true);
|
|
13664
|
-
await channel.sendText(chatId, `Bookmark saved: ${aliasName} \u2192 ${aliasPath}`, "plain");
|
|
13740
|
+
await channel.sendText(chatId, `Bookmark saved: ${aliasName} \u2192 ${aliasPath}`, { parseMode: "plain" });
|
|
13665
13741
|
return;
|
|
13666
13742
|
}
|
|
13667
13743
|
const arg = commandArgs;
|
|
@@ -13695,31 +13771,31 @@ ${lines.join("\n")}`, "plain");
|
|
|
13695
13771
|
await channel.sendKeyboard(chatId, `Multiple matches for "${arg}":`, buttons);
|
|
13696
13772
|
return;
|
|
13697
13773
|
}
|
|
13698
|
-
await channel.sendText(chatId, `Directory alias '${arg}' not found. Use /cwd aliases to see saved bookmarks.`, "plain");
|
|
13774
|
+
await channel.sendText(chatId, `Directory alias '${arg}' not found. Use /cwd aliases to see saved bookmarks.`, { parseMode: "plain" });
|
|
13699
13775
|
break;
|
|
13700
13776
|
}
|
|
13701
13777
|
case "memory": {
|
|
13702
13778
|
if (commandArgs?.startsWith("edit ")) {
|
|
13703
13779
|
const editMatch = commandArgs.match(/^edit\s+(\d+)\s+(.+)/);
|
|
13704
13780
|
if (!editMatch) {
|
|
13705
|
-
await channel.sendText(chatId, "Usage: /memory edit <id> <new content>", "plain");
|
|
13781
|
+
await channel.sendText(chatId, "Usage: /memory edit <id> <new content>", { parseMode: "plain" });
|
|
13706
13782
|
break;
|
|
13707
13783
|
}
|
|
13708
13784
|
const editId = parseInt(editMatch[1], 10);
|
|
13709
13785
|
const newContent = editMatch[2];
|
|
13710
13786
|
const mem = getMemoryById(editId);
|
|
13711
13787
|
if (!mem) {
|
|
13712
|
-
await channel.sendText(chatId, "Memory not found.", "plain");
|
|
13788
|
+
await channel.sendText(chatId, "Memory not found.", { parseMode: "plain" });
|
|
13713
13789
|
break;
|
|
13714
13790
|
}
|
|
13715
13791
|
deleteMemoryById(editId);
|
|
13716
13792
|
saveMemoryWithEmbedding(mem.trigger, newContent, mem.type);
|
|
13717
|
-
await channel.sendText(chatId, `Memory #${editId} updated.`, "plain");
|
|
13793
|
+
await channel.sendText(chatId, `Memory #${editId} updated.`, { parseMode: "plain" });
|
|
13718
13794
|
break;
|
|
13719
13795
|
}
|
|
13720
13796
|
const memories = listMemories();
|
|
13721
13797
|
if (memories.length === 0) {
|
|
13722
|
-
await channel.sendText(chatId, "No memories stored yet.", "plain");
|
|
13798
|
+
await channel.sendText(chatId, "No memories stored yet.", { parseMode: "plain" });
|
|
13723
13799
|
return;
|
|
13724
13800
|
}
|
|
13725
13801
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13728,19 +13804,19 @@ ${lines.join("\n")}`, "plain");
|
|
|
13728
13804
|
const lines = memories.map(
|
|
13729
13805
|
(m) => `- ${m.trigger}: ${m.content} (salience: ${m.salience.toFixed(2)})`
|
|
13730
13806
|
);
|
|
13731
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13807
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13732
13808
|
}
|
|
13733
13809
|
break;
|
|
13734
13810
|
}
|
|
13735
13811
|
case "remember": {
|
|
13736
13812
|
if (!commandArgs) {
|
|
13737
|
-
await channel.sendText(chatId, "Usage: /remember <text>", "plain");
|
|
13813
|
+
await channel.sendText(chatId, "Usage: /remember <text>", { parseMode: "plain" });
|
|
13738
13814
|
return;
|
|
13739
13815
|
}
|
|
13740
13816
|
const content = commandArgs.replace(/^that\s+/i, "");
|
|
13741
13817
|
const trigger = content.split(/\s+/).slice(0, 3).join(" ");
|
|
13742
13818
|
saveMemoryWithEmbedding(trigger, content, "semantic");
|
|
13743
|
-
await channel.sendText(chatId, "Got it, I'll remember that.", "plain");
|
|
13819
|
+
await channel.sendText(chatId, "Got it, I'll remember that.", { parseMode: "plain" });
|
|
13744
13820
|
if (typeof channel.sendKeyboard === "function") {
|
|
13745
13821
|
await channel.sendKeyboard(chatId, "", [
|
|
13746
13822
|
[{ label: "\u{1F4DA} View Memories", data: "menu:memory" }]
|
|
@@ -13750,14 +13826,14 @@ ${lines.join("\n")}`, "plain");
|
|
|
13750
13826
|
}
|
|
13751
13827
|
case "forget": {
|
|
13752
13828
|
if (!commandArgs) {
|
|
13753
|
-
await channel.sendText(chatId, "Usage: /forget <keyword>", "plain");
|
|
13829
|
+
await channel.sendText(chatId, "Usage: /forget <keyword>", { parseMode: "plain" });
|
|
13754
13830
|
return;
|
|
13755
13831
|
}
|
|
13756
13832
|
const count = forgetMemory(commandArgs);
|
|
13757
13833
|
await channel.sendText(
|
|
13758
13834
|
chatId,
|
|
13759
13835
|
count > 0 ? `Forgot ${count} memory(ies) matching "${commandArgs}".` : `No memories found matching "${commandArgs}".`,
|
|
13760
|
-
"plain"
|
|
13836
|
+
{ parseMode: "plain" }
|
|
13761
13837
|
);
|
|
13762
13838
|
break;
|
|
13763
13839
|
}
|
|
@@ -13772,7 +13848,7 @@ ${lines.join("\n")}`, "plain");
|
|
|
13772
13848
|
]);
|
|
13773
13849
|
} else {
|
|
13774
13850
|
const toggled = toggleVoice(chatId);
|
|
13775
|
-
await channel.sendText(chatId, toggled ? "Voice responses enabled." : "Voice responses disabled.", "plain");
|
|
13851
|
+
await channel.sendText(chatId, toggled ? "Voice responses enabled." : "Voice responses disabled.", { parseMode: "plain" });
|
|
13776
13852
|
}
|
|
13777
13853
|
break;
|
|
13778
13854
|
}
|
|
@@ -13791,7 +13867,7 @@ ${lines.join("\n")}`, "plain");
|
|
|
13791
13867
|
]
|
|
13792
13868
|
]);
|
|
13793
13869
|
} else {
|
|
13794
|
-
await channel.sendText(chatId, `Current Response Style: ${currentStyle}`, "plain");
|
|
13870
|
+
await channel.sendText(chatId, `Current Response Style: ${currentStyle}`, { parseMode: "plain" });
|
|
13795
13871
|
}
|
|
13796
13872
|
break;
|
|
13797
13873
|
}
|
|
@@ -13808,7 +13884,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13808
13884
|
} else {
|
|
13809
13885
|
const newSig = currentSig === "on" ? "off" : "on";
|
|
13810
13886
|
setModelSignature(chatId, newSig);
|
|
13811
|
-
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", "plain");
|
|
13887
|
+
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", { parseMode: "plain" });
|
|
13812
13888
|
}
|
|
13813
13889
|
break;
|
|
13814
13890
|
}
|
|
@@ -13818,7 +13894,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13818
13894
|
try {
|
|
13819
13895
|
adapter = getAdapterForChat(chatId);
|
|
13820
13896
|
} catch {
|
|
13821
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
13897
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
13822
13898
|
break;
|
|
13823
13899
|
}
|
|
13824
13900
|
const currentModel = getModel(chatId) ?? adapter.defaultModel;
|
|
@@ -13826,7 +13902,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13826
13902
|
const currentLevel = getThinkingLevel(chatId) || "auto";
|
|
13827
13903
|
if (!modelInfo || modelInfo.thinking !== "adjustable" || !modelInfo.thinkingLevels) {
|
|
13828
13904
|
await channel.sendText(chatId, `Current model (${shortModelName(currentModel)}) doesn't support adjustable thinking.
|
|
13829
|
-
Use /model to pick a model with \u26A1 thinking support.`, "plain");
|
|
13905
|
+
Use /model to pick a model with \u26A1 thinking support.`, { parseMode: "plain" });
|
|
13830
13906
|
break;
|
|
13831
13907
|
}
|
|
13832
13908
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13844,31 +13920,31 @@ Current: ${capitalize(currentLevel)}`,
|
|
|
13844
13920
|
} else {
|
|
13845
13921
|
await channel.sendText(chatId, `Thinking: ${capitalize(currentLevel)}
|
|
13846
13922
|
Levels: ${modelInfo.thinkingLevels.join(", ")}
|
|
13847
|
-
Set via callback (keyboard required).`, "plain");
|
|
13923
|
+
Set via callback (keyboard required).`, { parseMode: "plain" });
|
|
13848
13924
|
}
|
|
13849
13925
|
break;
|
|
13850
13926
|
}
|
|
13851
13927
|
case "imagine":
|
|
13852
13928
|
case "image": {
|
|
13853
13929
|
if (!commandArgs) {
|
|
13854
|
-
await channel.sendText(chatId, "Usage: /imagine <prompt>\nExample: /imagine a cat astronaut on Mars", "plain");
|
|
13930
|
+
await channel.sendText(chatId, "Usage: /imagine <prompt>\nExample: /imagine a cat astronaut on Mars", { parseMode: "plain" });
|
|
13855
13931
|
return;
|
|
13856
13932
|
}
|
|
13857
13933
|
if (!isImageGenAvailable()) {
|
|
13858
|
-
await channel.sendText(chatId, "Image generation requires GEMINI_API_KEY. Configure it in ~/.cc-claw/.env", "plain");
|
|
13934
|
+
await channel.sendText(chatId, "Image generation requires GEMINI_API_KEY. Configure it in ~/.cc-claw/.env", { parseMode: "plain" });
|
|
13859
13935
|
return;
|
|
13860
13936
|
}
|
|
13861
|
-
await channel.sendText(chatId, "\u{1F3A8} Generating image\u2026", "plain");
|
|
13937
|
+
await channel.sendText(chatId, "\u{1F3A8} Generating image\u2026", { parseMode: "plain" });
|
|
13862
13938
|
try {
|
|
13863
13939
|
const result = await generateImage(commandArgs);
|
|
13864
13940
|
const file = await readFile5(result.filePath);
|
|
13865
13941
|
const name = result.filePath.split("/").pop() ?? "image.png";
|
|
13866
13942
|
await channel.sendFile(chatId, file, name);
|
|
13867
13943
|
if (result.text) {
|
|
13868
|
-
await channel.sendText(chatId, result.text, "plain");
|
|
13944
|
+
await channel.sendText(chatId, result.text, { parseMode: "plain" });
|
|
13869
13945
|
}
|
|
13870
13946
|
} catch (err) {
|
|
13871
|
-
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, "plain");
|
|
13947
|
+
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
13872
13948
|
}
|
|
13873
13949
|
break;
|
|
13874
13950
|
}
|
|
@@ -13877,7 +13953,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13877
13953
|
await channel.sendText(
|
|
13878
13954
|
chatId,
|
|
13879
13955
|
"Usage: /schedule <description>\nExample: /schedule every day at 9am summarize AI news\n\nThe wizard will guide you through all configuration options.",
|
|
13880
|
-
"plain"
|
|
13956
|
+
{ parseMode: "plain" }
|
|
13881
13957
|
);
|
|
13882
13958
|
return;
|
|
13883
13959
|
}
|
|
@@ -13898,7 +13974,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13898
13974
|
await channel.sendText(
|
|
13899
13975
|
chatId,
|
|
13900
13976
|
success2 ? `Job #${id} cancelled.` : `Job #${id} not found.`,
|
|
13901
|
-
"plain"
|
|
13977
|
+
{ parseMode: "plain" }
|
|
13902
13978
|
);
|
|
13903
13979
|
break;
|
|
13904
13980
|
}
|
|
@@ -13912,7 +13988,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13912
13988
|
await channel.sendText(
|
|
13913
13989
|
chatId,
|
|
13914
13990
|
paused ? `Job #${pauseId} paused. Use /resume ${pauseId} to re-enable.` : `Job #${pauseId} not found.`,
|
|
13915
|
-
"plain"
|
|
13991
|
+
{ parseMode: "plain" }
|
|
13916
13992
|
);
|
|
13917
13993
|
break;
|
|
13918
13994
|
}
|
|
@@ -13926,7 +14002,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13926
14002
|
await channel.sendText(
|
|
13927
14003
|
chatId,
|
|
13928
14004
|
resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`,
|
|
13929
|
-
"plain"
|
|
14005
|
+
{ parseMode: "plain" }
|
|
13930
14006
|
);
|
|
13931
14007
|
break;
|
|
13932
14008
|
}
|
|
@@ -13936,9 +14012,9 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13936
14012
|
return;
|
|
13937
14013
|
}
|
|
13938
14014
|
const runJobId = parseInt(commandArgs, 10);
|
|
13939
|
-
await channel.sendText(chatId, `Triggering job #${runJobId}...`, "plain");
|
|
14015
|
+
await channel.sendText(chatId, `Triggering job #${runJobId}...`, { parseMode: "plain" });
|
|
13940
14016
|
const result = await triggerJob(runJobId);
|
|
13941
|
-
await channel.sendText(chatId, result, "plain");
|
|
14017
|
+
await channel.sendText(chatId, result, { parseMode: "plain" });
|
|
13942
14018
|
break;
|
|
13943
14019
|
}
|
|
13944
14020
|
case "runs": {
|
|
@@ -13948,7 +14024,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13948
14024
|
} else {
|
|
13949
14025
|
const runs = getJobRuns(void 0, 10);
|
|
13950
14026
|
if (runs.length === 0) {
|
|
13951
|
-
await channel.sendText(chatId, "No run history yet.", "plain");
|
|
14027
|
+
await channel.sendText(chatId, "No run history yet.", { parseMode: "plain" });
|
|
13952
14028
|
return;
|
|
13953
14029
|
}
|
|
13954
14030
|
const lines = runs.map((r) => {
|
|
@@ -13959,13 +14035,13 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13959
14035
|
Tokens: ${r.usageInput}in / ${r.usageOutput}out` : "";
|
|
13960
14036
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${duration}${error3}${usage2}`;
|
|
13961
14037
|
});
|
|
13962
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
14038
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
13963
14039
|
}
|
|
13964
14040
|
break;
|
|
13965
14041
|
}
|
|
13966
14042
|
case "editjob": {
|
|
13967
14043
|
if (!commandArgs) {
|
|
13968
|
-
await channel.sendText(chatId, "Usage: /editjob <job-id>", "plain");
|
|
14044
|
+
await channel.sendText(chatId, "Usage: /editjob <job-id>", { parseMode: "plain" });
|
|
13969
14045
|
return;
|
|
13970
14046
|
}
|
|
13971
14047
|
const editId = parseInt(commandArgs, 10);
|
|
@@ -13974,7 +14050,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13974
14050
|
}
|
|
13975
14051
|
case "health": {
|
|
13976
14052
|
const report = getHealthReport();
|
|
13977
|
-
await channel.sendText(chatId, formatHealthReport(report), "plain");
|
|
14053
|
+
await channel.sendText(chatId, formatHealthReport(report), { parseMode: "plain" });
|
|
13978
14054
|
if (typeof channel.sendKeyboard === "function") {
|
|
13979
14055
|
await channel.sendKeyboard(chatId, "", [
|
|
13980
14056
|
[
|
|
@@ -13990,7 +14066,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13990
14066
|
if (query) {
|
|
13991
14067
|
const results = searchMessageLog(chatId, query, 20);
|
|
13992
14068
|
if (results.length === 0) {
|
|
13993
|
-
await channel.sendText(chatId, `No matching history found. Try /memories ${query} for older sessions.`, "plain");
|
|
14069
|
+
await channel.sendText(chatId, `No matching history found. Try /memories ${query} for older sessions.`, { parseMode: "plain" });
|
|
13994
14070
|
break;
|
|
13995
14071
|
}
|
|
13996
14072
|
const lines = [`\u{1F4CB} History: "${query}"`, "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"];
|
|
@@ -14001,14 +14077,14 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14001
14077
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${roleLabel}: ${preview}`);
|
|
14002
14078
|
}
|
|
14003
14079
|
lines.push("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
14004
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
14080
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14005
14081
|
} else {
|
|
14006
14082
|
if (typeof channel.sendKeyboard === "function") {
|
|
14007
14083
|
await sendHistoryView(chatId, channel, {});
|
|
14008
14084
|
} else {
|
|
14009
14085
|
const rows = getRecentMessageLog(chatId, 20).reverse();
|
|
14010
14086
|
if (rows.length === 0) {
|
|
14011
|
-
await channel.sendText(chatId, "No conversation history found.", "plain");
|
|
14087
|
+
await channel.sendText(chatId, "No conversation history found.", { parseMode: "plain" });
|
|
14012
14088
|
break;
|
|
14013
14089
|
}
|
|
14014
14090
|
const lines = ["\u{1F4CB} Recent conversation (last 10 exchanges):", "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"];
|
|
@@ -14019,7 +14095,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14019
14095
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${roleLabel}: ${preview}`);
|
|
14020
14096
|
}
|
|
14021
14097
|
lines.push("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
14022
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
14098
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14023
14099
|
}
|
|
14024
14100
|
}
|
|
14025
14101
|
break;
|
|
@@ -14027,7 +14103,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14027
14103
|
case "skills": {
|
|
14028
14104
|
const skills2 = await discoverAllSkills();
|
|
14029
14105
|
if (skills2.length === 0) {
|
|
14030
|
-
await channel.sendText(chatId, "No skills found. Install skills with /skill-install <github-url> or place them in ~/.cc-claw/workspace/skills/", "plain");
|
|
14106
|
+
await channel.sendText(chatId, "No skills found. Install skills with /skill-install <github-url> or place them in ~/.cc-claw/workspace/skills/", { parseMode: "plain" });
|
|
14031
14107
|
return;
|
|
14032
14108
|
}
|
|
14033
14109
|
const page = commandArgs ? parseInt(commandArgs, 10) || 1 : 1;
|
|
@@ -14036,16 +14112,16 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14036
14112
|
}
|
|
14037
14113
|
case "skill-install": {
|
|
14038
14114
|
if (!commandArgs) {
|
|
14039
|
-
await channel.sendText(chatId, "Usage: /skill-install <github-url>\nExample: /skill-install jacob-bd/universal-skills-manager", "plain");
|
|
14115
|
+
await channel.sendText(chatId, "Usage: /skill-install <github-url>\nExample: /skill-install jacob-bd/universal-skills-manager", { parseMode: "plain" });
|
|
14040
14116
|
return;
|
|
14041
14117
|
}
|
|
14042
|
-
await channel.sendText(chatId, `Installing skill from ${commandArgs}...`, "plain");
|
|
14118
|
+
await channel.sendText(chatId, `Installing skill from ${commandArgs}...`, { parseMode: "plain" });
|
|
14043
14119
|
const result = await installSkillFromGitHub(commandArgs);
|
|
14044
14120
|
if (result.success) {
|
|
14045
14121
|
await channel.sendText(chatId, `Skill "${result.skillName}" installed to ~/.cc-claw/workspace/skills/
|
|
14046
|
-
Use /skills to see it.`, "plain");
|
|
14122
|
+
Use /skills to see it.`, { parseMode: "plain" });
|
|
14047
14123
|
} else {
|
|
14048
|
-
await channel.sendText(chatId, `Installation failed: ${result.error}`, "plain");
|
|
14124
|
+
await channel.sendText(chatId, `Installation failed: ${result.error}`, { parseMode: "plain" });
|
|
14049
14125
|
}
|
|
14050
14126
|
break;
|
|
14051
14127
|
}
|
|
@@ -14079,10 +14155,10 @@ Use /skills to see it.`, "plain");
|
|
|
14079
14155
|
}
|
|
14080
14156
|
} else {
|
|
14081
14157
|
if (aliases.length === 0) {
|
|
14082
|
-
await channel.sendText(chatId, "No chat aliases configured yet.\nUsage: /chats name <chat_id> <alias>\n\nGroup chats are auto-discovered when the bot receives a message from them.", "plain");
|
|
14158
|
+
await channel.sendText(chatId, "No chat aliases configured yet.\nUsage: /chats name <chat_id> <alias>\n\nGroup chats are auto-discovered when the bot receives a message from them.", { parseMode: "plain" });
|
|
14083
14159
|
} else {
|
|
14084
14160
|
const lines = ["Authorized chats:", "", ...aliases.map((a) => ` ${a.alias} -> ${a.chatId}`)];
|
|
14085
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
14161
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14086
14162
|
}
|
|
14087
14163
|
}
|
|
14088
14164
|
break;
|
|
@@ -14092,12 +14168,12 @@ Use /skills to see it.`, "plain");
|
|
|
14092
14168
|
const targetChatId = parts[1];
|
|
14093
14169
|
const alias = parts.slice(2).join("-").toLowerCase();
|
|
14094
14170
|
setChatAlias(alias, targetChatId);
|
|
14095
|
-
await channel.sendText(chatId, `Alias set: ${alias} -> ${targetChatId}`, "plain");
|
|
14171
|
+
await channel.sendText(chatId, `Alias set: ${alias} -> ${targetChatId}`, { parseMode: "plain" });
|
|
14096
14172
|
} else if (parts[0] === "remove" && parts[1]) {
|
|
14097
14173
|
const removed = removeChatAlias(parts[1]);
|
|
14098
|
-
await channel.sendText(chatId, removed ? `Alias "${parts[1]}" removed.` : `Alias "${parts[1]}" not found.`, "plain");
|
|
14174
|
+
await channel.sendText(chatId, removed ? `Alias "${parts[1]}" removed.` : `Alias "${parts[1]}" not found.`, { parseMode: "plain" });
|
|
14099
14175
|
} else {
|
|
14100
|
-
await channel.sendText(chatId, "Usage:\n /chats \u2014 list all aliases\n /chats name <chat_id> <alias> \u2014 assign alias\n /chats remove <alias> \u2014 remove alias", "plain");
|
|
14176
|
+
await channel.sendText(chatId, "Usage:\n /chats \u2014 list all aliases\n /chats name <chat_id> <alias> \u2014 assign alias\n /chats remove <alias> \u2014 remove alias", { parseMode: "plain" });
|
|
14101
14177
|
}
|
|
14102
14178
|
break;
|
|
14103
14179
|
}
|
|
@@ -14111,7 +14187,7 @@ Use /skills to see it.`, "plain");
|
|
|
14111
14187
|
if (typeof channel.sendKeyboard === "function") {
|
|
14112
14188
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14113
14189
|
} else {
|
|
14114
|
-
await channel.sendText(chatId, "Heartbeat enabled. I'll check in periodically.", "plain");
|
|
14190
|
+
await channel.sendText(chatId, "Heartbeat enabled. I'll check in periodically.", { parseMode: "plain" });
|
|
14115
14191
|
}
|
|
14116
14192
|
break;
|
|
14117
14193
|
}
|
|
@@ -14121,14 +14197,14 @@ Use /skills to see it.`, "plain");
|
|
|
14121
14197
|
if (typeof channel.sendKeyboard === "function") {
|
|
14122
14198
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14123
14199
|
} else {
|
|
14124
|
-
await channel.sendText(chatId, "Heartbeat disabled.", "plain");
|
|
14200
|
+
await channel.sendText(chatId, "Heartbeat disabled.", { parseMode: "plain" });
|
|
14125
14201
|
}
|
|
14126
14202
|
break;
|
|
14127
14203
|
}
|
|
14128
14204
|
case "interval": {
|
|
14129
14205
|
const ms = parseIntervalToMs(value ?? "30m");
|
|
14130
14206
|
if (!ms || ms < 6e4) {
|
|
14131
|
-
await channel.sendText(chatId, "Invalid interval. Use e.g. 15m, 30m, 1h, 2h", "plain");
|
|
14207
|
+
await channel.sendText(chatId, "Invalid interval. Use e.g. 15m, 30m, 1h, 2h", { parseMode: "plain" });
|
|
14132
14208
|
break;
|
|
14133
14209
|
}
|
|
14134
14210
|
setHeartbeatConfig(chatId, { intervalMs: ms });
|
|
@@ -14138,14 +14214,14 @@ Use /skills to see it.`, "plain");
|
|
|
14138
14214
|
if (typeof channel.sendKeyboard === "function") {
|
|
14139
14215
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14140
14216
|
} else {
|
|
14141
|
-
await channel.sendText(chatId, `Heartbeat interval set to ${ms / 6e4} minutes.`, "plain");
|
|
14217
|
+
await channel.sendText(chatId, `Heartbeat interval set to ${ms / 6e4} minutes.`, { parseMode: "plain" });
|
|
14142
14218
|
}
|
|
14143
14219
|
break;
|
|
14144
14220
|
}
|
|
14145
14221
|
case "hours": {
|
|
14146
14222
|
const hourMatch = (value ?? "").match(/^(\d{1,2})-(\d{1,2})$/);
|
|
14147
14223
|
if (!hourMatch) {
|
|
14148
|
-
await channel.sendText(chatId, "Usage: /heartbeat hours 8-22", "plain");
|
|
14224
|
+
await channel.sendText(chatId, "Usage: /heartbeat hours 8-22", { parseMode: "plain" });
|
|
14149
14225
|
break;
|
|
14150
14226
|
}
|
|
14151
14227
|
const hbStart = `${hourMatch[1].padStart(2, "0")}:00`;
|
|
@@ -14154,7 +14230,7 @@ Use /skills to see it.`, "plain");
|
|
|
14154
14230
|
if (typeof channel.sendKeyboard === "function") {
|
|
14155
14231
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14156
14232
|
} else {
|
|
14157
|
-
await channel.sendText(chatId, `Active hours: ${hbStart} - ${hbEnd}`, "plain");
|
|
14233
|
+
await channel.sendText(chatId, `Active hours: ${hbStart} - ${hbEnd}`, { parseMode: "plain" });
|
|
14158
14234
|
}
|
|
14159
14235
|
break;
|
|
14160
14236
|
}
|
|
@@ -14162,7 +14238,7 @@ Use /skills to see it.`, "plain");
|
|
|
14162
14238
|
if (typeof channel.sendKeyboard === "function") {
|
|
14163
14239
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14164
14240
|
} else {
|
|
14165
|
-
await channel.sendText(chatId, formatHeartbeatStatus(chatId), "plain");
|
|
14241
|
+
await channel.sendText(chatId, formatHeartbeatStatus(chatId), { parseMode: "plain" });
|
|
14166
14242
|
}
|
|
14167
14243
|
}
|
|
14168
14244
|
break;
|
|
@@ -14170,7 +14246,7 @@ Use /skills to see it.`, "plain");
|
|
|
14170
14246
|
if (typeof channel.sendKeyboard === "function") {
|
|
14171
14247
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14172
14248
|
} else {
|
|
14173
|
-
await channel.sendText(chatId, formatHeartbeatStatus(chatId), "plain");
|
|
14249
|
+
await channel.sendText(chatId, formatHeartbeatStatus(chatId), { parseMode: "plain" });
|
|
14174
14250
|
}
|
|
14175
14251
|
break;
|
|
14176
14252
|
}
|
|
@@ -14185,7 +14261,7 @@ Use /skills to see it.`, "plain");
|
|
|
14185
14261
|
} catch {
|
|
14186
14262
|
}
|
|
14187
14263
|
clearSession(chatId);
|
|
14188
|
-
await channel.sendText(chatId, `Agent mode set to <b>${modeArg}</b>. Session cleared.`, "html");
|
|
14264
|
+
await channel.sendText(chatId, `Agent mode set to <b>${modeArg}</b>. Session cleared.`, { parseMode: "html" });
|
|
14189
14265
|
} else if (typeof channel.sendKeyboard === "function") {
|
|
14190
14266
|
const current = getAgentMode(chatId);
|
|
14191
14267
|
await channel.sendKeyboard(chatId, `Agent mode: <b>${current}</b>
|
|
@@ -14199,7 +14275,7 @@ Choose a mode:`, [
|
|
|
14199
14275
|
]);
|
|
14200
14276
|
} else {
|
|
14201
14277
|
const current = getAgentMode(chatId);
|
|
14202
|
-
await channel.sendText(chatId, `Agent mode: ${current}. Use /agents mode <auto|native|claw> to change.`, "plain");
|
|
14278
|
+
await channel.sendText(chatId, `Agent mode: ${current}. Use /agents mode <auto|native|claw> to change.`, { parseMode: "plain" });
|
|
14203
14279
|
}
|
|
14204
14280
|
return;
|
|
14205
14281
|
}
|
|
@@ -14212,7 +14288,7 @@ Choose a mode:`, [
|
|
|
14212
14288
|
ORDER BY createdAt DESC LIMIT 20
|
|
14213
14289
|
`).all(chatId);
|
|
14214
14290
|
if (events.length === 0) {
|
|
14215
|
-
await channel.sendText(chatId, "No native sub-agent activity in the last 24h.", "plain");
|
|
14291
|
+
await channel.sendText(chatId, "No native sub-agent activity in the last 24h.", { parseMode: "plain" });
|
|
14216
14292
|
} else {
|
|
14217
14293
|
const lines2 = events.map((e) => {
|
|
14218
14294
|
const d = e.detail ? JSON.parse(e.detail) : {};
|
|
@@ -14220,7 +14296,7 @@ Choose a mode:`, [
|
|
|
14220
14296
|
});
|
|
14221
14297
|
await channel.sendText(chatId, `<b>Native agent history (24h)</b>
|
|
14222
14298
|
|
|
14223
|
-
${lines2.join("\n")}`, "html");
|
|
14299
|
+
${lines2.join("\n")}`, { parseMode: "html" });
|
|
14224
14300
|
}
|
|
14225
14301
|
return;
|
|
14226
14302
|
}
|
|
@@ -14237,7 +14313,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14237
14313
|
const runners2 = getAllRunners();
|
|
14238
14314
|
const runnerMap = new Map(runners2.map((r) => [r.id, r]));
|
|
14239
14315
|
if (agents2.length === 0) {
|
|
14240
|
-
await channel.sendText(chatId, "<b>Active Agents</b>\n\nNo active agents.", "html");
|
|
14316
|
+
await channel.sendText(chatId, "<b>Active Agents</b>\n\nNo active agents.", { parseMode: "html" });
|
|
14241
14317
|
break;
|
|
14242
14318
|
}
|
|
14243
14319
|
const { getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
@@ -14271,7 +14347,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14271
14347
|
lines.push("");
|
|
14272
14348
|
}
|
|
14273
14349
|
lines.push(`Total: ${agents2.length} agent(s) (${runningCount} running, ${queuedCount} queued)`);
|
|
14274
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14350
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14275
14351
|
if (typeof channel.sendKeyboard === "function") {
|
|
14276
14352
|
const agentButtons = [];
|
|
14277
14353
|
for (const a of agents2) {
|
|
@@ -14290,7 +14366,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14290
14366
|
const db3 = getDb();
|
|
14291
14367
|
const orch = getActiveOrchestration(db3, chatId);
|
|
14292
14368
|
if (!orch) {
|
|
14293
|
-
await channel.sendText(chatId, "<b>Task Board</b>\n\nNo active orchestration. Start a task to create one.", "html");
|
|
14369
|
+
await channel.sendText(chatId, "<b>Task Board</b>\n\nNo active orchestration. Start a task to create one.", { parseMode: "html" });
|
|
14294
14370
|
break;
|
|
14295
14371
|
}
|
|
14296
14372
|
const tasks = listTasksByOrchestration(db3, orch.id);
|
|
@@ -14325,7 +14401,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14325
14401
|
if (lines.length === 2) {
|
|
14326
14402
|
lines.push("No tasks yet.");
|
|
14327
14403
|
}
|
|
14328
|
-
await channel.sendText(chatId, lines.join("\n").trimEnd(), "html");
|
|
14404
|
+
await channel.sendText(chatId, lines.join("\n").trimEnd(), { parseMode: "html" });
|
|
14329
14405
|
if (typeof channel.sendKeyboard === "function" && tasks.length > 0) {
|
|
14330
14406
|
const taskButtons = [];
|
|
14331
14407
|
const viewable = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
|
|
@@ -14346,7 +14422,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14346
14422
|
const db4 = getDb();
|
|
14347
14423
|
const agents3 = listActiveAgents(db4);
|
|
14348
14424
|
if (agents3.length === 0) {
|
|
14349
|
-
await channel.sendText(chatId, "No active agents to stop.", "plain");
|
|
14425
|
+
await channel.sendText(chatId, "No active agents to stop.", { parseMode: "plain" });
|
|
14350
14426
|
break;
|
|
14351
14427
|
}
|
|
14352
14428
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -14374,7 +14450,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14374
14450
|
|
|
14375
14451
|
${agentLines.join("\n")}`, buttons);
|
|
14376
14452
|
} else {
|
|
14377
|
-
await channel.sendText(chatId, "Usage: /stopagent <id>\nUse first 8 chars of agent ID or full ID.", "plain");
|
|
14453
|
+
await channel.sendText(chatId, "Usage: /stopagent <id>\nUse first 8 chars of agent ID or full ID.", { parseMode: "plain" });
|
|
14378
14454
|
}
|
|
14379
14455
|
break;
|
|
14380
14456
|
}
|
|
@@ -14383,16 +14459,16 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14383
14459
|
const id = commandArgs.trim();
|
|
14384
14460
|
const match = agents2.find((a) => a.id === id || a.id.startsWith(id));
|
|
14385
14461
|
if (!match) {
|
|
14386
|
-
await channel.sendText(chatId, `No active agent found matching "${id}". Use /agents to list.`, "plain");
|
|
14462
|
+
await channel.sendText(chatId, `No active agent found matching "${id}". Use /agents to list.`, { parseMode: "plain" });
|
|
14387
14463
|
break;
|
|
14388
14464
|
}
|
|
14389
14465
|
const ok = cancelAgent(match.id);
|
|
14390
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
14466
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
14391
14467
|
break;
|
|
14392
14468
|
}
|
|
14393
14469
|
case "stopall": {
|
|
14394
14470
|
const count = cancelAllAgents(chatId);
|
|
14395
|
-
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", "plain");
|
|
14471
|
+
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", { parseMode: "plain" });
|
|
14396
14472
|
if (count > 0 && typeof channel.sendKeyboard === "function") {
|
|
14397
14473
|
await channel.sendKeyboard(chatId, "", [
|
|
14398
14474
|
[
|
|
@@ -14406,7 +14482,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14406
14482
|
case "runners": {
|
|
14407
14483
|
const runners2 = getAllRunners();
|
|
14408
14484
|
if (runners2.length === 0) {
|
|
14409
|
-
await channel.sendText(chatId, "<b>Registered Runners</b>\n\nNo runners registered.", "html");
|
|
14485
|
+
await channel.sendText(chatId, "<b>Registered Runners</b>\n\nNo runners registered.", { parseMode: "html" });
|
|
14410
14486
|
break;
|
|
14411
14487
|
}
|
|
14412
14488
|
const lines = ["<b>Registered Runners</b>", ""];
|
|
@@ -14414,7 +14490,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14414
14490
|
const specialties = r.capabilities.specialties?.join(", ") ?? "";
|
|
14415
14491
|
lines.push(`\u2022 <b>${r.id}</b> (${r.displayName}) \u2014 ${specialties}`);
|
|
14416
14492
|
}
|
|
14417
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14493
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14418
14494
|
break;
|
|
14419
14495
|
}
|
|
14420
14496
|
case "mcp":
|
|
@@ -14483,7 +14559,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14483
14559
|
} else {
|
|
14484
14560
|
lines.splice(1, 0, `<i>${connectedCount}/${totalCount} connected</i>`);
|
|
14485
14561
|
}
|
|
14486
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14562
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14487
14563
|
break;
|
|
14488
14564
|
}
|
|
14489
14565
|
case "cron": {
|
|
@@ -14502,7 +14578,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14502
14578
|
}
|
|
14503
14579
|
const id = parseInt(cronSubArgs, 10);
|
|
14504
14580
|
const ok = cancelJob(id);
|
|
14505
|
-
await channel.sendText(chatId, ok ? `Job #${id} cancelled.` : `Job #${id} not found.`, "plain");
|
|
14581
|
+
await channel.sendText(chatId, ok ? `Job #${id} cancelled.` : `Job #${id} not found.`, { parseMode: "plain" });
|
|
14506
14582
|
break;
|
|
14507
14583
|
}
|
|
14508
14584
|
case "pause": {
|
|
@@ -14512,7 +14588,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14512
14588
|
}
|
|
14513
14589
|
const pauseId = parseInt(cronSubArgs, 10);
|
|
14514
14590
|
const paused = pauseJob(pauseId);
|
|
14515
|
-
await channel.sendText(chatId, paused ? `Job #${pauseId} paused.` : `Job #${pauseId} not found.`, "plain");
|
|
14591
|
+
await channel.sendText(chatId, paused ? `Job #${pauseId} paused.` : `Job #${pauseId} not found.`, { parseMode: "plain" });
|
|
14516
14592
|
break;
|
|
14517
14593
|
}
|
|
14518
14594
|
case "resume": {
|
|
@@ -14522,7 +14598,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14522
14598
|
}
|
|
14523
14599
|
const resumeId = parseInt(cronSubArgs, 10);
|
|
14524
14600
|
const resumed = resumeJob(resumeId);
|
|
14525
|
-
await channel.sendText(chatId, resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`, "plain");
|
|
14601
|
+
await channel.sendText(chatId, resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`, { parseMode: "plain" });
|
|
14526
14602
|
break;
|
|
14527
14603
|
}
|
|
14528
14604
|
case "run": {
|
|
@@ -14531,9 +14607,9 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14531
14607
|
return;
|
|
14532
14608
|
}
|
|
14533
14609
|
const runId = parseInt(cronSubArgs, 10);
|
|
14534
|
-
await channel.sendText(chatId, `Triggering job #${runId}...`, "plain");
|
|
14610
|
+
await channel.sendText(chatId, `Triggering job #${runId}...`, { parseMode: "plain" });
|
|
14535
14611
|
const runResult = await triggerJob(runId);
|
|
14536
|
-
await channel.sendText(chatId, runResult, "plain");
|
|
14612
|
+
await channel.sendText(chatId, runResult, { parseMode: "plain" });
|
|
14537
14613
|
break;
|
|
14538
14614
|
}
|
|
14539
14615
|
case "runs": {
|
|
@@ -14543,20 +14619,20 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14543
14619
|
} else {
|
|
14544
14620
|
const cronRuns2 = getJobRuns(void 0, 10);
|
|
14545
14621
|
if (cronRuns2.length === 0) {
|
|
14546
|
-
await channel.sendText(chatId, "No run history.", "plain");
|
|
14622
|
+
await channel.sendText(chatId, "No run history.", { parseMode: "plain" });
|
|
14547
14623
|
return;
|
|
14548
14624
|
}
|
|
14549
14625
|
const runLines = cronRuns2.map((r) => {
|
|
14550
14626
|
const dur = r.durationMs ? ` (${(r.durationMs / 1e3).toFixed(1)}s)` : "";
|
|
14551
14627
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${dur}`;
|
|
14552
14628
|
});
|
|
14553
|
-
await channel.sendText(chatId, runLines.join("\n\n"), "plain");
|
|
14629
|
+
await channel.sendText(chatId, runLines.join("\n\n"), { parseMode: "plain" });
|
|
14554
14630
|
}
|
|
14555
14631
|
break;
|
|
14556
14632
|
}
|
|
14557
14633
|
case "edit": {
|
|
14558
14634
|
if (!cronSubArgs) {
|
|
14559
|
-
await channel.sendText(chatId, "Usage: /cron edit <id>", "plain");
|
|
14635
|
+
await channel.sendText(chatId, "Usage: /cron edit <id>", { parseMode: "plain" });
|
|
14560
14636
|
return;
|
|
14561
14637
|
}
|
|
14562
14638
|
const editId = parseInt(cronSubArgs, 10);
|
|
@@ -14565,7 +14641,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14565
14641
|
}
|
|
14566
14642
|
case "health": {
|
|
14567
14643
|
const report = getHealthReport();
|
|
14568
|
-
await channel.sendText(chatId, formatHealthReport(report), "plain");
|
|
14644
|
+
await channel.sendText(chatId, formatHealthReport(report), { parseMode: "plain" });
|
|
14569
14645
|
break;
|
|
14570
14646
|
}
|
|
14571
14647
|
default:
|
|
@@ -14577,84 +14653,112 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14577
14653
|
const testMsg = commandArgs?.trim() || "hey";
|
|
14578
14654
|
const result = classifyIntent(testMsg, chatId);
|
|
14579
14655
|
await channel.sendText(chatId, `Intent: ${result}
|
|
14580
|
-
Message: "${testMsg}"`, "plain");
|
|
14656
|
+
Message: "${testMsg}"`, { parseMode: "plain" });
|
|
14581
14657
|
break;
|
|
14582
14658
|
}
|
|
14583
14659
|
case "evolve": {
|
|
14584
|
-
const {
|
|
14585
|
-
const
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
|
|
14660
|
+
const { getReflectionStatus: getRefStatus, getUnprocessedSignalCount: getUnprocessedSignalCount2, getPendingInsightCount: getPendingInsightCount2, getLastAnalysisTime: getLastAnalysisTime2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14661
|
+
const isActive = getRefStatus(getDb(), chatId) === "active";
|
|
14662
|
+
if (!isActive) {
|
|
14663
|
+
const text = [
|
|
14664
|
+
"Self-Learning & Evolution",
|
|
14665
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
14666
|
+
"",
|
|
14667
|
+
"Teach your assistant to improve over time.",
|
|
14668
|
+
"",
|
|
14669
|
+
"When enabled, CC-Claw watches for corrections,",
|
|
14670
|
+
"preferences, and frustration in your messages,",
|
|
14671
|
+
"then proposes changes to its personality and",
|
|
14672
|
+
"behavior files (SOUL.md, USER.md).",
|
|
14673
|
+
"",
|
|
14674
|
+
"You review and approve every change."
|
|
14675
|
+
].join("\n");
|
|
14676
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14677
|
+
const { buildEvolveOnboardingKeyboard: buildEvolveOnboardingKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14678
|
+
await channel.sendKeyboard(chatId, text, buildEvolveOnboardingKeyboard2());
|
|
14679
|
+
} else {
|
|
14680
|
+
await channel.sendText(chatId, text + "\n\nUse /evolve enable to activate.", { parseMode: "plain" });
|
|
14681
|
+
}
|
|
14682
|
+
} else {
|
|
14683
|
+
const signals = getUnprocessedSignalCount2(getDb(), chatId);
|
|
14684
|
+
const pending = getPendingInsightCount2(getDb(), chatId);
|
|
14593
14685
|
const lastTime = getLastAnalysisTime2(getDb(), chatId);
|
|
14594
|
-
let
|
|
14686
|
+
let lastText = "never";
|
|
14595
14687
|
if (lastTime) {
|
|
14596
14688
|
const diffMs = Date.now() - (/* @__PURE__ */ new Date(lastTime + "Z")).getTime();
|
|
14597
14689
|
const diffHours = Math.floor(diffMs / 36e5);
|
|
14598
|
-
if (diffHours < 1)
|
|
14599
|
-
else if (diffHours < 24)
|
|
14600
|
-
else {
|
|
14601
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
14602
|
-
lastAnalysisText = `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
14603
|
-
}
|
|
14690
|
+
if (diffHours < 1) lastText = "< 1 hour ago";
|
|
14691
|
+
else if (diffHours < 24) lastText = `${diffHours}h ago`;
|
|
14692
|
+
else lastText = `${Math.floor(diffHours / 24)}d ago`;
|
|
14604
14693
|
}
|
|
14605
|
-
const
|
|
14606
|
-
"
|
|
14694
|
+
const dashText = [
|
|
14695
|
+
"Self-Learning & Evolution",
|
|
14607
14696
|
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
14608
14697
|
"",
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14612
|
-
`Unprocessed signals: ${signalCount}`,
|
|
14613
|
-
`Last analysis: ${lastAnalysisText}`
|
|
14698
|
+
`\u2705 Active`,
|
|
14699
|
+
`Signals: ${signals} pending \xB7 Proposals: ${pending}`,
|
|
14700
|
+
`Last analysis: ${lastText}`
|
|
14614
14701
|
].join("\n");
|
|
14615
|
-
|
|
14616
|
-
{
|
|
14617
|
-
{
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14702
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14703
|
+
const { buildEvolveMenuKeyboard: buildEvolveMenuKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14704
|
+
await channel.sendKeyboard(chatId, dashText, buildEvolveMenuKeyboard2({ pendingProposals: pending, unprocessedSignals: signals }));
|
|
14705
|
+
} else {
|
|
14706
|
+
await channel.sendText(chatId, dashText, { parseMode: "plain" });
|
|
14707
|
+
}
|
|
14708
|
+
}
|
|
14709
|
+
break;
|
|
14710
|
+
}
|
|
14711
|
+
case "reflect": {
|
|
14712
|
+
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
14713
|
+
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14714
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
14715
|
+
try {
|
|
14716
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
14717
|
+
if (insights.length === 0) {
|
|
14718
|
+
const { getReflectionStatus: getRefStatus } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14719
|
+
const isFrozen = getRefStatus(getDb(), chatId) === "frozen";
|
|
14720
|
+
if (isFrozen) {
|
|
14721
|
+
const msg2 = "No insights found. Self-learning is disabled \u2014\nenable it with /evolve so feedback signals are\ncaptured automatically between analyses.";
|
|
14722
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14723
|
+
await channel.sendKeyboard(chatId, msg2, [[
|
|
14724
|
+
{ label: "Open /evolve", data: "evolve:menu", style: "primary" }
|
|
14725
|
+
]]);
|
|
14726
|
+
} else {
|
|
14727
|
+
await channel.sendText(chatId, msg2, { parseMode: "plain" });
|
|
14728
|
+
}
|
|
14627
14729
|
} else {
|
|
14628
|
-
|
|
14629
|
-
await channel.sendText(chatId, formatNightlySummary2(items), "plain");
|
|
14730
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
14630
14731
|
}
|
|
14631
|
-
}
|
|
14632
|
-
|
|
14732
|
+
} else {
|
|
14733
|
+
const items = insights.map((ins, i) => ({ id: i + 1, category: ins.category, insight: ins.insight }));
|
|
14734
|
+
await channel.sendText(chatId, formatNightlySummary2(items) + "\n\nUse /evolve to review and apply proposals.", { parseMode: "plain" });
|
|
14633
14735
|
}
|
|
14736
|
+
} catch (e) {
|
|
14737
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
14634
14738
|
}
|
|
14635
14739
|
break;
|
|
14636
14740
|
}
|
|
14637
14741
|
default:
|
|
14638
|
-
await channel.sendText(chatId, `Unknown command: /${command}. Type /help for available commands.`, "plain");
|
|
14742
|
+
await channel.sendText(chatId, `Unknown command: /${command}. Type /help for available commands.`, { parseMode: "plain" });
|
|
14639
14743
|
}
|
|
14640
14744
|
}
|
|
14641
14745
|
async function handleVoice(msg, channel) {
|
|
14642
14746
|
const { chatId, fileName } = msg;
|
|
14643
|
-
await channel.sendText(chatId, "Transcribing voice message...", "plain");
|
|
14747
|
+
await channel.sendText(chatId, "Transcribing voice message...", { parseMode: "plain" });
|
|
14644
14748
|
try {
|
|
14645
14749
|
const audioBuffer = await channel.downloadFile(fileName);
|
|
14646
14750
|
const transcript = await transcribeAudio(audioBuffer);
|
|
14647
14751
|
if (!transcript) {
|
|
14648
|
-
await channel.sendText(chatId, "Couldn't transcribe the voice message.", "plain");
|
|
14752
|
+
await channel.sendText(chatId, "Couldn't transcribe the voice message.", { parseMode: "plain" });
|
|
14649
14753
|
return;
|
|
14650
14754
|
}
|
|
14651
14755
|
const vBackendId = getBackend(chatId) ?? "claude";
|
|
14652
14756
|
const vLimitMsg = checkBackendLimits(vBackendId);
|
|
14653
14757
|
if (vLimitMsg) {
|
|
14654
|
-
await channel.sendText(chatId, vLimitMsg, "plain");
|
|
14758
|
+
await channel.sendText(chatId, vLimitMsg, { parseMode: "plain" });
|
|
14655
14759
|
return;
|
|
14656
14760
|
}
|
|
14657
|
-
await channel.sendText(chatId, "Thinking...", "plain");
|
|
14761
|
+
await channel.sendText(chatId, "Thinking...", { parseMode: "plain" });
|
|
14658
14762
|
const mode = getMode(chatId);
|
|
14659
14763
|
const vModel = resolveModel(chatId);
|
|
14660
14764
|
const vVerbose = getVerboseLevel(chatId);
|
|
@@ -14666,7 +14770,7 @@ async function handleVoice(msg, channel) {
|
|
|
14666
14770
|
await sendResponse(chatId, channel, voiceResponse, msg.messageId);
|
|
14667
14771
|
} catch (err) {
|
|
14668
14772
|
error("[router] Voice error:", err);
|
|
14669
|
-
await channel.sendText(chatId, `Voice processing error: ${errorMessage(err)}`, "plain");
|
|
14773
|
+
await channel.sendText(chatId, `Voice processing error: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
14670
14774
|
}
|
|
14671
14775
|
}
|
|
14672
14776
|
async function handleMedia(msg, channel) {
|
|
@@ -14674,15 +14778,15 @@ async function handleMedia(msg, channel) {
|
|
|
14674
14778
|
const mBackendId = getBackend(chatId) ?? "claude";
|
|
14675
14779
|
const mLimitMsg = checkBackendLimits(mBackendId);
|
|
14676
14780
|
if (mLimitMsg) {
|
|
14677
|
-
await channel.sendText(chatId, mLimitMsg, "plain");
|
|
14781
|
+
await channel.sendText(chatId, mLimitMsg, { parseMode: "plain" });
|
|
14678
14782
|
return;
|
|
14679
14783
|
}
|
|
14680
|
-
await channel.sendText(chatId, "Processing your file...", "plain");
|
|
14784
|
+
await channel.sendText(chatId, "Processing your file...", { parseMode: "plain" });
|
|
14681
14785
|
try {
|
|
14682
14786
|
if (msg.type === "video") {
|
|
14683
14787
|
const fileId = msg.metadata?.fileId ?? fileName;
|
|
14684
14788
|
if (!fileId) {
|
|
14685
|
-
await channel.sendText(chatId, "Could not retrieve video file ID.", "plain");
|
|
14789
|
+
await channel.sendText(chatId, "Could not retrieve video file ID.", { parseMode: "plain" });
|
|
14686
14790
|
return;
|
|
14687
14791
|
}
|
|
14688
14792
|
const videoBuffer = await channel.downloadFile(fileId);
|
|
@@ -14774,11 +14878,12 @@ ${content}
|
|
|
14774
14878
|
await sendResponse(chatId, channel, mediaResponse, msg.messageId);
|
|
14775
14879
|
} catch (err) {
|
|
14776
14880
|
error("[router] Media error:", err);
|
|
14777
|
-
await channel.sendText(chatId, `Error processing file: ${errorMessage(err)}`, "plain");
|
|
14881
|
+
await channel.sendText(chatId, `Error processing file: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
14778
14882
|
}
|
|
14779
14883
|
}
|
|
14780
14884
|
async function handleText(msg, channel) {
|
|
14781
|
-
const { chatId
|
|
14885
|
+
const { chatId } = msg;
|
|
14886
|
+
let { text } = msg;
|
|
14782
14887
|
if (hasActiveProfile(chatId)) {
|
|
14783
14888
|
await handleProfileText(chatId, text, channel);
|
|
14784
14889
|
return;
|
|
@@ -14786,7 +14891,7 @@ async function handleText(msg, channel) {
|
|
|
14786
14891
|
if (hasPendingWizard(chatId)) {
|
|
14787
14892
|
if (text.toLowerCase() === "cancel") {
|
|
14788
14893
|
cancelWizard(chatId);
|
|
14789
|
-
await channel.sendText(chatId, "Scheduling cancelled.", "plain");
|
|
14894
|
+
await channel.sendText(chatId, "Scheduling cancelled.", { parseMode: "plain" });
|
|
14790
14895
|
return;
|
|
14791
14896
|
}
|
|
14792
14897
|
if (text.toLowerCase() === "confirm") {
|
|
@@ -14801,14 +14906,14 @@ async function handleText(msg, channel) {
|
|
|
14801
14906
|
const content = rememberMatch[1];
|
|
14802
14907
|
const trigger = content.split(/\s+/).slice(0, 3).join(" ");
|
|
14803
14908
|
saveMemoryWithEmbedding(trigger, content, "semantic");
|
|
14804
|
-
await channel.sendText(chatId, "Got it, I'll remember that.", "plain");
|
|
14909
|
+
await channel.sendText(chatId, "Got it, I'll remember that.", { parseMode: "plain" });
|
|
14805
14910
|
return;
|
|
14806
14911
|
}
|
|
14807
14912
|
const model2 = resolveModel(chatId);
|
|
14808
14913
|
const backendId = getBackend(chatId) ?? "claude";
|
|
14809
14914
|
const limitMsg = checkBackendLimits(backendId);
|
|
14810
14915
|
if (limitMsg) {
|
|
14811
|
-
await channel.sendText(chatId, limitMsg, "plain");
|
|
14916
|
+
await channel.sendText(chatId, limitMsg, { parseMode: "plain" });
|
|
14812
14917
|
return;
|
|
14813
14918
|
}
|
|
14814
14919
|
let intent = classifyIntent(text, chatId);
|
|
@@ -14830,18 +14935,32 @@ async function handleText(msg, channel) {
|
|
|
14830
14935
|
const lastWarn = dashboardClawWarnings.get(chatId) ?? 0;
|
|
14831
14936
|
if (Date.now() - lastWarn > 3e5) {
|
|
14832
14937
|
dashboardClawWarnings.set(chatId, Date.now());
|
|
14833
|
-
await channel.sendText(chatId, "\u26A0\uFE0F CC-Claw orchestration requires DASHBOARD_ENABLED=1. Using native agents.", "plain");
|
|
14938
|
+
await channel.sendText(chatId, "\u26A0\uFE0F CC-Claw orchestration requires DASHBOARD_ENABLED=1. Using native agents.", { parseMode: "plain" });
|
|
14834
14939
|
}
|
|
14835
14940
|
effectiveAgentMode = "native";
|
|
14836
14941
|
}
|
|
14942
|
+
const { isSideQuest: hasSqPrefix, cleanText: sqCleanText } = parseSideQuestPrefix(text);
|
|
14943
|
+
if (hasSqPrefix && isChatBusy(chatId)) {
|
|
14944
|
+
const sqMsg = { ...msg, text: sqCleanText };
|
|
14945
|
+
handleSideQuest(chatId, sqMsg, channel).catch(
|
|
14946
|
+
(err) => error(`[router] Side quest error for ${chatId}:`, err)
|
|
14947
|
+
);
|
|
14948
|
+
return;
|
|
14949
|
+
}
|
|
14950
|
+
if (hasSqPrefix) {
|
|
14951
|
+
text = sqCleanText;
|
|
14952
|
+
}
|
|
14837
14953
|
if (isChatBusy(chatId) && !bypassBusyCheck.delete(chatId)) {
|
|
14838
14954
|
if (typeof channel.sendKeyboard === "function") {
|
|
14839
14955
|
pendingInterrupts.set(chatId, { msg, channel });
|
|
14840
|
-
await channel.sendKeyboard(chatId, "\u23F3 Agent is working on a request
|
|
14956
|
+
await channel.sendKeyboard(chatId, "\u23F3 Agent is working on a request. You can queue, interrupt, or start a parallel task.", [
|
|
14841
14957
|
[
|
|
14842
|
-
{ label: "\u{1F4E5} Queue
|
|
14958
|
+
{ label: "\u{1F4E5} Queue", data: `interrupt:queue:${chatId}` },
|
|
14843
14959
|
{ label: "\u26A1 Send now", data: `interrupt:now:${chatId}` }
|
|
14844
14960
|
],
|
|
14961
|
+
[
|
|
14962
|
+
{ label: "\u{1F5FA} Side quest \u2014 run in parallel", data: `interrupt:sidequest:${chatId}` }
|
|
14963
|
+
],
|
|
14845
14964
|
[
|
|
14846
14965
|
{ label: "\u{1F5D1} Don't send", data: `interrupt:discard:${chatId}` }
|
|
14847
14966
|
]
|
|
@@ -14897,7 +15016,7 @@ async function handleText(msg, channel) {
|
|
|
14897
15016
|
const toSlot = slots.find((s) => (s.label || `slot-${s.id}`) === to);
|
|
14898
15017
|
const fromIcon = fromSlot?.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
14899
15018
|
const toIcon = toSlot?.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
14900
|
-
channel.sendText(cid, `\u26A0\uFE0F Quota reached on ${fromIcon} ${from} \u2014 switched to ${toIcon} ${to}. Context saved.`, "plain").catch(() => {
|
|
15019
|
+
channel.sendText(cid, `\u26A0\uFE0F Quota reached on ${fromIcon} ${from} \u2014 switched to ${toIcon} ${to}. Context saved.`, { parseMode: "plain" }).catch(() => {
|
|
14901
15020
|
});
|
|
14902
15021
|
}
|
|
14903
15022
|
});
|
|
@@ -14933,6 +15052,9 @@ async function handleText(msg, channel) {
|
|
|
14933
15052
|
return;
|
|
14934
15053
|
}
|
|
14935
15054
|
if (await handleResponseExhaustion(responseText, chatId, msg, channel)) return;
|
|
15055
|
+
if (activeSideQuests.has(chatId) && responseText && !responseText.startsWith("(No response")) {
|
|
15056
|
+
responseText = "\u{1F4CB} <b>Main task</b>\n\n" + responseText;
|
|
15057
|
+
}
|
|
14936
15058
|
responseText = ensureReaction(responseText, cleanText || text);
|
|
14937
15059
|
await sendResponse(chatId, channel, responseText, msg.messageId);
|
|
14938
15060
|
try {
|
|
@@ -14959,7 +15081,7 @@ async function handleText(msg, channel) {
|
|
|
14959
15081
|
];
|
|
14960
15082
|
await channel.sendKeyboard(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}). Switch backend?`, rows);
|
|
14961
15083
|
} else {
|
|
14962
|
-
await channel.sendText(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}).`, "plain");
|
|
15084
|
+
await channel.sendText(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}).`, { parseMode: "plain" });
|
|
14963
15085
|
}
|
|
14964
15086
|
return;
|
|
14965
15087
|
} else if (errMsg.includes(GEMINI_ALL_SLOTS_COOLDOWN_MSG)) {
|
|
@@ -14971,7 +15093,7 @@ async function handleText(msg, channel) {
|
|
|
14971
15093
|
];
|
|
14972
15094
|
await channel.sendKeyboard(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}. Switch backend?`, rows);
|
|
14973
15095
|
} else {
|
|
14974
|
-
await channel.sendText(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}.`, "plain");
|
|
15096
|
+
await channel.sendText(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}.`, { parseMode: "plain" });
|
|
14975
15097
|
}
|
|
14976
15098
|
return;
|
|
14977
15099
|
}
|
|
@@ -14980,7 +15102,7 @@ async function handleText(msg, channel) {
|
|
|
14980
15102
|
if (await handleResponseExhaustion(errMsg, chatId, msg, channel)) return;
|
|
14981
15103
|
}
|
|
14982
15104
|
const userMsg = diagnoseAgentError(errMsg, chatId);
|
|
14983
|
-
await channel.sendText(chatId, userMsg, "plain");
|
|
15105
|
+
await channel.sendText(chatId, userMsg, { parseMode: "plain" });
|
|
14984
15106
|
} finally {
|
|
14985
15107
|
typingActive = false;
|
|
14986
15108
|
const pending = pendingInterrupts.get(chatId);
|
|
@@ -15006,6 +15128,81 @@ After installing, restart the service: cc-claw service restart`;
|
|
|
15006
15128
|
}
|
|
15007
15129
|
return `Error: ${msg}`;
|
|
15008
15130
|
}
|
|
15131
|
+
async function handleSideQuest(parentChatId, msg, channel) {
|
|
15132
|
+
const sqId = `sq:${parentChatId}:${randomUUID3()}`;
|
|
15133
|
+
const active = activeSideQuests.get(parentChatId) ?? /* @__PURE__ */ new Set();
|
|
15134
|
+
if (active.size >= MAX_SIDE_QUESTS) {
|
|
15135
|
+
await channel.sendText(parentChatId, `Side quest slots full (${active.size} running). Queue this or wait for one to finish.`, { parseMode: "plain" });
|
|
15136
|
+
return;
|
|
15137
|
+
}
|
|
15138
|
+
active.add(sqId);
|
|
15139
|
+
activeSideQuests.set(parentChatId, active);
|
|
15140
|
+
await channel.sendKeyboard?.(parentChatId, "\u{1F5FA} Starting side quest\u2026", [
|
|
15141
|
+
[{ label: "\u274C Cancel", data: `sq:cancel:${sqId}` }]
|
|
15142
|
+
]);
|
|
15143
|
+
const startTime = Date.now();
|
|
15144
|
+
let typingActive = true;
|
|
15145
|
+
const typingLoop = async () => {
|
|
15146
|
+
while (typingActive) {
|
|
15147
|
+
try {
|
|
15148
|
+
await channel.sendTyping?.(parentChatId);
|
|
15149
|
+
} catch {
|
|
15150
|
+
}
|
|
15151
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
15152
|
+
}
|
|
15153
|
+
};
|
|
15154
|
+
typingLoop().catch(() => {
|
|
15155
|
+
});
|
|
15156
|
+
try {
|
|
15157
|
+
const backend2 = getBackend(parentChatId);
|
|
15158
|
+
const model2 = getModel(parentChatId);
|
|
15159
|
+
const permMode = getMode(parentChatId);
|
|
15160
|
+
const response = await askAgent(sqId, msg.text ?? "", {
|
|
15161
|
+
cwd: getCwd(parentChatId) ?? void 0,
|
|
15162
|
+
model: model2 ?? void 0,
|
|
15163
|
+
permMode,
|
|
15164
|
+
backend: backend2 ?? void 0,
|
|
15165
|
+
settingsSourceChatId: parentChatId,
|
|
15166
|
+
agentMode: "native",
|
|
15167
|
+
maxTurns: 10,
|
|
15168
|
+
timeoutMs: 3e5,
|
|
15169
|
+
bootstrapTier: "full"
|
|
15170
|
+
});
|
|
15171
|
+
typingActive = false;
|
|
15172
|
+
const userText = msg.text ?? "";
|
|
15173
|
+
const truncated = userText.length > 60 ? userText.slice(0, 57) + "\u2026" : userText;
|
|
15174
|
+
const header2 = `\u{1F5FA} <b>Side quest: "${truncated}"</b>
|
|
15175
|
+
|
|
15176
|
+
`;
|
|
15177
|
+
const responseText = header2 + (response.text ?? "");
|
|
15178
|
+
await sendResponse(parentChatId, channel, responseText, msg.messageId, typeof msg.messageId === "string" ? parseInt(msg.messageId) : void 0);
|
|
15179
|
+
const adapterForLog = backend2 ? getAdapter(backend2) : getAdapterForChat(parentChatId);
|
|
15180
|
+
appendToLog(parentChatId, `[side quest] ${userText}`, `[side quest] ${response.text ?? ""}`, adapterForLog.id, model2 ?? null, null);
|
|
15181
|
+
if (response.usage) {
|
|
15182
|
+
addUsage(parentChatId, response.usage.input, response.usage.output, response.usage.cacheRead, model2 ?? void 0, backend2 ?? void 0);
|
|
15183
|
+
}
|
|
15184
|
+
try {
|
|
15185
|
+
const { detectAndLogSignals: detectAndLogSignals2 } = await Promise.resolve().then(() => (init_detect(), detect_exports));
|
|
15186
|
+
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(parentChatId);
|
|
15187
|
+
detectAndLogSignals2(parentChatId, userText, response.text ?? "", {
|
|
15188
|
+
backendId: adapter.id,
|
|
15189
|
+
model: model2 ?? adapter.defaultModel
|
|
15190
|
+
});
|
|
15191
|
+
} catch {
|
|
15192
|
+
}
|
|
15193
|
+
} catch (err) {
|
|
15194
|
+
typingActive = false;
|
|
15195
|
+
await channel.sendText(parentChatId, `\u{1F5FA} Side quest failed: ${err.message}`, { parseMode: "plain" });
|
|
15196
|
+
} finally {
|
|
15197
|
+
typingActive = false;
|
|
15198
|
+
const activeSet = activeSideQuests.get(parentChatId);
|
|
15199
|
+
if (activeSet) {
|
|
15200
|
+
activeSet.delete(sqId);
|
|
15201
|
+
if (activeSet.size === 0) activeSideQuests.delete(parentChatId);
|
|
15202
|
+
}
|
|
15203
|
+
clearSession(sqId);
|
|
15204
|
+
}
|
|
15205
|
+
}
|
|
15009
15206
|
function formatToolStart(toolName, input, level) {
|
|
15010
15207
|
if (level === "normal") {
|
|
15011
15208
|
const path = input.file_path ?? input.path ?? input.file ?? "";
|
|
@@ -15078,11 +15275,11 @@ function makeToolActionCallback(chatId, channel, level) {
|
|
|
15078
15275
|
return async (toolName, input, result) => {
|
|
15079
15276
|
if (result === void 0) {
|
|
15080
15277
|
const msg = formatToolStart(toolName, input, level);
|
|
15081
|
-
await channel.sendText(chatId, msg, "plain").catch(() => {
|
|
15278
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" }).catch(() => {
|
|
15082
15279
|
});
|
|
15083
15280
|
} else if (level === "verbose") {
|
|
15084
15281
|
const msg = formatToolResult(toolName, result);
|
|
15085
|
-
if (msg) await channel.sendText(chatId, msg, "plain").catch(() => {
|
|
15282
|
+
if (msg) await channel.sendText(chatId, msg, { parseMode: "plain" }).catch(() => {
|
|
15086
15283
|
});
|
|
15087
15284
|
}
|
|
15088
15285
|
};
|
|
@@ -15133,11 +15330,11 @@ async function processImageGenerations(chatId, channel, text) {
|
|
|
15133
15330
|
const name = result.filePath.split("/").pop() ?? "image.png";
|
|
15134
15331
|
await channel.sendFile(chatId, file, name);
|
|
15135
15332
|
if (result.text) {
|
|
15136
|
-
await channel.sendText(chatId, result.text, "plain");
|
|
15333
|
+
await channel.sendText(chatId, result.text, { parseMode: "plain" });
|
|
15137
15334
|
}
|
|
15138
15335
|
} catch (err) {
|
|
15139
15336
|
error(`[router] Image generation failed for "${prompt.slice(0, 50)}":`, err);
|
|
15140
|
-
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, "plain");
|
|
15337
|
+
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
15141
15338
|
}
|
|
15142
15339
|
}
|
|
15143
15340
|
return text.replace(pattern, "").trim();
|
|
@@ -15164,7 +15361,7 @@ async function processReaction(chatId, channel, text, messageId) {
|
|
|
15164
15361
|
}
|
|
15165
15362
|
return text.replace(/\[REACT:(.+?)\]/g, "").trim();
|
|
15166
15363
|
}
|
|
15167
|
-
async function sendResponse(chatId, channel, text, messageId) {
|
|
15364
|
+
async function sendResponse(chatId, channel, text, messageId, replyToMessageId) {
|
|
15168
15365
|
text = await processReaction(chatId, channel, text, messageId);
|
|
15169
15366
|
const { cleanText: afterUpdates, updates } = extractUserUpdates(text);
|
|
15170
15367
|
for (const { key, value } of updates) {
|
|
@@ -15209,14 +15406,14 @@ async function sendResponse(chatId, channel, text, messageId) {
|
|
|
15209
15406
|
error("[router] TTS failed, falling back to text:", err);
|
|
15210
15407
|
}
|
|
15211
15408
|
}
|
|
15212
|
-
await channel.sendText(chatId, cleanText);
|
|
15409
|
+
await channel.sendText(chatId, cleanText, replyToMessageId ? { replyToMessageId } : void 0);
|
|
15213
15410
|
}
|
|
15214
15411
|
function isImageExt(ext) {
|
|
15215
15412
|
return ["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"].includes(ext);
|
|
15216
15413
|
}
|
|
15217
15414
|
async function sendVoiceConfigKeyboard(chatId, channel) {
|
|
15218
15415
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15219
|
-
await channel.sendText(chatId, "Voice configuration requires an interactive channel (Telegram).", "plain");
|
|
15416
|
+
await channel.sendText(chatId, "Voice configuration requires an interactive channel (Telegram).", { parseMode: "plain" });
|
|
15220
15417
|
return;
|
|
15221
15418
|
}
|
|
15222
15419
|
const config2 = getVoiceConfig(chatId);
|
|
@@ -15282,7 +15479,7 @@ async function sendBackendSwitchConfirmation(chatId, target, channel) {
|
|
|
15282
15479
|
const current = getBackend(chatId);
|
|
15283
15480
|
const targetAdapter = getAdapter(target);
|
|
15284
15481
|
if (current === target) {
|
|
15285
|
-
await channel.sendText(chatId, `Already using ${targetAdapter.displayName}.`, "plain");
|
|
15482
|
+
await channel.sendText(chatId, `Already using ${targetAdapter.displayName}.`, { parseMode: "plain" });
|
|
15286
15483
|
return;
|
|
15287
15484
|
}
|
|
15288
15485
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -15306,7 +15503,7 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15306
15503
|
const targetAdapter = getAdapter(backendId);
|
|
15307
15504
|
const pairCount = getMessagePairCount(chatId);
|
|
15308
15505
|
if (pairCount >= 2) {
|
|
15309
|
-
await channel.sendText(chatId, `\u23F3 Saving context...`, "plain");
|
|
15506
|
+
await channel.sendText(chatId, `\u23F3 Saving context...`, { parseMode: "plain" });
|
|
15310
15507
|
}
|
|
15311
15508
|
const summarized = await summarizeWithFallbackChain(chatId, backendId);
|
|
15312
15509
|
const bridge = buildContextBridge(chatId);
|
|
@@ -15314,9 +15511,9 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15314
15511
|
setPendingContextBridge(chatId, bridge);
|
|
15315
15512
|
}
|
|
15316
15513
|
if (summarized) {
|
|
15317
|
-
await channel.sendText(chatId, "\u{1F4BE} Context saved \u2014 session summarized to memory.", "plain");
|
|
15514
|
+
await channel.sendText(chatId, "\u{1F4BE} Context saved \u2014 session summarized to memory.", { parseMode: "plain" });
|
|
15318
15515
|
} else if (bridge) {
|
|
15319
|
-
await channel.sendText(chatId, "\u{1F4AC} Context preserved.", "plain");
|
|
15516
|
+
await channel.sendText(chatId, "\u{1F4AC} Context preserved.", { parseMode: "plain" });
|
|
15320
15517
|
}
|
|
15321
15518
|
clearSession(chatId);
|
|
15322
15519
|
clearModel(chatId);
|
|
@@ -15324,7 +15521,7 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15324
15521
|
clearChatGeminiSlot(chatId);
|
|
15325
15522
|
setBackend(chatId, backendId);
|
|
15326
15523
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Backend switched to ${targetAdapter.displayName}`, detail: { field: "backend", value: backendId } });
|
|
15327
|
-
await channel.sendText(chatId, `\u2705 Switched to ${targetAdapter.displayName}. Ready!`, "plain");
|
|
15524
|
+
await channel.sendText(chatId, `\u2705 Switched to ${targetAdapter.displayName}. Ready!`, { parseMode: "plain" });
|
|
15328
15525
|
}
|
|
15329
15526
|
async function sendHistoryView(chatId, channel, filter) {
|
|
15330
15527
|
const limit = filter.limit ?? 10;
|
|
@@ -15341,7 +15538,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15341
15538
|
}
|
|
15342
15539
|
const userMsgs = rows.filter((r) => r.role === "user").slice(0, limit);
|
|
15343
15540
|
if (userMsgs.length === 0) {
|
|
15344
|
-
await channel.sendText(chatId, "No conversation history found.", "plain");
|
|
15541
|
+
await channel.sendText(chatId, "No conversation history found.", { parseMode: "plain" });
|
|
15345
15542
|
return;
|
|
15346
15543
|
}
|
|
15347
15544
|
const lines = [`\u{1F4CB} Recent Conversation (last ${userMsgs.length})`, "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"];
|
|
@@ -15350,7 +15547,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15350
15547
|
const preview = row.content.slice(0, 80) + (row.content.length > 80 ? "\u2026" : "");
|
|
15351
15548
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${preview}`);
|
|
15352
15549
|
}
|
|
15353
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
15550
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
15354
15551
|
const filterRow = [
|
|
15355
15552
|
{ label: "Show More (25)", data: "hist:recent:25" },
|
|
15356
15553
|
{ label: "Today", data: "hist:today" },
|
|
@@ -15366,7 +15563,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15366
15563
|
async function sendMemoryPage(chatId, channel, page) {
|
|
15367
15564
|
const memories = listMemories();
|
|
15368
15565
|
if (memories.length === 0) {
|
|
15369
|
-
await channel.sendText(chatId, "No memories stored yet.", "plain");
|
|
15566
|
+
await channel.sendText(chatId, "No memories stored yet.", { parseMode: "plain" });
|
|
15370
15567
|
return;
|
|
15371
15568
|
}
|
|
15372
15569
|
const pageSize = 10;
|
|
@@ -15442,7 +15639,7 @@ async function sendHeartbeatKeyboard(chatId, channel) {
|
|
|
15442
15639
|
async function sendForgetPicker(chatId, channel, page) {
|
|
15443
15640
|
const memories = listMemories();
|
|
15444
15641
|
if (memories.length === 0) {
|
|
15445
|
-
await channel.sendText(chatId, "No memories to forget.", "plain");
|
|
15642
|
+
await channel.sendText(chatId, "No memories to forget.", { parseMode: "plain" });
|
|
15446
15643
|
return;
|
|
15447
15644
|
}
|
|
15448
15645
|
const { text, buttons } = buildPaginatedKeyboard({
|
|
@@ -15478,7 +15675,7 @@ function getJobStatusLabel(job) {
|
|
|
15478
15675
|
async function sendJobsBoard(chatId, channel, page) {
|
|
15479
15676
|
const jobs = listJobs();
|
|
15480
15677
|
if (jobs.length === 0) {
|
|
15481
|
-
await channel.sendText(chatId, "No scheduled jobs.\n\nCreate one: /schedule <description>", "plain");
|
|
15678
|
+
await channel.sendText(chatId, "No scheduled jobs.\n\nCreate one: /schedule <description>", { parseMode: "plain" });
|
|
15482
15679
|
return;
|
|
15483
15680
|
}
|
|
15484
15681
|
if (typeof channel.sendKeyboard !== "function") {
|
|
@@ -15489,7 +15686,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15489
15686
|
return `#${j.id} [${status}] ${schedule2}${tz}
|
|
15490
15687
|
${j.description}`;
|
|
15491
15688
|
});
|
|
15492
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
15689
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
15493
15690
|
return;
|
|
15494
15691
|
}
|
|
15495
15692
|
const headerLines = [];
|
|
@@ -15534,7 +15731,7 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15534
15731
|
[{ label: "Refresh List", data: "job:back" }]
|
|
15535
15732
|
]);
|
|
15536
15733
|
} else {
|
|
15537
|
-
await channel.sendText(chatId, "Job not found.", "plain");
|
|
15734
|
+
await channel.sendText(chatId, "Job not found.", { parseMode: "plain" });
|
|
15538
15735
|
}
|
|
15539
15736
|
return;
|
|
15540
15737
|
}
|
|
@@ -15560,7 +15757,7 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15560
15757
|
];
|
|
15561
15758
|
const text = lines.join("\n");
|
|
15562
15759
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15563
|
-
await channel.sendText(chatId, text, "plain");
|
|
15760
|
+
await channel.sendText(chatId, text, { parseMode: "plain" });
|
|
15564
15761
|
return;
|
|
15565
15762
|
}
|
|
15566
15763
|
const actionRow1 = [
|
|
@@ -15590,7 +15787,7 @@ async function sendJobRunsView(chatId, jobId, channel, page) {
|
|
|
15590
15787
|
[{ label: "\u2190 Back to Job", data: `job:view:${jobId}` }]
|
|
15591
15788
|
]);
|
|
15592
15789
|
} else {
|
|
15593
|
-
await channel.sendText(chatId, msg, "plain");
|
|
15790
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
15594
15791
|
}
|
|
15595
15792
|
return;
|
|
15596
15793
|
}
|
|
@@ -15601,7 +15798,7 @@ async function sendJobRunsView(chatId, jobId, channel, page) {
|
|
|
15601
15798
|
Error: ${r.error.slice(0, 100)}` : "";
|
|
15602
15799
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${duration}${error3}`;
|
|
15603
15800
|
});
|
|
15604
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
15801
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
15605
15802
|
return;
|
|
15606
15803
|
}
|
|
15607
15804
|
const statusEmoji = {
|
|
@@ -15648,11 +15845,11 @@ async function sendJobPicker(chatId, channel, action) {
|
|
|
15648
15845
|
const jobs = action === "resume" ? allJobs.filter((j) => j.active && !j.enabled) : action === "pause" ? allJobs.filter((j) => j.active && j.enabled) : allJobs.filter((j) => j.active);
|
|
15649
15846
|
if (jobs.length === 0) {
|
|
15650
15847
|
const msg = action === "resume" ? "No paused jobs." : action === "pause" ? "No active jobs to pause." : "No active jobs.";
|
|
15651
|
-
await channel.sendText(chatId, msg, "plain");
|
|
15848
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
15652
15849
|
return;
|
|
15653
15850
|
}
|
|
15654
15851
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15655
|
-
await channel.sendText(chatId, `Usage: /${action} <job-id>`, "plain");
|
|
15852
|
+
await channel.sendText(chatId, `Usage: /${action} <job-id>`, { parseMode: "plain" });
|
|
15656
15853
|
return;
|
|
15657
15854
|
}
|
|
15658
15855
|
const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
|
|
@@ -15723,7 +15920,7 @@ async function handleCallback(chatId, data, channel) {
|
|
|
15723
15920
|
const previous = getBackend(chatId);
|
|
15724
15921
|
if (chosen === previous) {
|
|
15725
15922
|
const adapter = getAdapter(chosen);
|
|
15726
|
-
await channel.sendText(chatId, `Already using ${adapter.displayName}.`, "plain");
|
|
15923
|
+
await channel.sendText(chatId, `Already using ${adapter.displayName}.`, { parseMode: "plain" });
|
|
15727
15924
|
return;
|
|
15728
15925
|
}
|
|
15729
15926
|
await sendBackendSwitchConfirmation(chatId, chosen, channel);
|
|
@@ -15737,14 +15934,14 @@ async function handleCallback(chatId, data, channel) {
|
|
|
15737
15934
|
if (!getAllBackendIds().includes(chosen)) return;
|
|
15738
15935
|
await doBackendSwitch(chatId, chosen, channel);
|
|
15739
15936
|
} else if (data.startsWith("backend_cancel:") || data === "backend_cancel") {
|
|
15740
|
-
await channel.sendText(chatId, "Switch cancelled.", "plain");
|
|
15937
|
+
await channel.sendText(chatId, "Switch cancelled.", { parseMode: "plain" });
|
|
15741
15938
|
} else if (data.startsWith("model:")) {
|
|
15742
15939
|
const chosen = data.slice(6);
|
|
15743
15940
|
let adapter;
|
|
15744
15941
|
try {
|
|
15745
15942
|
adapter = getAdapterForChat(chatId);
|
|
15746
15943
|
} catch {
|
|
15747
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
15944
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
15748
15945
|
return;
|
|
15749
15946
|
}
|
|
15750
15947
|
const modelInfo = adapter.availableModels[chosen];
|
|
@@ -15766,30 +15963,30 @@ Select thinking/effort level:`,
|
|
|
15766
15963
|
thinkingButtons
|
|
15767
15964
|
);
|
|
15768
15965
|
} else {
|
|
15769
|
-
await channel.sendText(chatId, `Model set to ${modelInfo.label}. Session continues.`, "plain");
|
|
15966
|
+
await channel.sendText(chatId, `Model set to ${modelInfo.label}. Session continues.`, { parseMode: "plain" });
|
|
15770
15967
|
}
|
|
15771
15968
|
} else {
|
|
15772
|
-
await channel.sendText(chatId, `Model switched to ${modelInfo.label}. Session continues.`, "plain");
|
|
15969
|
+
await channel.sendText(chatId, `Model switched to ${modelInfo.label}. Session continues.`, { parseMode: "plain" });
|
|
15773
15970
|
}
|
|
15774
15971
|
} else if (data.startsWith("thinking:")) {
|
|
15775
15972
|
const level = data.slice(9);
|
|
15776
15973
|
setThinkingLevel(chatId, level);
|
|
15777
15974
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Thinking level set to ${level}`, detail: { field: "thinking", value: level } });
|
|
15778
15975
|
const label2 = level === "auto" ? "Auto" : level.replace("_", " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
15779
|
-
await channel.sendText(chatId, `Thinking level set to: ${label2}`, "plain");
|
|
15976
|
+
await channel.sendText(chatId, `Thinking level set to: ${label2}`, { parseMode: "plain" });
|
|
15780
15977
|
} else if (data.startsWith("summarizer:")) {
|
|
15781
15978
|
const rest = data.slice(11);
|
|
15782
15979
|
if (rest === "auto") {
|
|
15783
15980
|
clearSummarizer(chatId);
|
|
15784
|
-
await channel.sendText(chatId, "Summarizer set to auto (uses active backend).", "plain");
|
|
15981
|
+
await channel.sendText(chatId, "Summarizer set to auto (uses active backend).", { parseMode: "plain" });
|
|
15785
15982
|
} else if (rest === "off") {
|
|
15786
15983
|
setSummarizer(chatId, "off", null);
|
|
15787
|
-
await channel.sendText(chatId, "Session summarization disabled.", "plain");
|
|
15984
|
+
await channel.sendText(chatId, "Session summarization disabled.", { parseMode: "plain" });
|
|
15788
15985
|
} else {
|
|
15789
15986
|
const [bk, ...modelParts] = rest.split(":");
|
|
15790
15987
|
const mdl = modelParts.join(":") || null;
|
|
15791
15988
|
setSummarizer(chatId, bk, mdl);
|
|
15792
|
-
await channel.sendText(chatId, `Summarizer pinned to ${bk}:${mdl ?? "default"}.`, "plain");
|
|
15989
|
+
await channel.sendText(chatId, `Summarizer pinned to ${bk}:${mdl ?? "default"}.`, { parseMode: "plain" });
|
|
15793
15990
|
}
|
|
15794
15991
|
} else if (data.startsWith("perms:")) {
|
|
15795
15992
|
let chosen = data.slice(6);
|
|
@@ -15797,7 +15994,7 @@ Select thinking/effort level:`,
|
|
|
15797
15994
|
if (!PERM_MODES[chosen]) return;
|
|
15798
15995
|
const previous = getMode(chatId);
|
|
15799
15996
|
if (chosen === previous) {
|
|
15800
|
-
await channel.sendText(chatId, `Already in ${chosen} mode.`, "plain");
|
|
15997
|
+
await channel.sendText(chatId, `Already in ${chosen} mode.`, { parseMode: "plain" });
|
|
15801
15998
|
return;
|
|
15802
15999
|
}
|
|
15803
16000
|
setMode(chatId, chosen);
|
|
@@ -15806,14 +16003,14 @@ Select thinking/effort level:`,
|
|
|
15806
16003
|
chatId,
|
|
15807
16004
|
`Permission mode: ${chosen}
|
|
15808
16005
|
${PERM_MODES[chosen]}`,
|
|
15809
|
-
"plain"
|
|
16006
|
+
{ parseMode: "plain" }
|
|
15810
16007
|
);
|
|
15811
16008
|
} else if (data.startsWith("perm:escalate:")) {
|
|
15812
16009
|
const targetMode = data.slice(14);
|
|
15813
16010
|
if (!PERM_MODES[targetMode]) return;
|
|
15814
16011
|
setMode(chatId, targetMode);
|
|
15815
16012
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Permission escalated to ${targetMode}`, detail: { field: "permissions", value: targetMode } });
|
|
15816
|
-
await channel.sendText(chatId, `Switched to ${targetMode} mode. Re-processing your request...`, "plain");
|
|
16013
|
+
await channel.sendText(chatId, `Switched to ${targetMode} mode. Re-processing your request...`, { parseMode: "plain" });
|
|
15817
16014
|
const pending = getPendingEscalation(chatId);
|
|
15818
16015
|
if (pending) {
|
|
15819
16016
|
removePendingEscalation(chatId);
|
|
@@ -15821,12 +16018,12 @@ ${PERM_MODES[chosen]}`,
|
|
|
15821
16018
|
}
|
|
15822
16019
|
} else if (data === "perm:deny") {
|
|
15823
16020
|
removePendingEscalation(chatId);
|
|
15824
|
-
await channel.sendText(chatId, "Keeping current mode.", "plain");
|
|
16021
|
+
await channel.sendText(chatId, "Keeping current mode.", { parseMode: "plain" });
|
|
15825
16022
|
} else if (data.startsWith("verbose:")) {
|
|
15826
16023
|
const chosen = data.slice(8);
|
|
15827
16024
|
if (!VERBOSE_LEVELS[chosen]) return;
|
|
15828
16025
|
setVerboseLevel(chatId, chosen);
|
|
15829
|
-
await channel.sendText(chatId, `Tool visibility: ${VERBOSE_LEVELS[chosen]}`, "plain");
|
|
16026
|
+
await channel.sendText(chatId, `Tool visibility: ${VERBOSE_LEVELS[chosen]}`, { parseMode: "plain" });
|
|
15830
16027
|
} else if (data.startsWith("tool:toggle:")) {
|
|
15831
16028
|
const toolName = data.slice(12);
|
|
15832
16029
|
if (!ALL_TOOLS.includes(toolName)) return;
|
|
@@ -15834,11 +16031,11 @@ ${PERM_MODES[chosen]}`,
|
|
|
15834
16031
|
await channel.sendText(
|
|
15835
16032
|
chatId,
|
|
15836
16033
|
`${newState ? "\u2705" : "\u274C"} ${toolName} ${newState ? "enabled" : "disabled"}`,
|
|
15837
|
-
"plain"
|
|
16034
|
+
{ parseMode: "plain" }
|
|
15838
16035
|
);
|
|
15839
16036
|
} else if (data === "tool:reset") {
|
|
15840
16037
|
resetTools(chatId);
|
|
15841
|
-
await channel.sendText(chatId, "Tool configuration reset \u2014 all tools enabled.", "plain");
|
|
16038
|
+
await channel.sendText(chatId, "Tool configuration reset \u2014 all tools enabled.", { parseMode: "plain" });
|
|
15842
16039
|
} else if (data.startsWith("sched:")) {
|
|
15843
16040
|
await handleWizardCallback(chatId, data, channel);
|
|
15844
16041
|
} else if (data.startsWith("profile:")) {
|
|
@@ -15847,9 +16044,9 @@ ${PERM_MODES[chosen]}`,
|
|
|
15847
16044
|
const parts = data.slice(11).split(":");
|
|
15848
16045
|
if (parts[0] === "yes" && parts.length >= 3) {
|
|
15849
16046
|
appendToUserProfile(parts[1], parts.slice(2).join(":"));
|
|
15850
|
-
await channel.sendText(chatId, `Preference saved: ${parts[1]}`, "plain");
|
|
16047
|
+
await channel.sendText(chatId, `Preference saved: ${parts[1]}`, { parseMode: "plain" });
|
|
15851
16048
|
} else {
|
|
15852
|
-
await channel.sendText(chatId, "Preference not saved.", "plain");
|
|
16049
|
+
await channel.sendText(chatId, "Preference not saved.", { parseMode: "plain" });
|
|
15853
16050
|
}
|
|
15854
16051
|
} else if (data.startsWith("shell:")) {
|
|
15855
16052
|
const parts = data.split(":");
|
|
@@ -15858,7 +16055,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15858
16055
|
if (action === "confirm") {
|
|
15859
16056
|
const pending = getPendingCommand(id);
|
|
15860
16057
|
if (!pending) {
|
|
15861
|
-
await channel.sendText(chatId, "Confirmation expired. Please re-send the command.", "plain");
|
|
16058
|
+
await channel.sendText(chatId, "Confirmation expired. Please re-send the command.", { parseMode: "plain" });
|
|
15862
16059
|
return;
|
|
15863
16060
|
}
|
|
15864
16061
|
removePendingCommand(id);
|
|
@@ -15869,27 +16066,27 @@ ${PERM_MODES[chosen]}`,
|
|
|
15869
16066
|
}
|
|
15870
16067
|
} else if (action === "cancel") {
|
|
15871
16068
|
removePendingCommand(id);
|
|
15872
|
-
await channel.sendText(chatId, "Command cancelled.", "plain");
|
|
16069
|
+
await channel.sendText(chatId, "Command cancelled.", { parseMode: "plain" });
|
|
15873
16070
|
}
|
|
15874
16071
|
} else if (data.startsWith("cwd:")) {
|
|
15875
16072
|
const parts = data.split(":");
|
|
15876
16073
|
const action = parts[1];
|
|
15877
16074
|
const targetChatId = parts.slice(2).join(":");
|
|
15878
16075
|
if (action === "keep") {
|
|
15879
|
-
await channel.sendText(chatId, "Session kept. The agent will continue with existing context.", "plain");
|
|
16076
|
+
await channel.sendText(chatId, "Session kept. The agent will continue with existing context.", { parseMode: "plain" });
|
|
15880
16077
|
} else if (action === "summarize") {
|
|
15881
16078
|
await summarizeSession(targetChatId);
|
|
15882
16079
|
clearSession(targetChatId);
|
|
15883
|
-
await channel.sendText(chatId, "Session summarized and reset. Context preserved in memory.", "plain");
|
|
16080
|
+
await channel.sendText(chatId, "Session summarized and reset. Context preserved in memory.", { parseMode: "plain" });
|
|
15884
16081
|
} else if (action === "reset") {
|
|
15885
16082
|
clearSession(targetChatId);
|
|
15886
|
-
await channel.sendText(chatId, "Session reset. Clean slate.", "plain");
|
|
16083
|
+
await channel.sendText(chatId, "Session reset. Clean slate.", { parseMode: "plain" });
|
|
15887
16084
|
}
|
|
15888
16085
|
} else if (data.startsWith("cwdpick:")) {
|
|
15889
16086
|
const alias = data.slice(8);
|
|
15890
16087
|
const bookmark = getBookmark(chatId, alias);
|
|
15891
16088
|
if (!bookmark) {
|
|
15892
|
-
await channel.sendText(chatId, `Bookmark '${alias}' no longer exists.`, "plain");
|
|
16089
|
+
await channel.sendText(chatId, `Bookmark '${alias}' no longer exists.`, { parseMode: "plain" });
|
|
15893
16090
|
return;
|
|
15894
16091
|
}
|
|
15895
16092
|
setCwd(chatId, bookmark.path);
|
|
@@ -15904,22 +16101,36 @@ ${PERM_MODES[chosen]}`,
|
|
|
15904
16101
|
if (action === "now" && pending) {
|
|
15905
16102
|
pendingInterrupts.delete(targetChatId);
|
|
15906
16103
|
stopAgent(targetChatId);
|
|
15907
|
-
await channel.sendText(chatId, "\u26A1 Stopping current task and processing your message\u2026", "plain");
|
|
16104
|
+
await channel.sendText(chatId, "\u26A1 Stopping current task and processing your message\u2026", { parseMode: "plain" });
|
|
15908
16105
|
bypassBusyCheck.add(targetChatId);
|
|
15909
16106
|
handleMessage(pending.msg, pending.channel).catch(() => {
|
|
15910
16107
|
});
|
|
15911
16108
|
} else if (action === "queue" && pending) {
|
|
15912
16109
|
pendingInterrupts.delete(targetChatId);
|
|
15913
16110
|
bypassBusyCheck.add(targetChatId);
|
|
15914
|
-
await channel.sendText(chatId, "\u{1F4E5} Message queued \u2014 will process after current task.", "plain");
|
|
16111
|
+
await channel.sendText(chatId, "\u{1F4E5} Message queued \u2014 will process after current task.", { parseMode: "plain" });
|
|
15915
16112
|
handleMessage(pending.msg, pending.channel).catch(() => {
|
|
15916
16113
|
});
|
|
16114
|
+
} else if (action === "sidequest") {
|
|
16115
|
+
const pending2 = pendingInterrupts.get(targetChatId);
|
|
16116
|
+
if (pending2) {
|
|
16117
|
+
pendingInterrupts.delete(targetChatId);
|
|
16118
|
+
handleSideQuest(targetChatId, pending2.msg, pending2.channel).catch(
|
|
16119
|
+
(err) => error(`[router] Side quest error for ${targetChatId}:`, err)
|
|
16120
|
+
);
|
|
16121
|
+
} else {
|
|
16122
|
+
await channel.sendText(chatId, "Main task finished \u2014 your message was already processed.", { parseMode: "plain" });
|
|
16123
|
+
}
|
|
15917
16124
|
} else if (action === "discard") {
|
|
15918
16125
|
pendingInterrupts.delete(targetChatId);
|
|
15919
|
-
await channel.sendText(chatId, "\u{1F5D1} Message discarded.", "plain");
|
|
16126
|
+
await channel.sendText(chatId, "\u{1F5D1} Message discarded.", { parseMode: "plain" });
|
|
15920
16127
|
} else {
|
|
15921
|
-
await channel.sendText(chatId, "Message already processed or expired.", "plain");
|
|
16128
|
+
await channel.sendText(chatId, "Message already processed or expired.", { parseMode: "plain" });
|
|
15922
16129
|
}
|
|
16130
|
+
} else if (data.startsWith("sq:cancel:")) {
|
|
16131
|
+
const sqId = data.slice("sq:cancel:".length);
|
|
16132
|
+
stopAgent(sqId);
|
|
16133
|
+
await channel.sendText(chatId, "\u{1F5FA} Side quest cancelled.", { parseMode: "plain" });
|
|
15923
16134
|
} else if (data.startsWith("fallback:")) {
|
|
15924
16135
|
const parts = data.split(":");
|
|
15925
16136
|
const targetBackend = parts[1];
|
|
@@ -15927,7 +16138,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15927
16138
|
const pendingMsg = pendingFallbackMessages.get(targetChatId);
|
|
15928
16139
|
if (targetBackend === "wait") {
|
|
15929
16140
|
pendingFallbackMessages.delete(targetChatId);
|
|
15930
|
-
await channel.sendText(chatId, "OK \u2014 you can switch manually with /backend when ready.", "plain");
|
|
16141
|
+
await channel.sendText(chatId, "OK \u2014 you can switch manually with /backend when ready.", { parseMode: "plain" });
|
|
15931
16142
|
} else if (pendingMsg) {
|
|
15932
16143
|
pendingFallbackMessages.delete(targetChatId);
|
|
15933
16144
|
if (pendingMsg.agentMode) pendingMsg.msg.agentMode = pendingMsg.agentMode;
|
|
@@ -15937,10 +16148,10 @@ ${PERM_MODES[chosen]}`,
|
|
|
15937
16148
|
clearSession(targetChatId);
|
|
15938
16149
|
setBackend(targetChatId, targetBackend);
|
|
15939
16150
|
const adapter = getAdapter(targetBackend);
|
|
15940
|
-
await channel.sendText(chatId, `Switched to ${adapter.displayName}. Resending your message\u2026`, "plain");
|
|
16151
|
+
await channel.sendText(chatId, `Switched to ${adapter.displayName}. Resending your message\u2026`, { parseMode: "plain" });
|
|
15941
16152
|
await handleMessage(pendingMsg.msg, pendingMsg.channel);
|
|
15942
16153
|
} else {
|
|
15943
|
-
await channel.sendText(chatId, "Fallback expired. Use /backend to switch manually.", "plain");
|
|
16154
|
+
await channel.sendText(chatId, "Fallback expired. Use /backend to switch manually.", { parseMode: "plain" });
|
|
15944
16155
|
}
|
|
15945
16156
|
} else if (data.startsWith("voice:")) {
|
|
15946
16157
|
const action = data.slice(6);
|
|
@@ -15948,7 +16159,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15948
16159
|
const current = isVoiceEnabled(chatId);
|
|
15949
16160
|
const desired = action === "on";
|
|
15950
16161
|
if (current !== desired) toggleVoice(chatId);
|
|
15951
|
-
await channel.sendText(chatId, desired ? "\u{1F50A} Voice responses enabled." : "\u{1F507} Voice responses disabled.", "plain");
|
|
16162
|
+
await channel.sendText(chatId, desired ? "\u{1F50A} Voice responses enabled." : "\u{1F507} Voice responses disabled.", { parseMode: "plain" });
|
|
15952
16163
|
}
|
|
15953
16164
|
} else if (data.startsWith("style:")) {
|
|
15954
16165
|
const selectedStyle = data.split(":")[1];
|
|
@@ -15963,7 +16174,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15963
16174
|
]
|
|
15964
16175
|
]);
|
|
15965
16176
|
}
|
|
15966
|
-
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, "plain");
|
|
16177
|
+
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, { parseMode: "plain" });
|
|
15967
16178
|
}
|
|
15968
16179
|
} else if (data.startsWith("agentmode:")) {
|
|
15969
16180
|
const mode = data.split(":")[1];
|
|
@@ -15974,7 +16185,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15974
16185
|
} catch {
|
|
15975
16186
|
}
|
|
15976
16187
|
clearSession(chatId);
|
|
15977
|
-
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, "html");
|
|
16188
|
+
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
|
|
15978
16189
|
}
|
|
15979
16190
|
return;
|
|
15980
16191
|
} else if (data.startsWith("agents:")) {
|
|
@@ -15985,11 +16196,11 @@ ${PERM_MODES[chosen]}`,
|
|
|
15985
16196
|
const agents2 = listActiveAgents(db3);
|
|
15986
16197
|
const match = agents2.find((a) => a.id.startsWith(shortId));
|
|
15987
16198
|
if (!match) {
|
|
15988
|
-
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped. Use /agents to refresh.`, "plain");
|
|
16199
|
+
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped. Use /agents to refresh.`, { parseMode: "plain" });
|
|
15989
16200
|
return;
|
|
15990
16201
|
}
|
|
15991
16202
|
const ok = cancelAgent(match.id);
|
|
15992
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
16203
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
15993
16204
|
} else if (rest === "tasks") {
|
|
15994
16205
|
const synth = { chatId, messageId: "", text: "", senderName: "User", type: "command", source: "telegram", command: "tasks", commandArgs: "" };
|
|
15995
16206
|
await handleCommand(synth, channel);
|
|
@@ -16003,16 +16214,16 @@ ${PERM_MODES[chosen]}`,
|
|
|
16003
16214
|
const agents2 = listActiveAgents(db3);
|
|
16004
16215
|
const match = agents2.find((a) => a.id.startsWith(shortId));
|
|
16005
16216
|
if (!match) {
|
|
16006
|
-
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped.`, "plain");
|
|
16217
|
+
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped.`, { parseMode: "plain" });
|
|
16007
16218
|
return;
|
|
16008
16219
|
}
|
|
16009
16220
|
const ok = cancelAgent(match.id);
|
|
16010
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
16221
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
16011
16222
|
} else if (rest === "all") {
|
|
16012
16223
|
const count = cancelAllAgents(chatId);
|
|
16013
|
-
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", "plain");
|
|
16224
|
+
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", { parseMode: "plain" });
|
|
16014
16225
|
} else if (rest === "cancel") {
|
|
16015
|
-
await channel.sendText(chatId, "Cancelled.", "plain");
|
|
16226
|
+
await channel.sendText(chatId, "Cancelled.", { parseMode: "plain" });
|
|
16016
16227
|
}
|
|
16017
16228
|
return;
|
|
16018
16229
|
} else if (data.startsWith("tasks:")) {
|
|
@@ -16022,7 +16233,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
16022
16233
|
const db3 = getDb();
|
|
16023
16234
|
const task = getTask(db3, taskId);
|
|
16024
16235
|
if (!task) {
|
|
16025
|
-
await channel.sendText(chatId, "Task not found or outdated. Use /tasks to refresh.", "plain");
|
|
16236
|
+
await channel.sendText(chatId, "Task not found or outdated. Use /tasks to refresh.", { parseMode: "plain" });
|
|
16026
16237
|
return;
|
|
16027
16238
|
}
|
|
16028
16239
|
const STATUS_EMOJI_TASK = {
|
|
@@ -16046,7 +16257,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
16046
16257
|
task.result ? `
|
|
16047
16258
|
Result: ${task.result.slice(0, 500)}` : ""
|
|
16048
16259
|
].filter(Boolean);
|
|
16049
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
16260
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
16050
16261
|
}
|
|
16051
16262
|
return;
|
|
16052
16263
|
} else if (data.startsWith("grotation:")) {
|
|
@@ -16056,25 +16267,25 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16056
16267
|
if (mode === "accounts") {
|
|
16057
16268
|
const oauthSlots = getGeminiSlots().filter((s) => s.enabled && s.slotType === "oauth");
|
|
16058
16269
|
if (oauthSlots.length === 0) {
|
|
16059
|
-
await channel.sendText(chatId, "\u26A0\uFE0F No OAuth accounts configured. Add one with <code>cc-claw gemini add-account</code> or choose a different mode.", "html");
|
|
16270
|
+
await channel.sendText(chatId, "\u26A0\uFE0F No OAuth accounts configured. Add one with <code>cc-claw gemini add-account</code> or choose a different mode.", { parseMode: "html" });
|
|
16060
16271
|
return;
|
|
16061
16272
|
}
|
|
16062
16273
|
} else if (mode === "keys") {
|
|
16063
16274
|
const keySlots = getGeminiSlots().filter((s) => s.enabled && s.slotType === "api_key");
|
|
16064
16275
|
if (keySlots.length === 0) {
|
|
16065
|
-
await channel.sendText(chatId, "\u26A0\uFE0F No API keys configured. Add one with <code>cc-claw gemini add-key</code> or choose a different mode.", "html");
|
|
16276
|
+
await channel.sendText(chatId, "\u26A0\uFE0F No API keys configured. Add one with <code>cc-claw gemini add-key</code> or choose a different mode.", { parseMode: "html" });
|
|
16066
16277
|
return;
|
|
16067
16278
|
}
|
|
16068
16279
|
}
|
|
16069
16280
|
setGeminiRotationMode(mode);
|
|
16070
16281
|
const modeLabels = { off: "Off", all: "All", accounts: "\u{1F468}\u{1F3FD}\u200D\u{1F4BB} Accounts only", keys: "\u{1F511} Keys only" };
|
|
16071
|
-
await channel.sendText(chatId, `Rotation mode set to <b>${modeLabels[mode]}</b>.`, "html");
|
|
16282
|
+
await channel.sendText(chatId, `Rotation mode set to <b>${modeLabels[mode]}</b>.`, { parseMode: "html" });
|
|
16072
16283
|
return;
|
|
16073
16284
|
} else if (data.startsWith("gslot:")) {
|
|
16074
16285
|
const val = data.split(":")[1];
|
|
16075
16286
|
if (val === "auto") {
|
|
16076
16287
|
clearChatGeminiSlot(chatId);
|
|
16077
|
-
await channel.sendText(chatId, "Gemini slot set to <b>\u{1F504} auto rotation</b>.", "html");
|
|
16288
|
+
await channel.sendText(chatId, "Gemini slot set to <b>\u{1F504} auto rotation</b>.", { parseMode: "html" });
|
|
16078
16289
|
} else {
|
|
16079
16290
|
const slotId = parseInt(val, 10);
|
|
16080
16291
|
const slots = getGeminiSlots();
|
|
@@ -16083,14 +16294,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16083
16294
|
pinChatGeminiSlot(chatId, slotId);
|
|
16084
16295
|
const label2 = slot.label || `slot-${slot.id}`;
|
|
16085
16296
|
const icon = slot.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
16086
|
-
await channel.sendText(chatId, `Pinned to ${icon} <b>${label2}</b>`, "html");
|
|
16297
|
+
await channel.sendText(chatId, `Pinned to ${icon} <b>${label2}</b>`, { parseMode: "html" });
|
|
16087
16298
|
}
|
|
16088
16299
|
}
|
|
16089
16300
|
return;
|
|
16090
16301
|
} else if (data === "gopen:accounts") {
|
|
16091
16302
|
const slots = getGeminiSlots();
|
|
16092
16303
|
if (slots.length === 0) {
|
|
16093
|
-
await channel.sendText(chatId, "No Gemini credentials configured.\nAdd with: <code>cc-claw gemini add-key</code> or <code>cc-claw gemini add-account</code>", "html");
|
|
16304
|
+
await channel.sendText(chatId, "No Gemini credentials configured.\nAdd with: <code>cc-claw gemini add-key</code> or <code>cc-claw gemini add-account</code>", { parseMode: "html" });
|
|
16094
16305
|
return;
|
|
16095
16306
|
}
|
|
16096
16307
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16122,7 +16333,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16122
16333
|
await channel.sendText(
|
|
16123
16334
|
chatId,
|
|
16124
16335
|
value === "on" ? "\u{1F9E0} Model signature enabled. Each response will show the active model and thinking level." : "Model signature disabled.",
|
|
16125
|
-
"plain"
|
|
16336
|
+
{ parseMode: "plain" }
|
|
16126
16337
|
);
|
|
16127
16338
|
} else if (data.startsWith("vcfg:")) {
|
|
16128
16339
|
const parts = data.slice(5).split(":");
|
|
@@ -16134,14 +16345,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16134
16345
|
await channel.sendText(
|
|
16135
16346
|
chatId,
|
|
16136
16347
|
"\u26A0\uFE0F Grok requires `XAI_API_KEY` to be set.\n\nAdd it to your config:\n```\necho 'XAI_API_KEY=your-key-here' >> ~/.cc-claw/.env\ncc-claw service restart\n```\n\nGet a key at: https://console.x.ai/team/default/api-keys\n\nSetting Grok as your provider \u2014 it will activate once the key is added.",
|
|
16137
|
-
"markdown"
|
|
16348
|
+
{ parseMode: "markdown" }
|
|
16138
16349
|
);
|
|
16139
16350
|
}
|
|
16140
16351
|
if (provider === "elevenlabs" && !process.env.ELEVENLABS_API_KEY) {
|
|
16141
16352
|
await channel.sendText(
|
|
16142
16353
|
chatId,
|
|
16143
16354
|
"\u26A0\uFE0F ElevenLabs requires `ELEVENLABS_API_KEY` to be set.\n\nAdd it to your config:\n```\necho 'ELEVENLABS_API_KEY=your-key-here' >> ~/.cc-claw/.env\ncc-claw service restart\n```\n\nGet a key at: https://elevenlabs.io/api\n\nSetting ElevenLabs as your provider \u2014 it will activate once the key is added.",
|
|
16144
|
-
"markdown"
|
|
16355
|
+
{ parseMode: "markdown" }
|
|
16145
16356
|
);
|
|
16146
16357
|
}
|
|
16147
16358
|
const defaultVoice = provider === "grok" ? "eve" : provider === "macos" ? "Samantha" : "21m00Tcm4TlvDq8ikWAM";
|
|
@@ -16153,7 +16364,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16153
16364
|
const config2 = getVoiceConfig(chatId);
|
|
16154
16365
|
setVoiceProvider(chatId, config2.provider, voiceId);
|
|
16155
16366
|
const voiceName = config2.provider === "elevenlabs" ? ELEVENLABS_VOICES[voiceId]?.name ?? voiceId : config2.provider === "macos" ? MACOS_VOICES[voiceId]?.name ?? voiceId : voiceId;
|
|
16156
|
-
await channel.sendText(chatId, `\u2705 Voice set to: ${voiceName}`, "plain");
|
|
16367
|
+
await channel.sendText(chatId, `\u2705 Voice set to: ${voiceName}`, { parseMode: "plain" });
|
|
16157
16368
|
}
|
|
16158
16369
|
} else if (data.startsWith("skills:page:")) {
|
|
16159
16370
|
const page = parseInt(data.slice(12), 10);
|
|
@@ -16172,7 +16383,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16172
16383
|
const skills2 = await discoverAllSkills();
|
|
16173
16384
|
const skill = skillSource ? skills2.find((s) => s.name === skillName && s.source === skillSource) : skills2.find((s) => s.name === skillName);
|
|
16174
16385
|
if (!skill) {
|
|
16175
|
-
await channel.sendText(chatId, `Skill "${skillName}" not found.`, "plain");
|
|
16386
|
+
await channel.sendText(chatId, `Skill "${skillName}" not found.`, { parseMode: "plain" });
|
|
16176
16387
|
return;
|
|
16177
16388
|
}
|
|
16178
16389
|
const activeBackend = getBackend(chatId) ?? "claude";
|
|
@@ -16180,13 +16391,13 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16180
16391
|
await channel.sendText(
|
|
16181
16392
|
chatId,
|
|
16182
16393
|
`Note: "${skillName}" lists compatible backends as [${skill.compatibleBackends.join(", ")}], but active backend is ${activeBackend}. Proceeding anyway.`,
|
|
16183
|
-
"plain"
|
|
16394
|
+
{ parseMode: "plain" }
|
|
16184
16395
|
);
|
|
16185
16396
|
}
|
|
16186
16397
|
const raw = await readFile5(skill.filePath, "utf-8");
|
|
16187
16398
|
const skillContent = stripFrontmatter2(raw);
|
|
16188
16399
|
const tags = skill.sources.join(", ");
|
|
16189
|
-
await channel.sendText(chatId, `Loading skill: ${skillName} [${tags}]...`, "plain");
|
|
16400
|
+
await channel.sendText(chatId, `Loading skill: ${skillName} [${tags}]...`, { parseMode: "plain" });
|
|
16190
16401
|
const skillModel = resolveModel(chatId);
|
|
16191
16402
|
const sMode = getMode(chatId);
|
|
16192
16403
|
const sVerbose = getVerboseLevel(chatId);
|
|
@@ -16199,19 +16410,64 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16199
16410
|
const action = parts[1];
|
|
16200
16411
|
const idStr = parts[2];
|
|
16201
16412
|
switch (action) {
|
|
16413
|
+
case "menu": {
|
|
16414
|
+
const { getReflectionStatus: getRefStatus, getUnprocessedSignalCount: getUnprocessedSignalCount2, getPendingInsightCount: getPendingInsightCount2, getLastAnalysisTime: getLastAnalysisTime2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16415
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16416
|
+
const menuActive = getRefStatus(getDb2(), chatId) === "active";
|
|
16417
|
+
if (!menuActive) {
|
|
16418
|
+
const { buildEvolveOnboardingKeyboard: buildEvolveOnboardingKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16419
|
+
const text = [
|
|
16420
|
+
"Self-Learning & Evolution",
|
|
16421
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
16422
|
+
"",
|
|
16423
|
+
"Teach your assistant to improve over time.",
|
|
16424
|
+
"",
|
|
16425
|
+
"When enabled, CC-Claw watches for corrections,",
|
|
16426
|
+
"preferences, and frustration in your messages,",
|
|
16427
|
+
"then proposes changes to its personality and",
|
|
16428
|
+
"behavior files (SOUL.md, USER.md).",
|
|
16429
|
+
"",
|
|
16430
|
+
"You review and approve every change."
|
|
16431
|
+
].join("\n");
|
|
16432
|
+
await channel.sendKeyboard(chatId, text, buildEvolveOnboardingKeyboard2());
|
|
16433
|
+
} else {
|
|
16434
|
+
const { buildEvolveMenuKeyboard: buildEvolveMenuKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16435
|
+
const signals = getUnprocessedSignalCount2(getDb2(), chatId);
|
|
16436
|
+
const pending = getPendingInsightCount2(getDb2(), chatId);
|
|
16437
|
+
const lastTime = getLastAnalysisTime2(getDb2(), chatId);
|
|
16438
|
+
let lastText = "never";
|
|
16439
|
+
if (lastTime) {
|
|
16440
|
+
const diffMs = Date.now() - (/* @__PURE__ */ new Date(lastTime + "Z")).getTime();
|
|
16441
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
16442
|
+
if (diffHours < 1) lastText = "< 1 hour ago";
|
|
16443
|
+
else if (diffHours < 24) lastText = `${diffHours}h ago`;
|
|
16444
|
+
else lastText = `${Math.floor(diffHours / 24)}d ago`;
|
|
16445
|
+
}
|
|
16446
|
+
const lines = [
|
|
16447
|
+
"Self-Learning & Evolution",
|
|
16448
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
16449
|
+
"",
|
|
16450
|
+
`\u2705 Active`,
|
|
16451
|
+
`Signals: ${signals} pending \xB7 Proposals: ${pending}`,
|
|
16452
|
+
`Last analysis: ${lastText}`
|
|
16453
|
+
];
|
|
16454
|
+
await channel.sendKeyboard(chatId, lines.join("\n"), buildEvolveMenuKeyboard2({ pendingProposals: pending, unprocessedSignals: signals }));
|
|
16455
|
+
}
|
|
16456
|
+
break;
|
|
16457
|
+
}
|
|
16202
16458
|
case "analyze": {
|
|
16203
16459
|
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
16204
16460
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16205
|
-
await channel.sendText(chatId, "Analyzing recent interactions...", "plain");
|
|
16461
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
16206
16462
|
try {
|
|
16207
|
-
const insights = await runAnalysis2(chatId);
|
|
16463
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
16208
16464
|
if (insights.length === 0) {
|
|
16209
|
-
await channel.sendText(chatId, "No new insights from recent interactions.", "plain");
|
|
16465
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
16210
16466
|
} else {
|
|
16211
|
-
await channel.sendText(chatId, formatNightlySummary2(insights), "plain");
|
|
16467
|
+
await channel.sendText(chatId, formatNightlySummary2(insights), { parseMode: "plain" });
|
|
16212
16468
|
}
|
|
16213
16469
|
} catch (e) {
|
|
16214
|
-
await channel.sendText(chatId, `Analysis failed: ${e}`, "plain");
|
|
16470
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
16215
16471
|
}
|
|
16216
16472
|
break;
|
|
16217
16473
|
}
|
|
@@ -16221,7 +16477,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16221
16477
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16222
16478
|
const pending = getPendingInsights2(getDb2(), chatId);
|
|
16223
16479
|
if (pending.length === 0) {
|
|
16224
|
-
await channel.sendText(chatId, "No pending proposals.", "plain");
|
|
16480
|
+
await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
|
|
16225
16481
|
} else {
|
|
16226
16482
|
for (const insight of pending.slice(0, 5)) {
|
|
16227
16483
|
const card = formatProposalCard2(insight);
|
|
@@ -16229,7 +16485,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16229
16485
|
await channel.sendKeyboard(chatId, card, kb);
|
|
16230
16486
|
}
|
|
16231
16487
|
if (pending.length > 5) {
|
|
16232
|
-
await channel.sendText(chatId, `${pending.length - 5} more proposals. Run /evolve again to see next batch.`, "plain");
|
|
16488
|
+
await channel.sendText(chatId, `${pending.length - 5} more proposals. Run /evolve again to see next batch.`, { parseMode: "plain" });
|
|
16233
16489
|
}
|
|
16234
16490
|
}
|
|
16235
16491
|
break;
|
|
@@ -16240,25 +16496,25 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16240
16496
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16241
16497
|
const insight = getInsightById2(getDb2(), parseInt(idStr, 10));
|
|
16242
16498
|
if (insight?.proposedDiff) {
|
|
16243
|
-
await channel.sendText(chatId, formatDiffCodeBlock2(insight.proposedDiff), "plain");
|
|
16499
|
+
await channel.sendText(chatId, formatDiffCodeBlock2(insight.proposedDiff), { parseMode: "plain" });
|
|
16244
16500
|
}
|
|
16245
16501
|
break;
|
|
16246
16502
|
}
|
|
16247
16503
|
case "apply": {
|
|
16248
16504
|
const { applyInsight: applyInsight2 } = await Promise.resolve().then(() => (init_apply(), apply_exports));
|
|
16249
16505
|
const result = await applyInsight2(parseInt(idStr, 10));
|
|
16250
|
-
await channel.sendText(chatId, result.message, "plain");
|
|
16506
|
+
await channel.sendText(chatId, result.message, { parseMode: "plain" });
|
|
16251
16507
|
break;
|
|
16252
16508
|
}
|
|
16253
16509
|
case "skip": {
|
|
16254
|
-
await channel.sendText(chatId, "Skipped \u2014 will show again next review.", "plain");
|
|
16510
|
+
await channel.sendText(chatId, "Skipped \u2014 will show again next review.", { parseMode: "plain" });
|
|
16255
16511
|
break;
|
|
16256
16512
|
}
|
|
16257
16513
|
case "reject": {
|
|
16258
16514
|
const { updateInsightStatus: updateInsightStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16259
16515
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16260
16516
|
updateInsightStatus2(getDb2(), parseInt(idStr, 10), "rejected");
|
|
16261
|
-
await channel.sendText(chatId, "Rejected. Won't propose similar changes.", "plain");
|
|
16517
|
+
await channel.sendText(chatId, "Rejected. Won't propose similar changes.", { parseMode: "plain" });
|
|
16262
16518
|
break;
|
|
16263
16519
|
}
|
|
16264
16520
|
case "stats": {
|
|
@@ -16273,7 +16529,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16273
16529
|
if (drift && (drift.soulDrift > 0.5 || drift.userDrift > 0.5)) {
|
|
16274
16530
|
report += "\n\nSOUL.md has changed significantly since reflection started.\nTap History in /evolve to review all applied changes.";
|
|
16275
16531
|
}
|
|
16276
|
-
await channel.sendText(chatId, report, "plain");
|
|
16532
|
+
await channel.sendText(chatId, report, { parseMode: "plain" });
|
|
16277
16533
|
break;
|
|
16278
16534
|
}
|
|
16279
16535
|
case "history": {
|
|
@@ -16293,7 +16549,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16293
16549
|
msg += `#${i.id} [${i.category}] ${i.insight}
|
|
16294
16550
|
`;
|
|
16295
16551
|
});
|
|
16296
|
-
await channel.sendText(chatId, msg, "plain");
|
|
16552
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
16297
16553
|
break;
|
|
16298
16554
|
}
|
|
16299
16555
|
case "toggle": {
|
|
@@ -16311,12 +16567,12 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16311
16567
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
16312
16568
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16313
16569
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
16314
|
-
await channel.sendText(chatId, "Self-learning enabled. Signal detection is now active.\nCreate a nightly cron job with /schedule to enable automatic analysis.", "plain");
|
|
16570
|
+
await channel.sendText(chatId, "\u2705 Self-learning enabled. Signal detection is now active.\nCreate a nightly cron job with /schedule to enable automatic analysis.", { parseMode: "plain" });
|
|
16315
16571
|
} else {
|
|
16316
16572
|
setReflectionStatus2(getDb2(), chatId, "frozen", null, null);
|
|
16317
16573
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16318
16574
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_frozen", summary: "Reflection disabled" });
|
|
16319
|
-
await channel.sendText(chatId, "Self-learning disabled. No signals will be collected.", "plain");
|
|
16575
|
+
await channel.sendText(chatId, "\u26D4 Self-learning disabled. No signals will be collected.", { parseMode: "plain" });
|
|
16320
16576
|
}
|
|
16321
16577
|
break;
|
|
16322
16578
|
}
|
|
@@ -16324,14 +16580,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16324
16580
|
if (idStr) {
|
|
16325
16581
|
const { rollbackInsight: rollbackInsight2 } = await Promise.resolve().then(() => (init_apply(), apply_exports));
|
|
16326
16582
|
const result = await rollbackInsight2(parseInt(idStr, 10));
|
|
16327
|
-
await channel.sendText(chatId, result.message, "plain");
|
|
16583
|
+
await channel.sendText(chatId, result.message, { parseMode: "plain" });
|
|
16328
16584
|
} else {
|
|
16329
16585
|
const { getAppliedInsights: getAppliedInsights2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16330
16586
|
const { buildUndoKeyboard: buildUndoKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16331
16587
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16332
16588
|
const applied = getAppliedInsights2(getDb2(), chatId, 10);
|
|
16333
16589
|
if (applied.length === 0) {
|
|
16334
|
-
await channel.sendText(chatId, "No applied insights to undo.", "plain");
|
|
16590
|
+
await channel.sendText(chatId, "No applied insights to undo.", { parseMode: "plain" });
|
|
16335
16591
|
} else {
|
|
16336
16592
|
const kb = buildUndoKeyboard2(applied);
|
|
16337
16593
|
await channel.sendKeyboard(chatId, "Select an insight to undo:", kb);
|
|
@@ -16344,7 +16600,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16344
16600
|
const { setReflectionModelConfig: setReflectionModelConfig2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16345
16601
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16346
16602
|
setReflectionModelConfig2(getDb2(), chatId, idStr);
|
|
16347
|
-
await channel.sendText(chatId, `Analysis model set to: ${idStr}`, "plain");
|
|
16603
|
+
await channel.sendText(chatId, `Analysis model set to: ${idStr}`, { parseMode: "plain" });
|
|
16348
16604
|
} else {
|
|
16349
16605
|
const { getReflectionModelConfig: getReflectionModelConfig2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16350
16606
|
const { buildModelKeyboard: buildModelKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
@@ -16362,16 +16618,16 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16362
16618
|
if (action === "all") {
|
|
16363
16619
|
const pendingIds = getLoggedChatIds();
|
|
16364
16620
|
if (pendingIds.length === 0) {
|
|
16365
|
-
await channel.sendText(chatId, "No pending sessions to summarize.", "plain");
|
|
16621
|
+
await channel.sendText(chatId, "No pending sessions to summarize.", { parseMode: "plain" });
|
|
16366
16622
|
return;
|
|
16367
16623
|
}
|
|
16368
|
-
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, "plain");
|
|
16624
|
+
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, { parseMode: "plain" });
|
|
16369
16625
|
await summarizeAllPending();
|
|
16370
|
-
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, "plain");
|
|
16626
|
+
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, { parseMode: "plain" });
|
|
16371
16627
|
} else if (action === "undo") {
|
|
16372
16628
|
const pending = pendingSummaryUndo.get(chatId);
|
|
16373
16629
|
if (!pending) {
|
|
16374
|
-
await channel.sendText(chatId, "Undo window expired.", "plain");
|
|
16630
|
+
await channel.sendText(chatId, "Undo window expired.", { parseMode: "plain" });
|
|
16375
16631
|
return;
|
|
16376
16632
|
}
|
|
16377
16633
|
clearTimeout(pending.timer);
|
|
@@ -16389,20 +16645,20 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16389
16645
|
if (action === "go") {
|
|
16390
16646
|
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
16391
16647
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16392
|
-
await channel.sendText(chatId, "Analyzing recent interactions...", "plain");
|
|
16648
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
16393
16649
|
try {
|
|
16394
|
-
const insights = await runAnalysis2(chatId);
|
|
16650
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
16395
16651
|
if (insights.length === 0) {
|
|
16396
|
-
await channel.sendText(chatId, "No new insights from recent interactions.", "plain");
|
|
16652
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
16397
16653
|
} else {
|
|
16398
16654
|
const items = insights.map((ins, i) => ({ id: i + 1, category: ins.category, insight: ins.insight }));
|
|
16399
|
-
await channel.sendText(chatId, formatNightlySummary2(items) + "\n\nUse /evolve to review and apply proposals.", "plain");
|
|
16655
|
+
await channel.sendText(chatId, formatNightlySummary2(items) + "\n\nUse /evolve to review and apply proposals.", { parseMode: "plain" });
|
|
16400
16656
|
}
|
|
16401
16657
|
} catch (e) {
|
|
16402
|
-
await channel.sendText(chatId, `Analysis failed: ${e}`, "plain");
|
|
16658
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
16403
16659
|
}
|
|
16404
16660
|
} else if (action === "cancel") {
|
|
16405
|
-
await channel.sendText(chatId, "Reflection cancelled.", "plain");
|
|
16661
|
+
await channel.sendText(chatId, "Reflection cancelled.", { parseMode: "plain" });
|
|
16406
16662
|
}
|
|
16407
16663
|
return;
|
|
16408
16664
|
} else if (data.startsWith("chats:")) {
|
|
@@ -16432,7 +16688,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16432
16688
|
} else if (action === "remove") {
|
|
16433
16689
|
const aliases = getAllChatAliases();
|
|
16434
16690
|
if (aliases.length === 0) {
|
|
16435
|
-
await channel.sendText(chatId, "No aliases to remove.", "plain");
|
|
16691
|
+
await channel.sendText(chatId, "No aliases to remove.", { parseMode: "plain" });
|
|
16436
16692
|
return;
|
|
16437
16693
|
}
|
|
16438
16694
|
const aliasButtons = aliases.map((a, i) => [{ label: a.alias, data: `chats:remove:${i}` }]);
|
|
@@ -16442,12 +16698,12 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16442
16698
|
const idx = parseInt(action.slice(7), 10);
|
|
16443
16699
|
const aliases = getAllChatAliases();
|
|
16444
16700
|
if (isNaN(idx) || idx < 0 || idx >= aliases.length) {
|
|
16445
|
-
await channel.sendText(chatId, "This data is outdated. Use /chats to refresh.", "plain");
|
|
16701
|
+
await channel.sendText(chatId, "This data is outdated. Use /chats to refresh.", { parseMode: "plain" });
|
|
16446
16702
|
return;
|
|
16447
16703
|
}
|
|
16448
16704
|
const alias = aliases[idx].alias;
|
|
16449
16705
|
const removed = removeChatAlias(alias);
|
|
16450
|
-
await channel.sendText(chatId, removed ? `Alias "${alias}" removed.` : `Alias "${alias}" not found.`, "plain");
|
|
16706
|
+
await channel.sendText(chatId, removed ? `Alias "${alias}" removed.` : `Alias "${alias}" not found.`, { parseMode: "plain" });
|
|
16451
16707
|
}
|
|
16452
16708
|
return;
|
|
16453
16709
|
} else if (data.startsWith("hist:")) {
|
|
@@ -16478,7 +16734,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16478
16734
|
[{ label: "Refresh List", data: "forget:page:1" }]
|
|
16479
16735
|
]);
|
|
16480
16736
|
} else {
|
|
16481
|
-
await channel.sendText(chatId, "This memory no longer exists.", "plain");
|
|
16737
|
+
await channel.sendText(chatId, "This memory no longer exists.", { parseMode: "plain" });
|
|
16482
16738
|
}
|
|
16483
16739
|
return;
|
|
16484
16740
|
}
|
|
@@ -16499,10 +16755,10 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16499
16755
|
await channel.sendText(
|
|
16500
16756
|
chatId,
|
|
16501
16757
|
deleted ? "Memory deleted." : "Memory not found \u2014 already deleted.",
|
|
16502
|
-
"plain"
|
|
16758
|
+
{ parseMode: "plain" }
|
|
16503
16759
|
);
|
|
16504
16760
|
} else if (rest === "cancel") {
|
|
16505
|
-
await channel.sendText(chatId, "Cancelled.", "plain");
|
|
16761
|
+
await channel.sendText(chatId, "Cancelled.", { parseMode: "plain" });
|
|
16506
16762
|
}
|
|
16507
16763
|
return;
|
|
16508
16764
|
} else if (data.startsWith("mem:")) {
|
|
@@ -16519,7 +16775,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16519
16775
|
[{ label: "Refresh List", data: "mem:page:1" }]
|
|
16520
16776
|
]);
|
|
16521
16777
|
} else {
|
|
16522
|
-
await channel.sendText(chatId, "This memory no longer exists.", "plain");
|
|
16778
|
+
await channel.sendText(chatId, "This memory no longer exists.", { parseMode: "plain" });
|
|
16523
16779
|
}
|
|
16524
16780
|
return;
|
|
16525
16781
|
}
|
|
@@ -16544,13 +16800,13 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16544
16800
|
await channel.sendText(
|
|
16545
16801
|
chatId,
|
|
16546
16802
|
deleted ? "Memory deleted." : "Memory not found \u2014 already deleted.",
|
|
16547
|
-
"plain"
|
|
16803
|
+
{ parseMode: "plain" }
|
|
16548
16804
|
);
|
|
16549
16805
|
} else if (rest.startsWith("forget:")) {
|
|
16550
16806
|
const id = parseInt(rest.slice(7), 10);
|
|
16551
16807
|
const memory2 = getMemoryById(id);
|
|
16552
16808
|
if (!memory2) {
|
|
16553
|
-
await channel.sendText(chatId, "Memory not found.", "plain");
|
|
16809
|
+
await channel.sendText(chatId, "Memory not found.", { parseMode: "plain" });
|
|
16554
16810
|
return;
|
|
16555
16811
|
}
|
|
16556
16812
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16568,7 +16824,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16568
16824
|
}
|
|
16569
16825
|
} else if (rest.startsWith("edit:")) {
|
|
16570
16826
|
const id = parseInt(rest.slice(5), 10);
|
|
16571
|
-
await channel.sendText(chatId, `Type: /memory edit ${id} <new content>`, "plain");
|
|
16827
|
+
await channel.sendText(chatId, `Type: /memory edit ${id} <new content>`, { parseMode: "plain" });
|
|
16572
16828
|
} else if (rest === "back") {
|
|
16573
16829
|
await sendMemoryPage(chatId, channel, 1);
|
|
16574
16830
|
} else if (rest === "showall") {
|
|
@@ -16606,7 +16862,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16606
16862
|
if (rest === "undo") {
|
|
16607
16863
|
const pending = pendingNewchatUndo.get(chatId);
|
|
16608
16864
|
if (!pending) {
|
|
16609
|
-
await channel.sendText(chatId, "Undo window expired.", "plain");
|
|
16865
|
+
await channel.sendText(chatId, "Undo window expired.", { parseMode: "plain" });
|
|
16610
16866
|
return;
|
|
16611
16867
|
}
|
|
16612
16868
|
clearTimeout(pending.timer);
|
|
@@ -16637,13 +16893,13 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16637
16893
|
clearBackendLimit(bid, win);
|
|
16638
16894
|
}
|
|
16639
16895
|
}
|
|
16640
|
-
await channel.sendText(chatId, "All usage limits cleared.", "plain");
|
|
16896
|
+
await channel.sendText(chatId, "All usage limits cleared.", { parseMode: "plain" });
|
|
16641
16897
|
await sendUnifiedUsage(chatId, channel, "session");
|
|
16642
16898
|
} else if (rest.startsWith("limits:set:")) {
|
|
16643
16899
|
const bid = rest.slice(11);
|
|
16644
16900
|
await channel.sendText(chatId, `Set limit for ${bid}:
|
|
16645
16901
|
/limits ${bid} daily <tokens>
|
|
16646
|
-
Example: /limits ${bid} daily 500000`, "plain");
|
|
16902
|
+
Example: /limits ${bid} daily 500000`, { parseMode: "plain" });
|
|
16647
16903
|
}
|
|
16648
16904
|
return;
|
|
16649
16905
|
} else if (data.startsWith("job:")) {
|
|
@@ -16655,14 +16911,14 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16655
16911
|
await sendJobDetail(chatId, id, channel);
|
|
16656
16912
|
} else if (rest.startsWith("run:")) {
|
|
16657
16913
|
const id = parseInt(rest.slice(4), 10);
|
|
16658
|
-
await channel.sendText(chatId, `Triggering job #${id}...`, "plain");
|
|
16914
|
+
await channel.sendText(chatId, `Triggering job #${id}...`, { parseMode: "plain" });
|
|
16659
16915
|
const result = await triggerJob(id);
|
|
16660
16916
|
if (typeof channel.sendKeyboard === "function") {
|
|
16661
16917
|
await channel.sendKeyboard(chatId, result, [
|
|
16662
16918
|
[{ label: "\u2190 Back to Job", data: `job:view:${id}` }]
|
|
16663
16919
|
]);
|
|
16664
16920
|
} else {
|
|
16665
|
-
await channel.sendText(chatId, result, "plain");
|
|
16921
|
+
await channel.sendText(chatId, result, { parseMode: "plain" });
|
|
16666
16922
|
}
|
|
16667
16923
|
} else if (rest.startsWith("pause:")) {
|
|
16668
16924
|
const id = parseInt(rest.slice(6), 10);
|
|
@@ -16670,7 +16926,7 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16670
16926
|
if (paused) {
|
|
16671
16927
|
await sendJobDetail(chatId, id, channel);
|
|
16672
16928
|
} else {
|
|
16673
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
16929
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16674
16930
|
}
|
|
16675
16931
|
} else if (rest.startsWith("resume:")) {
|
|
16676
16932
|
const id = parseInt(rest.slice(7), 10);
|
|
@@ -16678,22 +16934,22 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16678
16934
|
if (resumed) {
|
|
16679
16935
|
await sendJobDetail(chatId, id, channel);
|
|
16680
16936
|
} else {
|
|
16681
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
16937
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16682
16938
|
}
|
|
16683
16939
|
} else if (rest.startsWith("cancel:confirm:")) {
|
|
16684
16940
|
const id = parseInt(rest.slice(15), 10);
|
|
16685
16941
|
const cancelled = cancelJob(id);
|
|
16686
16942
|
if (cancelled) {
|
|
16687
|
-
await channel.sendText(chatId, `Job #${id} cancelled.`, "plain");
|
|
16943
|
+
await channel.sendText(chatId, `Job #${id} cancelled.`, { parseMode: "plain" });
|
|
16688
16944
|
await sendJobsBoard(chatId, channel, 1);
|
|
16689
16945
|
} else {
|
|
16690
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
16946
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16691
16947
|
}
|
|
16692
16948
|
} else if (rest.startsWith("cancel:")) {
|
|
16693
16949
|
const id = parseInt(rest.slice(7), 10);
|
|
16694
16950
|
const job = getJobById(id);
|
|
16695
16951
|
if (!job) {
|
|
16696
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
16952
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16697
16953
|
return;
|
|
16698
16954
|
}
|
|
16699
16955
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16747,7 +17003,7 @@ Command: ${command}`,
|
|
|
16747
17003
|
);
|
|
16748
17004
|
} else {
|
|
16749
17005
|
await channel.sendText(chatId, `\u26A0\uFE0F Destructive command blocked: ${command}
|
|
16750
|
-
No keyboard available to confirm.`, "plain");
|
|
17006
|
+
No keyboard available to confirm.`, { parseMode: "plain" });
|
|
16751
17007
|
}
|
|
16752
17008
|
return;
|
|
16753
17009
|
}
|
|
@@ -16764,9 +17020,9 @@ No keyboard available to confirm.`, "plain");
|
|
|
16764
17020
|
if (shouldSendAsFile(formatted)) {
|
|
16765
17021
|
const buffer = Buffer.from(result.output, "utf-8");
|
|
16766
17022
|
await channel.sendFile(chatId, buffer, "output.txt", "text/plain");
|
|
16767
|
-
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, "plain");
|
|
17023
|
+
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, { parseMode: "plain" });
|
|
16768
17024
|
} else {
|
|
16769
|
-
await channel.sendText(chatId, formatted, "html");
|
|
17025
|
+
await channel.sendText(chatId, formatted, { parseMode: "html" });
|
|
16770
17026
|
}
|
|
16771
17027
|
}
|
|
16772
17028
|
async function handleRawShell(command, chatId, channel, skipGuard = false) {
|
|
@@ -16785,7 +17041,7 @@ Command: ${command}`,
|
|
|
16785
17041
|
);
|
|
16786
17042
|
} else {
|
|
16787
17043
|
await channel.sendText(chatId, `\u26A0\uFE0F Destructive command blocked: ${command}
|
|
16788
|
-
No keyboard available to confirm.`, "plain");
|
|
17044
|
+
No keyboard available to confirm.`, { parseMode: "plain" });
|
|
16789
17045
|
}
|
|
16790
17046
|
return;
|
|
16791
17047
|
}
|
|
@@ -16802,9 +17058,9 @@ No keyboard available to confirm.`, "plain");
|
|
|
16802
17058
|
if (shouldSendAsFile(formatted)) {
|
|
16803
17059
|
const buffer = Buffer.from(result.output, "utf-8");
|
|
16804
17060
|
await channel.sendFile(chatId, buffer, "output.txt", "text/plain");
|
|
16805
|
-
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, "plain");
|
|
17061
|
+
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, { parseMode: "plain" });
|
|
16806
17062
|
} else {
|
|
16807
|
-
await channel.sendText(chatId, formatted, "plain");
|
|
17063
|
+
await channel.sendText(chatId, formatted, { parseMode: "plain" });
|
|
16808
17064
|
}
|
|
16809
17065
|
}
|
|
16810
17066
|
async function sendCwdSessionChoice(chatId, path, channel) {
|
|
@@ -16823,7 +17079,7 @@ What would you like to do?`,
|
|
|
16823
17079
|
);
|
|
16824
17080
|
} else {
|
|
16825
17081
|
await channel.sendText(chatId, `Working directory set to: ${path}
|
|
16826
|
-
Session kept.`, "plain");
|
|
17082
|
+
Session kept.`, { parseMode: "plain" });
|
|
16827
17083
|
}
|
|
16828
17084
|
}
|
|
16829
17085
|
function parseIntervalToMs(input) {
|
|
@@ -16884,7 +17140,7 @@ async function sendSkillsPage(chatId, channel, skills2, page) {
|
|
|
16884
17140
|
const header3 = totalPages > 1 ? `Skills (page ${safePage}/${totalPages}, ${skills2.length} total):` : "Available skills:";
|
|
16885
17141
|
const footer = totalPages > 1 ? `
|
|
16886
17142
|
Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
16887
|
-
await channel.sendText(chatId, [header3, "", ...lines, footer].join("\n"), "plain");
|
|
17143
|
+
await channel.sendText(chatId, [header3, "", ...lines, footer].join("\n"), { parseMode: "plain" });
|
|
16888
17144
|
return;
|
|
16889
17145
|
}
|
|
16890
17146
|
const buttons = pageSkills.map((s) => {
|
|
@@ -16901,7 +17157,7 @@ Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
|
16901
17157
|
const header2 = totalPages > 1 ? `${skills2.length} skills (page ${safePage}/${totalPages}). Select one to invoke:` : `${skills2.length} skills available. Select one to invoke:`;
|
|
16902
17158
|
await channel.sendKeyboard(chatId, header2, buttons);
|
|
16903
17159
|
}
|
|
16904
|
-
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
|
|
17160
|
+
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
|
|
16905
17161
|
var init_router = __esm({
|
|
16906
17162
|
"src/router.ts"() {
|
|
16907
17163
|
"use strict";
|
|
@@ -17040,6 +17296,8 @@ var init_router = __esm({
|
|
|
17040
17296
|
];
|
|
17041
17297
|
pendingInterrupts = /* @__PURE__ */ new Map();
|
|
17042
17298
|
bypassBusyCheck = /* @__PURE__ */ new Set();
|
|
17299
|
+
activeSideQuests = /* @__PURE__ */ new Map();
|
|
17300
|
+
MAX_SIDE_QUESTS = 2;
|
|
17043
17301
|
pendingFallbackMessages = /* @__PURE__ */ new Map();
|
|
17044
17302
|
dashboardClawWarnings = /* @__PURE__ */ new Map();
|
|
17045
17303
|
pendingSummaryUndo = /* @__PURE__ */ new Map();
|
|
@@ -17502,9 +17760,64 @@ Use the CC-Claw CLI when you need to:
|
|
|
17502
17760
|
|
|
17503
17761
|
## Telegram Quick Reference
|
|
17504
17762
|
|
|
17505
|
-
|
|
17506
|
-
- \`/
|
|
17507
|
-
-
|
|
17763
|
+
**Navigation & help:**
|
|
17764
|
+
- \`/menu\` (\`/m\`) \u2014 Home screen keyboard
|
|
17765
|
+
- \`/help\` (\`/start\`) \u2014 Help categories keyboard
|
|
17766
|
+
- \`/usage\` \u2014 Unified cost, limits, usage (\`/cost\` and \`/limits\` are aliases)
|
|
17767
|
+
- \`@botname <query>\` \u2014 Inline mode: memory/history search from any chat
|
|
17768
|
+
|
|
17769
|
+
**Session & history:**
|
|
17770
|
+
- \`/newchat\` (\`/new\`) \u2014 Start fresh conversation (with undo)
|
|
17771
|
+
- \`/summarize\` \u2014 Save session to memory (\`/summarize all\` for all pending)
|
|
17772
|
+
- \`/history\` \u2014 Recent messages (\`/history <query>\` for FTS search)
|
|
17773
|
+
- \`/stop\` \u2014 Cancel running task + any active side quests
|
|
17774
|
+
|
|
17775
|
+
**Side quests (parallel execution):**
|
|
17776
|
+
- \`sq: <message>\` or \`btw: <message>\` \u2014 Run in parallel while agent is busy (full tool access, shared context, max 2 concurrent, 5-min timeout)
|
|
17777
|
+
- Also available as "Side quest" button on the interrupt keyboard
|
|
17778
|
+
|
|
17779
|
+
**Backend & model:**
|
|
17780
|
+
- \`/backend\` \u2014 Backend picker keyboard
|
|
17781
|
+
- \`/claude\`, \`/gemini\`, \`/codex\`, \`/cursor\` \u2014 Switch directly
|
|
17782
|
+
- \`/model\` \u2014 Model picker keyboard
|
|
17783
|
+
- \`/thinking\` (\`/think\`) \u2014 Thinking level picker
|
|
17784
|
+
|
|
17785
|
+
**Settings keyboards:**
|
|
17786
|
+
- \`/permissions\` \u2014 Permission mode (yolo/safe/readonly/plan)
|
|
17787
|
+
- \`/tools\` \u2014 Enable/disable tools (safe mode)
|
|
17788
|
+
- \`/response_style\` \u2014 Concise / normal / detailed
|
|
17789
|
+
- \`/model_signature\` \u2014 Show/hide model name on responses
|
|
17790
|
+
- \`/agents mode\` \u2014 Agent mode (auto/native/claw)
|
|
17791
|
+
- \`/voice_config\` \u2014 Voice provider settings
|
|
17792
|
+
|
|
17793
|
+
**Memory:**
|
|
17794
|
+
- \`/remember <text>\` \u2014 Save a memory
|
|
17795
|
+
- \`/forget <keyword>\` \u2014 Delete memories
|
|
17796
|
+
- \`/memories\` \u2014 List memories
|
|
17797
|
+
|
|
17798
|
+
**Scheduling (interactive wizards):**
|
|
17799
|
+
- \`/schedule <description>\` \u2014 Create job via wizard
|
|
17800
|
+
- \`/jobs\` \u2014 Paginated job board
|
|
17801
|
+
- \`/editjob\` \u2014 Edit job wizard
|
|
17802
|
+
- \`/cancel\`, \`/pause\`, \`/resume\`, \`/run\`, \`/runs\` \u2014 Job action shortcuts
|
|
17803
|
+
- \`/health\` \u2014 Scheduler health
|
|
17804
|
+
|
|
17805
|
+
**Agents:**
|
|
17806
|
+
- \`/agents\` \u2014 Agent dashboard
|
|
17807
|
+
- \`/agents history\` \u2014 Recent sub-agent activity
|
|
17808
|
+
- \`/tasks\` \u2014 Task board
|
|
17809
|
+
- \`/stopagent\` \u2014 Interactive agent picker to stop
|
|
17810
|
+
- \`/stopall\` \u2014 Cancel all agents
|
|
17811
|
+
- \`/runners\` \u2014 List CLI runners
|
|
17812
|
+
|
|
17813
|
+
**Other:**
|
|
17814
|
+
- \`/imagine <prompt>\` (\`/image\`) \u2014 Generate image (requires GEMINI_API_KEY)
|
|
17815
|
+
- \`/skills\` \u2014 List skills
|
|
17816
|
+
- \`/skill-install <url>\` \u2014 Install skill from GitHub
|
|
17817
|
+
- \`/evolve\` \u2014 Self-learning interactive keyboard
|
|
17818
|
+
- \`/reflect\` \u2014 Trigger reflection analysis
|
|
17819
|
+
- \`/gemini_accounts\` \u2014 Gemini credential rotation management
|
|
17820
|
+
- \`/setup-profile\` \u2014 User profile setup wizard
|
|
17508
17821
|
|
|
17509
17822
|
## Command Reference
|
|
17510
17823
|
|
|
@@ -17516,6 +17829,7 @@ cc-claw doctor --json # Health checks (DB, CLIs, env, disk)
|
|
|
17516
17829
|
cc-claw doctor --fix --json # Auto-repair common issues
|
|
17517
17830
|
cc-claw logs -f # Follow daemon logs
|
|
17518
17831
|
cc-claw logs --error # Show error log
|
|
17832
|
+
cc-claw logs --lines 50 # Show last N lines
|
|
17519
17833
|
\`\`\`
|
|
17520
17834
|
|
|
17521
17835
|
### Backend & Model
|
|
@@ -17532,8 +17846,10 @@ cc-claw model set claude-opus-4-6 # Switch model
|
|
|
17532
17846
|
\`\`\`bash
|
|
17533
17847
|
cc-claw chat send "What is 2+2?" --json # Send message, get response
|
|
17534
17848
|
cc-claw chat send "analyze this" --stream # Stream response tokens
|
|
17535
|
-
cc-claw chat
|
|
17536
|
-
cc-claw
|
|
17849
|
+
cc-claw chat send "msg" --backend gemini --model gemini-3-flash-preview # Override backend/model
|
|
17850
|
+
cc-claw chat send "msg" --thinking high --cwd /path # Override thinking/cwd
|
|
17851
|
+
cc-claw chat stop # Cancel running task + side quests
|
|
17852
|
+
cc-claw tui --model claude-opus-4-6 # Interactive chat with model override
|
|
17537
17853
|
\`\`\`
|
|
17538
17854
|
|
|
17539
17855
|
### Memory
|
|
@@ -17541,6 +17857,7 @@ cc-claw tui # Interactive terminal chat
|
|
|
17541
17857
|
cc-claw memory list --json # All memories with salience
|
|
17542
17858
|
cc-claw memory search "topic" --json # Search memories
|
|
17543
17859
|
cc-claw memory history --json # Session summaries
|
|
17860
|
+
cc-claw memory history --limit 20 --json # Limit results
|
|
17544
17861
|
cc-claw memory add "key" "value" # Save a memory (needs daemon)
|
|
17545
17862
|
cc-claw memory forget "keyword" # Delete memories (needs daemon)
|
|
17546
17863
|
\`\`\`
|
|
@@ -17555,7 +17872,8 @@ cc-claw session new # Clear session (newchat + summarize)
|
|
|
17555
17872
|
\`\`\`bash
|
|
17556
17873
|
cc-claw cron list --json # All scheduled jobs
|
|
17557
17874
|
cc-claw cron health --json # Scheduler health
|
|
17558
|
-
cc-claw cron runs --json # Run history
|
|
17875
|
+
cc-claw cron runs --json # Run history (all jobs)
|
|
17876
|
+
cc-claw cron runs 3 --limit 10 --json # Run history for job #3
|
|
17559
17877
|
cc-claw cron create --description "Morning briefing" --cron "0 9 * * *" --backend claude
|
|
17560
17878
|
cc-claw cron edit 3 --model gemini-3-flash-preview # Change job model
|
|
17561
17879
|
cc-claw cron edit 3 --backend gemini --model gemini-3-flash-preview # Change backend + model
|
|
@@ -17572,6 +17890,7 @@ cc-claw cron run 3 # Trigger immediately
|
|
|
17572
17890
|
\`\`\`bash
|
|
17573
17891
|
cc-claw agents list --json # Active sub-agents
|
|
17574
17892
|
cc-claw agents spawn --runner claude --task "review code" --json
|
|
17893
|
+
cc-claw agents spawn --runner gemini --task "analyze" --model gemini-3-flash-preview --role worker
|
|
17575
17894
|
cc-claw agents cancel <id> # Cancel agent
|
|
17576
17895
|
cc-claw agents cancel-all # Cancel all
|
|
17577
17896
|
cc-claw tasks list --json # Task board
|
|
@@ -17584,6 +17903,8 @@ cc-claw config list --json # All runtime config
|
|
|
17584
17903
|
cc-claw config get backend --json # Specific config value
|
|
17585
17904
|
cc-claw config set backend gemini # Set config (needs daemon)
|
|
17586
17905
|
cc-claw config env --json # Static .env values (redacted)
|
|
17906
|
+
cc-claw config response-style # Get current response style
|
|
17907
|
+
cc-claw config response-style detailed # Set response style (concise/normal/detailed)
|
|
17587
17908
|
\`\`\`
|
|
17588
17909
|
|
|
17589
17910
|
### Usage & Cost
|
|
@@ -17656,6 +17977,37 @@ cc-claw summarizer set off # Disable summarization
|
|
|
17656
17977
|
cc-claw summarizer set claude:claude-haiku-4-5 # Pin specific backend:model
|
|
17657
17978
|
\`\`\`
|
|
17658
17979
|
|
|
17980
|
+
### Gemini Credentials
|
|
17981
|
+
\`\`\`bash
|
|
17982
|
+
cc-claw gemini list --json # Show all credential slots (API keys + OAuth accounts)
|
|
17983
|
+
cc-claw gemini add-key --label "work" # Add an API key slot
|
|
17984
|
+
cc-claw gemini add-account --label "personal" # Add OAuth account (browser sign-in)
|
|
17985
|
+
cc-claw gemini remove <id-or-label> # Remove a credential slot
|
|
17986
|
+
cc-claw gemini enable <id-or-label> # Enable a disabled slot
|
|
17987
|
+
cc-claw gemini disable <id-or-label> # Disable a slot (skip in rotation)
|
|
17988
|
+
cc-claw gemini reorder <id-or-label> <priority> # Change rotation priority
|
|
17989
|
+
cc-claw gemini rotation # Get current rotation mode
|
|
17990
|
+
cc-claw gemini rotation all # Set mode (off/all/accounts/keys)
|
|
17991
|
+
\`\`\`
|
|
17992
|
+
|
|
17993
|
+
### Self-Learning (evolve)
|
|
17994
|
+
\`\`\`bash
|
|
17995
|
+
cc-claw evolve --json # Status overview
|
|
17996
|
+
cc-claw evolve analyze # Trigger reflection analysis
|
|
17997
|
+
cc-claw evolve list --json # Pending proposals
|
|
17998
|
+
cc-claw evolve get <id> --json # Show proposal with diff
|
|
17999
|
+
cc-claw evolve apply <id> # Apply a proposal
|
|
18000
|
+
cc-claw evolve reject <id> # Reject a proposal
|
|
18001
|
+
cc-claw evolve undo <id> # Rollback applied insight
|
|
18002
|
+
cc-claw evolve on # Enable self-learning
|
|
18003
|
+
cc-claw evolve off # Disable self-learning
|
|
18004
|
+
cc-claw evolve model auto # Set analysis model (auto/pinned/cheap)
|
|
18005
|
+
cc-claw evolve model pinned --backend claude --model claude-haiku-4-5
|
|
18006
|
+
cc-claw evolve stats --days 30 --json # Growth report
|
|
18007
|
+
cc-claw evolve history --json # Applied/rejected insight history
|
|
18008
|
+
cc-claw evolve history --status applied --limit 10 # Filter history
|
|
18009
|
+
\`\`\`
|
|
18010
|
+
|
|
17659
18011
|
### Chat Aliases
|
|
17660
18012
|
\`\`\`bash
|
|
17661
18013
|
cc-claw chats list --json # Authorized chats and aliases
|
|
@@ -17678,8 +18030,7 @@ cc-claw mcps list --json # Registered MCP servers
|
|
|
17678
18030
|
\`\`\`bash
|
|
17679
18031
|
cc-claw db stats --json # Row counts, file size, WAL status
|
|
17680
18032
|
cc-claw db path # Print DB file location
|
|
17681
|
-
cc-claw db backup
|
|
17682
|
-
cc-claw db prune # Prune old data
|
|
18033
|
+
cc-claw db backup [path] # Create backup (optional destination)
|
|
17683
18034
|
\`\`\`
|
|
17684
18035
|
|
|
17685
18036
|
### Service Management
|
|
@@ -17697,6 +18048,7 @@ cc-claw service uninstall # Remove service
|
|
|
17697
18048
|
cc-claw setup # Interactive configuration wizard
|
|
17698
18049
|
cc-claw tui # Interactive terminal chat
|
|
17699
18050
|
cc-claw completion --shell zsh # Generate shell completions (bash/zsh/fish)
|
|
18051
|
+
cc-claw completion --shell zsh --install # Show install instructions
|
|
17700
18052
|
cc-claw --ai # Generate/install SKILL.md for AI tools
|
|
17701
18053
|
\`\`\`
|
|
17702
18054
|
|
|
@@ -17873,7 +18225,7 @@ async function main() {
|
|
|
17873
18225
|
pendingSummarizeNotify = () => {
|
|
17874
18226
|
if (primaryChatId) {
|
|
17875
18227
|
for (const ch of channelRegistry.list()) {
|
|
17876
|
-
ch.sendText(primaryChatId, "\u{1F504} Restarted \u2014 your conversations were summarized and saved.", "plain").catch(() => {
|
|
18228
|
+
ch.sendText(primaryChatId, "\u{1F504} Restarted \u2014 your conversations were summarized and saved.", { parseMode: "plain" }).catch(() => {
|
|
17877
18229
|
});
|
|
17878
18230
|
}
|
|
17879
18231
|
}
|
|
@@ -17900,7 +18252,7 @@ async function main() {
|
|
|
17900
18252
|
setNotifyCallback((chatId, message) => {
|
|
17901
18253
|
notifyQueue = notifyQueue.then(async () => {
|
|
17902
18254
|
for (const ch of channelRegistry.list()) {
|
|
17903
|
-
await ch.sendText(chatId, `\u{1F916} ${message}`, "plain").catch(() => {
|
|
18255
|
+
await ch.sendText(chatId, `\u{1F916} ${message}`, { parseMode: "plain" }).catch(() => {
|
|
17904
18256
|
});
|
|
17905
18257
|
}
|
|
17906
18258
|
await new Promise((r) => setTimeout(r, 300));
|