cc-claw 0.10.1 → 0.11.1
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 +909 -432
- 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.1" : (() => {
|
|
76
76
|
try {
|
|
77
77
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
78
78
|
} catch {
|
|
@@ -703,6 +703,7 @@ __export(store_exports4, {
|
|
|
703
703
|
setReflectionModelConfig: () => setReflectionModelConfig,
|
|
704
704
|
setReflectionStatus: () => setReflectionStatus,
|
|
705
705
|
updateInsightEffectiveness: () => updateInsightEffectiveness,
|
|
706
|
+
updateInsightProposal: () => updateInsightProposal,
|
|
706
707
|
updateInsightRollback: () => updateInsightRollback,
|
|
707
708
|
updateInsightStatus: () => updateInsightStatus,
|
|
708
709
|
upsertGrowthMetric: () => upsertGrowthMetric
|
|
@@ -932,6 +933,11 @@ function updateInsightStatus(db3, id, status) {
|
|
|
932
933
|
db3.prepare("UPDATE insights SET status = ? WHERE id = ?").run(status, id);
|
|
933
934
|
}
|
|
934
935
|
}
|
|
936
|
+
function updateInsightProposal(db3, id, targetFile, proposedDiff, proposedAction) {
|
|
937
|
+
db3.prepare(`
|
|
938
|
+
UPDATE insights SET targetFile = ?, proposedDiff = ?, proposedAction = ? WHERE id = ?
|
|
939
|
+
`).run(targetFile, proposedDiff ?? null, proposedAction ?? null, id);
|
|
940
|
+
}
|
|
935
941
|
function updateInsightRollback(db3, id, rollbackData) {
|
|
936
942
|
db3.prepare("UPDATE insights SET rollbackData = ? WHERE id = ?").run(rollbackData, id);
|
|
937
943
|
}
|
|
@@ -4556,7 +4562,7 @@ function searchContext(userMessage) {
|
|
|
4556
4562
|
}
|
|
4557
4563
|
return null;
|
|
4558
4564
|
}
|
|
4559
|
-
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode) {
|
|
4565
|
+
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext) {
|
|
4560
4566
|
const sections = [];
|
|
4561
4567
|
if (Date.now() - lastSyncMs >= 5e3) {
|
|
4562
4568
|
syncNativeCliFiles();
|
|
@@ -4580,9 +4586,12 @@ ${ctx}`);
|
|
|
4580
4586
|
}
|
|
4581
4587
|
}
|
|
4582
4588
|
if (chatId && tier !== "slim" && tier !== "chat") {
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
sections.push(bridge);
|
|
4589
|
+
if (sideQuestContext) {
|
|
4590
|
+
const bridge = buildContextBridge(sideQuestContext.parentChatId, 15);
|
|
4591
|
+
if (bridge) sections.push(bridge);
|
|
4592
|
+
} else {
|
|
4593
|
+
const bridge = consumeContextBridge(chatId);
|
|
4594
|
+
if (bridge) sections.push(bridge);
|
|
4586
4595
|
}
|
|
4587
4596
|
}
|
|
4588
4597
|
if (tier !== "slim") {
|
|
@@ -4620,6 +4629,23 @@ ${ctx}`);
|
|
|
4620
4629
|
"[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
4630
|
);
|
|
4622
4631
|
}
|
|
4632
|
+
if (sideQuestContext) {
|
|
4633
|
+
const { getInFlightMessage: getInFlightMessage3 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
4634
|
+
const inFlightMsg = getInFlightMessage3(sideQuestContext.parentChatId);
|
|
4635
|
+
const preamble = [
|
|
4636
|
+
`[Side quest context]`,
|
|
4637
|
+
`You are handling a side request while the user's main agent works on another task.`
|
|
4638
|
+
];
|
|
4639
|
+
if (inFlightMsg) {
|
|
4640
|
+
preamble.push(`The main agent is currently working on: "${inFlightMsg}"`);
|
|
4641
|
+
}
|
|
4642
|
+
preamble.push(
|
|
4643
|
+
`The user's recent conversation history is included above for context.`,
|
|
4644
|
+
`Focus specifically on what the user is asking in THIS message.`,
|
|
4645
|
+
`[End side quest context]`
|
|
4646
|
+
);
|
|
4647
|
+
sections.push(preamble.join("\n"));
|
|
4648
|
+
}
|
|
4623
4649
|
sections.push(userMessage);
|
|
4624
4650
|
const result = sections.join("\n\n");
|
|
4625
4651
|
log(`[bootstrap] Assembled prompt: tier=${tier}, sections=${sections.length}, totalChars=${result.length}`);
|
|
@@ -6772,19 +6798,26 @@ async function spawnAnalysis(adapter, model2, prompt) {
|
|
|
6772
6798
|
if (!resultText) resultText = accumulatedText;
|
|
6773
6799
|
return resultText;
|
|
6774
6800
|
}
|
|
6775
|
-
async function runAnalysis(chatId) {
|
|
6801
|
+
async function runAnalysis(chatId, opts = {}) {
|
|
6776
6802
|
const db3 = getDb();
|
|
6777
|
-
const
|
|
6778
|
-
if (
|
|
6779
|
-
|
|
6780
|
-
|
|
6803
|
+
const { force = false } = opts;
|
|
6804
|
+
if (!force) {
|
|
6805
|
+
const status = getReflectionStatus(db3, chatId);
|
|
6806
|
+
if (status === "frozen") {
|
|
6807
|
+
log(`[reflection] Skipping analysis for ${chatId} \u2014 reflection is frozen`);
|
|
6808
|
+
return [];
|
|
6809
|
+
}
|
|
6781
6810
|
}
|
|
6782
6811
|
const signals = getUnprocessedSignals(db3, chatId);
|
|
6783
|
-
if (signals.length === 0) {
|
|
6812
|
+
if (!force && signals.length === 0) {
|
|
6784
6813
|
log(`[reflection] No unprocessed signals for ${chatId}`);
|
|
6785
6814
|
return [];
|
|
6786
6815
|
}
|
|
6787
6816
|
const conversations = getTodayConversations(chatId);
|
|
6817
|
+
if (signals.length === 0 && !conversations) {
|
|
6818
|
+
log(`[reflection] No signals and no conversations for ${chatId} \u2014 nothing to analyze`);
|
|
6819
|
+
return [];
|
|
6820
|
+
}
|
|
6788
6821
|
const soulMd = readIdentityFile("SOUL.md");
|
|
6789
6822
|
const userMd = readIdentityFile("USER.md");
|
|
6790
6823
|
const applied = getAppliedInsights(db3, chatId);
|
|
@@ -6819,7 +6852,7 @@ async function runAnalysis(chatId) {
|
|
|
6819
6852
|
return [];
|
|
6820
6853
|
}
|
|
6821
6854
|
const { adapter, model: model2 } = resolved;
|
|
6822
|
-
log(`[reflection] Running analysis via ${adapter.id}:${model2} for chat ${chatId} (${signals.length} signals)`);
|
|
6855
|
+
log(`[reflection] Running analysis via ${adapter.id}:${model2} for chat ${chatId} (${signals.length} signals, force=${force})`);
|
|
6823
6856
|
let rawOutput;
|
|
6824
6857
|
try {
|
|
6825
6858
|
rawOutput = await spawnAnalysis(adapter, model2, prompt);
|
|
@@ -6829,13 +6862,12 @@ async function runAnalysis(chatId) {
|
|
|
6829
6862
|
}
|
|
6830
6863
|
if (!rawOutput || rawOutput.includes("NO_INSIGHTS")) {
|
|
6831
6864
|
log(`[reflection] Analysis returned no insights for ${chatId}`);
|
|
6832
|
-
markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6865
|
+
if (signals.length > 0) markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6833
6866
|
return [];
|
|
6834
6867
|
}
|
|
6835
6868
|
const parsed = parseAnalysisOutput(rawOutput);
|
|
6836
|
-
const signalIdStr = signals.map((s) => s.id).join(",");
|
|
6869
|
+
const signalIdStr = signals.length > 0 ? signals.map((s) => s.id).join(",") : "manual";
|
|
6837
6870
|
for (const insight of parsed) {
|
|
6838
|
-
const insightStatus = insight.category === "codebase" ? "recommendation" : "pending";
|
|
6839
6871
|
let conflictsWithId = null;
|
|
6840
6872
|
if (insight.conflictsWith && insight.conflictsWith !== "none") {
|
|
6841
6873
|
const parsed_id = parseInt(insight.conflictsWith, 10);
|
|
@@ -6856,19 +6888,20 @@ async function runAnalysis(chatId) {
|
|
|
6856
6888
|
model: model2
|
|
6857
6889
|
});
|
|
6858
6890
|
}
|
|
6859
|
-
markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6891
|
+
if (signals.length > 0) markSignalsProcessed(db3, signals.map((s) => s.id));
|
|
6860
6892
|
aggregateDailyMetrics(db3, chatId);
|
|
6861
6893
|
logActivity(db3, {
|
|
6862
6894
|
chatId,
|
|
6863
6895
|
source: "agent",
|
|
6864
6896
|
eventType: "reflection_triggered",
|
|
6865
|
-
summary: `Reflection analysis produced ${parsed.length} insight(s) from ${signals.length} signal(s)`,
|
|
6897
|
+
summary: `Reflection analysis produced ${parsed.length} insight(s) from ${signals.length} signal(s)${force ? " (manual)" : ""}`,
|
|
6866
6898
|
detail: {
|
|
6867
6899
|
signalCount: signals.length,
|
|
6868
6900
|
insightCount: parsed.length,
|
|
6869
6901
|
backend: adapter.id,
|
|
6870
6902
|
model: model2,
|
|
6871
|
-
categories: parsed.map((p) => p.category)
|
|
6903
|
+
categories: parsed.map((p) => p.category),
|
|
6904
|
+
forced: force
|
|
6872
6905
|
}
|
|
6873
6906
|
});
|
|
6874
6907
|
log(`[reflection] Analysis complete for ${chatId}: ${parsed.length} insight(s) from ${signals.length} signal(s)`);
|
|
@@ -8446,11 +8479,19 @@ var init_detect = __esm({
|
|
|
8446
8479
|
var agent_exports = {};
|
|
8447
8480
|
__export(agent_exports, {
|
|
8448
8481
|
askAgent: () => askAgent,
|
|
8482
|
+
getInFlightMessage: () => getInFlightMessage,
|
|
8449
8483
|
isChatBusy: () => isChatBusy,
|
|
8484
|
+
isSyntheticChatId: () => isSyntheticChatId,
|
|
8450
8485
|
stopAgent: () => stopAgent
|
|
8451
8486
|
});
|
|
8452
8487
|
import { spawn as spawn5 } from "child_process";
|
|
8453
8488
|
import { createInterface as createInterface4 } from "readline";
|
|
8489
|
+
function isSyntheticChatId(chatId) {
|
|
8490
|
+
return chatId.startsWith("sq:") || chatId.startsWith("cron:");
|
|
8491
|
+
}
|
|
8492
|
+
function getInFlightMessage(chatId) {
|
|
8493
|
+
return activeChats.get(chatId)?.userMessage;
|
|
8494
|
+
}
|
|
8454
8495
|
function killProcessGroup(proc, signal = "SIGTERM") {
|
|
8455
8496
|
try {
|
|
8456
8497
|
if (proc.pid) process.kill(-proc.pid, signal);
|
|
@@ -8650,12 +8691,16 @@ function spawnQuery(adapter, config2, model2, cancelState, thinkingLevel, timeou
|
|
|
8650
8691
|
});
|
|
8651
8692
|
});
|
|
8652
8693
|
}
|
|
8653
|
-
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation) {
|
|
8694
|
+
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation, parentChatId) {
|
|
8654
8695
|
const geminiAdapter = adapter;
|
|
8655
8696
|
const slots = getEligibleGeminiSlots(rotationMode);
|
|
8656
8697
|
if (slots.length === 0) {
|
|
8657
8698
|
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
8658
8699
|
}
|
|
8700
|
+
if (parentChatId) {
|
|
8701
|
+
const { env } = geminiAdapter.getEnvForSlot(parentChatId, void 0, rotationMode);
|
|
8702
|
+
return await spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, { ...opts, envOverride: env });
|
|
8703
|
+
}
|
|
8659
8704
|
const maxAttempts = Math.min(slots.length, 10);
|
|
8660
8705
|
let lastError;
|
|
8661
8706
|
for (let i = 0; i < maxAttempts; i++) {
|
|
@@ -8716,17 +8761,19 @@ function askAgent(chatId, userMessage, opts) {
|
|
|
8716
8761
|
return withChatLock(chatId, () => askAgentImpl(chatId, userMessage, opts));
|
|
8717
8762
|
}
|
|
8718
8763
|
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
|
|
8764
|
+
const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId } = opts ?? {};
|
|
8765
|
+
const settingsChat = settingsSourceChatId ?? chatId;
|
|
8766
|
+
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
8767
|
+
const mode = permMode ?? getMode(settingsChat);
|
|
8768
|
+
const responseStyle = getResponseStyle(settingsChat);
|
|
8769
|
+
const thinkingLevel = getThinkingLevel(settingsChat);
|
|
8724
8770
|
const resolvedCwd = cwd ?? WORKSPACE_PATH;
|
|
8725
8771
|
const tier = bootstrapTier ?? "full";
|
|
8726
|
-
const effectiveAgentMode = optsAgentMode ?? getAgentMode(
|
|
8727
|
-
const
|
|
8728
|
-
const
|
|
8729
|
-
const
|
|
8772
|
+
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
8773
|
+
const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
|
|
8774
|
+
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx);
|
|
8775
|
+
const existingSessionId = getSessionId(settingsChat);
|
|
8776
|
+
const allowedTools = getEnabledTools(settingsChat);
|
|
8730
8777
|
const mcpConfigPath = tier !== "slim" && effectiveAgentMode !== "native" && MCP_CONFIG_FLAG[adapter.id] ? getMcpConfigPath(chatId) : null;
|
|
8731
8778
|
const baseConfig = adapter.buildSpawnConfig({
|
|
8732
8779
|
prompt: fullPrompt,
|
|
@@ -8756,7 +8803,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8756
8803
|
}
|
|
8757
8804
|
return cfg;
|
|
8758
8805
|
})() : baseConfig;
|
|
8759
|
-
const cancelState = { cancelled: false };
|
|
8806
|
+
const cancelState = { cancelled: false, userMessage };
|
|
8760
8807
|
activeChats.set(chatId, cancelState);
|
|
8761
8808
|
const spawnOpts = { onStream, onToolAction, onSubagentActivity };
|
|
8762
8809
|
const resolvedModel = model2 ?? adapter.defaultModel;
|
|
@@ -8766,7 +8813,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8766
8813
|
try {
|
|
8767
8814
|
if (useGeminiRotation) {
|
|
8768
8815
|
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);
|
|
8816
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId);
|
|
8770
8817
|
} else {
|
|
8771
8818
|
result = await spawnQuery(adapter, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts);
|
|
8772
8819
|
}
|
|
@@ -8777,7 +8824,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8777
8824
|
clearSession(chatId);
|
|
8778
8825
|
if (useGeminiRotation) {
|
|
8779
8826
|
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);
|
|
8827
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, spawnOpts, rotationCb, settingsSourceChatId);
|
|
8781
8828
|
} else {
|
|
8782
8829
|
result = await spawnQuery(adapter, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts);
|
|
8783
8830
|
}
|
|
@@ -8802,7 +8849,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8802
8849
|
if (cancelState.cancelled) {
|
|
8803
8850
|
return { text: "Stopped.", usage: { input: result.input, output: result.output, cacheRead: result.cacheRead } };
|
|
8804
8851
|
}
|
|
8805
|
-
if (result.sessionId) {
|
|
8852
|
+
if (result.sessionId && !isSyntheticChatId(chatId)) {
|
|
8806
8853
|
setSessionId(chatId, result.sessionId);
|
|
8807
8854
|
}
|
|
8808
8855
|
if (!result.resultText && result.sawToolEvents) {
|
|
@@ -8813,7 +8860,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
8813
8860
|
await summarizeSession(chatId);
|
|
8814
8861
|
clearSession(chatId);
|
|
8815
8862
|
}
|
|
8816
|
-
if (result.resultText) {
|
|
8863
|
+
if (result.resultText && !isSyntheticChatId(chatId)) {
|
|
8817
8864
|
appendToLog(chatId, userMessage, result.resultText, adapter.id, model2 ?? null, result.sessionId ?? null);
|
|
8818
8865
|
const AUTO_SUMMARIZE_THRESHOLD = 30;
|
|
8819
8866
|
const pairCount = tier !== "chat" ? getMessagePairCount(chatId) : 0;
|
|
@@ -8944,7 +8991,7 @@ ${responseText.slice(0, 500)}`);
|
|
|
8944
8991
|
if (!cleanText) return true;
|
|
8945
8992
|
if (channelName === "telegram") {
|
|
8946
8993
|
const parsed = parseTelegramTarget(targetChatId);
|
|
8947
|
-
await channel.sendText(parsed.chatId, cleanText,
|
|
8994
|
+
await channel.sendText(parsed.chatId, cleanText, { threadId: parsed.threadId });
|
|
8948
8995
|
} else {
|
|
8949
8996
|
await channel.sendText(targetChatId, cleanText);
|
|
8950
8997
|
}
|
|
@@ -8990,7 +9037,7 @@ async function notifyJobFailure(job, errorMessage2, retryInfo) {
|
|
|
8990
9037
|
const lines = [`Scheduled job #${job.id} failed: ${errorMessage2}`];
|
|
8991
9038
|
if (retryInfo) lines.push(retryInfo);
|
|
8992
9039
|
try {
|
|
8993
|
-
await channel.sendText(notifyTarget, lines.join("\n"), "plain");
|
|
9040
|
+
await channel.sendText(notifyTarget, lines.join("\n"), { parseMode: "plain" });
|
|
8994
9041
|
} catch {
|
|
8995
9042
|
}
|
|
8996
9043
|
}
|
|
@@ -9002,7 +9049,7 @@ async function notifyJobAutoPaused(job) {
|
|
|
9002
9049
|
await channel.sendText(
|
|
9003
9050
|
job.chatId,
|
|
9004
9051
|
`Job #${job.id} ("${job.description}") has been auto-paused after ${job.consecutiveFailures} consecutive failures. Use /resume ${job.id} to re-enable.`,
|
|
9005
|
-
"plain"
|
|
9052
|
+
{ parseMode: "plain" }
|
|
9006
9053
|
);
|
|
9007
9054
|
} catch {
|
|
9008
9055
|
}
|
|
@@ -10022,6 +10069,9 @@ var init_telegram = __esm({
|
|
|
10022
10069
|
// src/channels/telegram.ts
|
|
10023
10070
|
import { Bot, InlineKeyboard, InputFile } from "grammy";
|
|
10024
10071
|
function numericChatId(chatId) {
|
|
10072
|
+
if (chatId.startsWith("sq:") || chatId.startsWith("cron:")) {
|
|
10073
|
+
throw new Error(`Synthetic chatId "${chatId}" passed to Telegram API`);
|
|
10074
|
+
}
|
|
10025
10075
|
const raw = chatId.includes(":") ? chatId.split(":").pop() : chatId;
|
|
10026
10076
|
return parseInt(raw);
|
|
10027
10077
|
}
|
|
@@ -10156,7 +10206,7 @@ var init_telegram2 = __esm({
|
|
|
10156
10206
|
error("[telegram] Handler error:", err);
|
|
10157
10207
|
});
|
|
10158
10208
|
} else {
|
|
10159
|
-
this.sendText(chatId, "I can handle text, voice, photos, documents, and videos. This message type isn't supported yet.", "plain").catch(() => {
|
|
10209
|
+
this.sendText(chatId, "I can handle text, voice, photos, documents, and videos. This message type isn't supported yet.", { parseMode: "plain" }).catch(() => {
|
|
10160
10210
|
});
|
|
10161
10211
|
}
|
|
10162
10212
|
});
|
|
@@ -10219,12 +10269,14 @@ var init_telegram2 = __esm({
|
|
|
10219
10269
|
async sendTyping(chatId) {
|
|
10220
10270
|
await this.bot.api.sendChatAction(numericChatId(chatId), "typing");
|
|
10221
10271
|
}
|
|
10222
|
-
async sendText(chatId, text,
|
|
10272
|
+
async sendText(chatId, text, opts) {
|
|
10273
|
+
const { parseMode, threadId, replyToMessageId } = opts ?? {};
|
|
10223
10274
|
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
10275
|
+
const replyOpts = replyToMessageId ? { reply_parameters: { message_id: replyToMessageId } } : {};
|
|
10224
10276
|
if (parseMode === "plain") {
|
|
10225
10277
|
const plainChunks = splitMessage(text);
|
|
10226
10278
|
for (const chunk of plainChunks) {
|
|
10227
|
-
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, { ...threadOpts });
|
|
10279
|
+
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, { ...threadOpts, ...replyOpts });
|
|
10228
10280
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10229
10281
|
}
|
|
10230
10282
|
return;
|
|
@@ -10235,14 +10287,15 @@ var init_telegram2 = __esm({
|
|
|
10235
10287
|
try {
|
|
10236
10288
|
const sent = await this.bot.api.sendMessage(numericChatId(chatId), chunk, {
|
|
10237
10289
|
parse_mode: "HTML",
|
|
10238
|
-
...threadOpts
|
|
10290
|
+
...threadOpts,
|
|
10291
|
+
...replyOpts
|
|
10239
10292
|
});
|
|
10240
10293
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10241
10294
|
} catch {
|
|
10242
10295
|
const sent = await this.bot.api.sendMessage(
|
|
10243
10296
|
numericChatId(chatId),
|
|
10244
10297
|
chunk.replace(/<[^>]+>/g, ""),
|
|
10245
|
-
{ ...threadOpts }
|
|
10298
|
+
{ ...threadOpts, ...replyOpts }
|
|
10246
10299
|
);
|
|
10247
10300
|
this.trackAgentMessage(sent.message_id, chatId);
|
|
10248
10301
|
}
|
|
@@ -10818,7 +10871,7 @@ function hasActiveProfile(chatId) {
|
|
|
10818
10871
|
}
|
|
10819
10872
|
async function startProfileWizard(chatId, channel) {
|
|
10820
10873
|
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");
|
|
10874
|
+
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
10875
|
}
|
|
10823
10876
|
async function handleProfileText(chatId, text, channel) {
|
|
10824
10877
|
const state = activeProfiles.get(chatId);
|
|
@@ -10833,9 +10886,9 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10833
10886
|
[{ label: "UTC", data: "profile:tz:UTC" }, { label: "Israel", data: "profile:tz:Asia/Jerusalem" }],
|
|
10834
10887
|
[{ label: "Europe/London", data: "profile:tz:Europe/London" }, { label: "Asia/Tokyo", data: "profile:tz:Asia/Tokyo" }]
|
|
10835
10888
|
]);
|
|
10836
|
-
await channel.sendText(chatId, "Or type your timezone (e.g. America/Chicago):", "plain");
|
|
10889
|
+
await channel.sendText(chatId, "Or type your timezone (e.g. America/Chicago):", { parseMode: "plain" });
|
|
10837
10890
|
} else {
|
|
10838
|
-
await channel.sendText(chatId, `Hi ${state.name}! What's your timezone? (e.g. America/New_York, UTC, Asia/Jerusalem)`, "plain");
|
|
10891
|
+
await channel.sendText(chatId, `Hi ${state.name}! What's your timezone? (e.g. America/New_York, UTC, Asia/Jerusalem)`, { parseMode: "plain" });
|
|
10839
10892
|
}
|
|
10840
10893
|
break;
|
|
10841
10894
|
case "timezone":
|
|
@@ -10843,7 +10896,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10843
10896
|
Intl.DateTimeFormat(void 0, { timeZone: text.trim() });
|
|
10844
10897
|
state.timezone = text.trim();
|
|
10845
10898
|
} catch {
|
|
10846
|
-
await channel.sendText(chatId, "Invalid timezone. Try again (e.g. America/New_York):", "plain");
|
|
10899
|
+
await channel.sendText(chatId, "Invalid timezone. Try again (e.g. America/New_York):", { parseMode: "plain" });
|
|
10847
10900
|
return;
|
|
10848
10901
|
}
|
|
10849
10902
|
state.step = "style";
|
|
@@ -10853,7 +10906,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10853
10906
|
[{ label: "Casual", data: "profile:style:casual" }, { label: "Formal", data: "profile:style:formal" }]
|
|
10854
10907
|
]);
|
|
10855
10908
|
} else {
|
|
10856
|
-
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", "plain");
|
|
10909
|
+
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", { parseMode: "plain" });
|
|
10857
10910
|
}
|
|
10858
10911
|
break;
|
|
10859
10912
|
case "style":
|
|
@@ -10865,7 +10918,7 @@ async function handleProfileText(chatId, text, channel) {
|
|
|
10865
10918
|
[{ label: "Personal assistant", data: "profile:use:personal" }, { label: "All of the above", data: "profile:use:all" }]
|
|
10866
10919
|
]);
|
|
10867
10920
|
} else {
|
|
10868
|
-
await channel.sendText(chatId, "Primary use? (coding / research / personal / all)", "plain");
|
|
10921
|
+
await channel.sendText(chatId, "Primary use? (coding / research / personal / all)", { parseMode: "plain" });
|
|
10869
10922
|
}
|
|
10870
10923
|
break;
|
|
10871
10924
|
case "use_case":
|
|
@@ -10880,14 +10933,14 @@ async function handleProfileCallback(chatId, data, channel) {
|
|
|
10880
10933
|
if (data.startsWith("profile:tz:")) {
|
|
10881
10934
|
state.timezone = data.slice(11);
|
|
10882
10935
|
state.step = "style";
|
|
10883
|
-
await channel.sendText(chatId, `Timezone: ${state.timezone}`, "plain");
|
|
10936
|
+
await channel.sendText(chatId, `Timezone: ${state.timezone}`, { parseMode: "plain" });
|
|
10884
10937
|
if (typeof channel.sendKeyboard === "function") {
|
|
10885
10938
|
await channel.sendKeyboard(chatId, "How should I communicate?", [
|
|
10886
10939
|
[{ label: "Concise", data: "profile:style:concise" }, { label: "Detailed", data: "profile:style:detailed" }],
|
|
10887
10940
|
[{ label: "Casual", data: "profile:style:casual" }, { label: "Formal", data: "profile:style:formal" }]
|
|
10888
10941
|
]);
|
|
10889
10942
|
} else {
|
|
10890
|
-
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", "plain");
|
|
10943
|
+
await channel.sendText(chatId, "Communication style? (concise / detailed / casual / formal)", { parseMode: "plain" });
|
|
10891
10944
|
}
|
|
10892
10945
|
} else if (data.startsWith("profile:style:")) {
|
|
10893
10946
|
state.style = data.slice(14);
|
|
@@ -10928,7 +10981,7 @@ Style: ${state.style}
|
|
|
10928
10981
|
Use: ${state.useCase}
|
|
10929
10982
|
|
|
10930
10983
|
You can edit ~/.cc-claw/identity/USER.md anytime or run /setup-profile again.`,
|
|
10931
|
-
"plain"
|
|
10984
|
+
{ parseMode: "plain" }
|
|
10932
10985
|
);
|
|
10933
10986
|
}
|
|
10934
10987
|
function extractUserUpdates(text) {
|
|
@@ -11743,9 +11796,9 @@ async function startWizard(chatId, input, channel) {
|
|
|
11743
11796
|
lines.push(' "every Monday at 10:30am"');
|
|
11744
11797
|
lines.push(' "every 5 minutes"');
|
|
11745
11798
|
lines.push(' or a raw cron: "0 9 * * 1-5"');
|
|
11746
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
11799
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
11747
11800
|
} else {
|
|
11748
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
11801
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
11749
11802
|
await promptTimezone(chatId, channel);
|
|
11750
11803
|
}
|
|
11751
11804
|
}
|
|
@@ -11758,7 +11811,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11758
11811
|
const trimmed = text.trim();
|
|
11759
11812
|
if (trimmed.toLowerCase() === "keep" && pending.cron) {
|
|
11760
11813
|
pending.step = "timezone";
|
|
11761
|
-
await channel.sendText(chatId, `Keeping schedule: ${pending.cron}`, "plain");
|
|
11814
|
+
await channel.sendText(chatId, `Keeping schedule: ${pending.cron}`, { parseMode: "plain" });
|
|
11762
11815
|
await promptTimezone(chatId, channel);
|
|
11763
11816
|
return;
|
|
11764
11817
|
}
|
|
@@ -11766,7 +11819,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11766
11819
|
pending.cron = trimmed;
|
|
11767
11820
|
pending.scheduleType = "cron";
|
|
11768
11821
|
pending.step = "timezone";
|
|
11769
|
-
await channel.sendText(chatId, `Schedule set: ${trimmed}`, "plain");
|
|
11822
|
+
await channel.sendText(chatId, `Schedule set: ${trimmed}`, { parseMode: "plain" });
|
|
11770
11823
|
await promptTimezone(chatId, channel);
|
|
11771
11824
|
return;
|
|
11772
11825
|
}
|
|
@@ -11776,13 +11829,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11776
11829
|
pending.scheduleType = "cron";
|
|
11777
11830
|
if (parsed.task && parsed.task !== text) pending.task = parsed.task;
|
|
11778
11831
|
pending.step = "timezone";
|
|
11779
|
-
await channel.sendText(chatId, `Schedule: ${pending.cron}`, "plain");
|
|
11832
|
+
await channel.sendText(chatId, `Schedule: ${pending.cron}`, { parseMode: "plain" });
|
|
11780
11833
|
await promptTimezone(chatId, channel);
|
|
11781
11834
|
} else {
|
|
11782
11835
|
await channel.sendText(chatId, `Couldn't parse that schedule. Try something like:
|
|
11783
11836
|
"every day at 9am"
|
|
11784
11837
|
"every 5 minutes"
|
|
11785
|
-
or a raw cron expression like "0 9 * * 1-5"`, "plain");
|
|
11838
|
+
or a raw cron expression like "0 9 * * 1-5"`, { parseMode: "plain" });
|
|
11786
11839
|
}
|
|
11787
11840
|
break;
|
|
11788
11841
|
}
|
|
@@ -11795,7 +11848,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11795
11848
|
pending.step = "backend";
|
|
11796
11849
|
await promptBackend(chatId, channel);
|
|
11797
11850
|
} catch {
|
|
11798
|
-
await channel.sendText(chatId, `"${tz}" is not a valid timezone. Try again or tap a button.`, "plain");
|
|
11851
|
+
await channel.sendText(chatId, `"${tz}" is not a valid timezone. Try again or tap a button.`, { parseMode: "plain" });
|
|
11799
11852
|
}
|
|
11800
11853
|
break;
|
|
11801
11854
|
}
|
|
@@ -11806,7 +11859,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11806
11859
|
pending.step = "model";
|
|
11807
11860
|
await promptModel(chatId, channel);
|
|
11808
11861
|
} else {
|
|
11809
|
-
await channel.sendText(chatId, `Unknown backend. Available: ${getAvailableBackendIds().join(", ")}`, "plain");
|
|
11862
|
+
await channel.sendText(chatId, `Unknown backend. Available: ${getAvailableBackendIds().join(", ")}`, { parseMode: "plain" });
|
|
11810
11863
|
}
|
|
11811
11864
|
break;
|
|
11812
11865
|
}
|
|
@@ -11819,7 +11872,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11819
11872
|
pending.step = "thinking";
|
|
11820
11873
|
await promptThinking(chatId, channel);
|
|
11821
11874
|
} else {
|
|
11822
|
-
await channel.sendText(chatId, `Unknown model. Choose: ${Object.keys(adapter.availableModels).join(", ")}`, "plain");
|
|
11875
|
+
await channel.sendText(chatId, `Unknown model. Choose: ${Object.keys(adapter.availableModels).join(", ")}`, { parseMode: "plain" });
|
|
11823
11876
|
}
|
|
11824
11877
|
break;
|
|
11825
11878
|
}
|
|
@@ -11837,7 +11890,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11837
11890
|
pending.step = "session";
|
|
11838
11891
|
await promptSession(chatId, channel);
|
|
11839
11892
|
} 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");
|
|
11893
|
+
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
11894
|
} else {
|
|
11842
11895
|
pending.timeout = val;
|
|
11843
11896
|
pending.step = "session";
|
|
@@ -11852,7 +11905,7 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11852
11905
|
pending.step = "delivery";
|
|
11853
11906
|
await promptDelivery(chatId, channel);
|
|
11854
11907
|
} else {
|
|
11855
|
-
await channel.sendText(chatId, "Choose: isolated or main", "plain");
|
|
11908
|
+
await channel.sendText(chatId, "Choose: isolated or main", { parseMode: "plain" });
|
|
11856
11909
|
}
|
|
11857
11910
|
break;
|
|
11858
11911
|
}
|
|
@@ -11865,13 +11918,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11865
11918
|
await promptTarget(chatId, channel);
|
|
11866
11919
|
} else if (dm === "webhook") {
|
|
11867
11920
|
pending.step = "target";
|
|
11868
|
-
await channel.sendText(chatId, "Enter the webhook URL:", "plain");
|
|
11921
|
+
await channel.sendText(chatId, "Enter the webhook URL:", { parseMode: "plain" });
|
|
11869
11922
|
} else {
|
|
11870
11923
|
pending.step = "confirm";
|
|
11871
11924
|
await promptConfirm(chatId, channel);
|
|
11872
11925
|
}
|
|
11873
11926
|
} else {
|
|
11874
|
-
await channel.sendText(chatId, "Choose: announce, webhook, or none", "plain");
|
|
11927
|
+
await channel.sendText(chatId, "Choose: announce, webhook, or none", { parseMode: "plain" });
|
|
11875
11928
|
}
|
|
11876
11929
|
break;
|
|
11877
11930
|
}
|
|
@@ -11889,13 +11942,13 @@ async function handleWizardText(chatId, text, channel) {
|
|
|
11889
11942
|
break;
|
|
11890
11943
|
}
|
|
11891
11944
|
default:
|
|
11892
|
-
await channel.sendText(chatId, "Please use the buttons to select an option, or type 'cancel' to abort.", "plain");
|
|
11945
|
+
await channel.sendText(chatId, "Please use the buttons to select an option, or type 'cancel' to abort.", { parseMode: "plain" });
|
|
11893
11946
|
}
|
|
11894
11947
|
}
|
|
11895
11948
|
async function handleWizardCallback(chatId, data, channel) {
|
|
11896
11949
|
const pending = pendingJobs.get(chatId);
|
|
11897
11950
|
if (!pending) {
|
|
11898
|
-
await channel.sendText(chatId, "No active scheduling wizard. Use /schedule to start one.", "plain");
|
|
11951
|
+
await channel.sendText(chatId, "No active scheduling wizard. Use /schedule to start one.", { parseMode: "plain" });
|
|
11899
11952
|
return;
|
|
11900
11953
|
}
|
|
11901
11954
|
resetWizardTimeout(chatId);
|
|
@@ -11903,20 +11956,20 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11903
11956
|
const tz = data.slice(9);
|
|
11904
11957
|
pending.timezone = COMMON_TIMEZONES[tz] ?? tz;
|
|
11905
11958
|
pending.step = "backend";
|
|
11906
|
-
await channel.sendText(chatId, `Timezone: ${pending.timezone}`, "plain");
|
|
11959
|
+
await channel.sendText(chatId, `Timezone: ${pending.timezone}`, { parseMode: "plain" });
|
|
11907
11960
|
await promptBackend(chatId, channel);
|
|
11908
11961
|
} else if (data.startsWith("sched:backend:")) {
|
|
11909
11962
|
const backend2 = data.slice(14);
|
|
11910
11963
|
pending.backend = backend2;
|
|
11911
11964
|
pending.step = "model";
|
|
11912
11965
|
const adapter = getAdapter(backend2);
|
|
11913
|
-
await channel.sendText(chatId, `Backend: ${adapter.displayName}`, "plain");
|
|
11966
|
+
await channel.sendText(chatId, `Backend: ${adapter.displayName}`, { parseMode: "plain" });
|
|
11914
11967
|
await promptModel(chatId, channel);
|
|
11915
11968
|
} else if (data.startsWith("sched:model:")) {
|
|
11916
11969
|
const model2 = data.slice(12);
|
|
11917
11970
|
pending.model = model2;
|
|
11918
11971
|
pending.step = "thinking";
|
|
11919
|
-
await channel.sendText(chatId, `Model: ${model2}`, "plain");
|
|
11972
|
+
await channel.sendText(chatId, `Model: ${model2}`, { parseMode: "plain" });
|
|
11920
11973
|
await promptThinking(chatId, channel);
|
|
11921
11974
|
} else if (data.startsWith("sched:thinking:")) {
|
|
11922
11975
|
pending.thinking = data.slice(15);
|
|
@@ -11931,7 +11984,7 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11931
11984
|
}
|
|
11932
11985
|
pending.step = "session";
|
|
11933
11986
|
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");
|
|
11987
|
+
await channel.sendText(chatId, `Timeout: ${label2}`, { parseMode: "plain" });
|
|
11935
11988
|
await promptSession(chatId, channel);
|
|
11936
11989
|
} else if (data.startsWith("sched:session:")) {
|
|
11937
11990
|
pending.sessionType = data.slice(14);
|
|
@@ -11944,7 +11997,7 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11944
11997
|
await promptTarget(chatId, channel);
|
|
11945
11998
|
} else if (pending.deliveryMode === "webhook") {
|
|
11946
11999
|
pending.step = "target";
|
|
11947
|
-
await channel.sendText(chatId, "Enter the webhook URL:", "plain");
|
|
12000
|
+
await channel.sendText(chatId, "Enter the webhook URL:", { parseMode: "plain" });
|
|
11948
12001
|
} else {
|
|
11949
12002
|
pending.step = "confirm";
|
|
11950
12003
|
await promptConfirm(chatId, channel);
|
|
@@ -11953,21 +12006,21 @@ async function handleWizardCallback(chatId, data, channel) {
|
|
|
11953
12006
|
pending.target = chatId;
|
|
11954
12007
|
pending.channel = "telegram";
|
|
11955
12008
|
pending.step = "confirm";
|
|
11956
|
-
await channel.sendText(chatId, "Delivery: this chat", "plain");
|
|
12009
|
+
await channel.sendText(chatId, "Delivery: this chat", { parseMode: "plain" });
|
|
11957
12010
|
await promptConfirm(chatId, channel);
|
|
11958
12011
|
} else if (data === "sched:confirm") {
|
|
11959
12012
|
await finalizeJob(chatId, channel);
|
|
11960
12013
|
} else if (data === "sched:edit") {
|
|
11961
12014
|
pending.step = "schedule";
|
|
11962
|
-
await channel.sendText(chatId, "Starting over. When should this run?\nSend a schedule or raw cron expression:", "plain");
|
|
12015
|
+
await channel.sendText(chatId, "Starting over. When should this run?\nSend a schedule or raw cron expression:", { parseMode: "plain" });
|
|
11963
12016
|
} else if (data === "sched:cancel") {
|
|
11964
12017
|
pendingJobs.delete(chatId);
|
|
11965
|
-
await channel.sendText(chatId, "Scheduling cancelled.", "plain");
|
|
12018
|
+
await channel.sendText(chatId, "Scheduling cancelled.", { parseMode: "plain" });
|
|
11966
12019
|
}
|
|
11967
12020
|
}
|
|
11968
12021
|
async function promptTimezone(chatId, channel) {
|
|
11969
12022
|
if (typeof channel.sendKeyboard !== "function") {
|
|
11970
|
-
await channel.sendText(chatId, "Enter a timezone (e.g. America/New_York, UTC, Asia/Jerusalem):", "plain");
|
|
12023
|
+
await channel.sendText(chatId, "Enter a timezone (e.g. America/New_York, UTC, Asia/Jerusalem):", { parseMode: "plain" });
|
|
11971
12024
|
return;
|
|
11972
12025
|
}
|
|
11973
12026
|
const tzButtons = [];
|
|
@@ -11983,7 +12036,7 @@ async function promptTimezone(chatId, channel) {
|
|
|
11983
12036
|
}
|
|
11984
12037
|
async function promptBackend(chatId, channel) {
|
|
11985
12038
|
if (typeof channel.sendKeyboard !== "function") {
|
|
11986
|
-
await channel.sendText(chatId, `Enter backend (${getAvailableBackendIds().join(", ")}):`, "plain");
|
|
12039
|
+
await channel.sendText(chatId, `Enter backend (${getAvailableBackendIds().join(", ")}):`, { parseMode: "plain" });
|
|
11987
12040
|
return;
|
|
11988
12041
|
}
|
|
11989
12042
|
const adapters2 = getAvailableAdapters();
|
|
@@ -11999,7 +12052,7 @@ async function promptModel(chatId, channel) {
|
|
|
11999
12052
|
const adapter = getAdapter(pending.backend);
|
|
12000
12053
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12001
12054
|
const models = Object.keys(adapter.availableModels).join(", ");
|
|
12002
|
-
await channel.sendText(chatId, `Enter model (${models}):`, "plain");
|
|
12055
|
+
await channel.sendText(chatId, `Enter model (${models}):`, { parseMode: "plain" });
|
|
12003
12056
|
return;
|
|
12004
12057
|
}
|
|
12005
12058
|
const buttons = Object.entries(adapter.availableModels).map(([id, info]) => [{
|
|
@@ -12015,7 +12068,7 @@ async function promptThinking(chatId, channel) {
|
|
|
12015
12068
|
const modelInfo = adapter.availableModels[pending.model];
|
|
12016
12069
|
if (modelInfo?.thinking === "adjustable" && modelInfo.thinkingLevels) {
|
|
12017
12070
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12018
|
-
await channel.sendText(chatId, `Enter thinking level (${modelInfo.thinkingLevels.join(", ")}):`, "plain");
|
|
12071
|
+
await channel.sendText(chatId, `Enter thinking level (${modelInfo.thinkingLevels.join(", ")}):`, { parseMode: "plain" });
|
|
12019
12072
|
return;
|
|
12020
12073
|
}
|
|
12021
12074
|
const buttons = modelInfo.thinkingLevels.map((level) => [{
|
|
@@ -12031,7 +12084,7 @@ async function promptThinking(chatId, channel) {
|
|
|
12031
12084
|
}
|
|
12032
12085
|
async function promptTimeout(chatId, channel) {
|
|
12033
12086
|
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");
|
|
12087
|
+
await channel.sendText(chatId, `Job timeout in seconds (${TIMEOUT_MIN_SECONDS}-${TIMEOUT_MAX_SECONDS}), or "default" for ${TIMEOUT_DEFAULT_SECONDS}s:`, { parseMode: "plain" });
|
|
12035
12088
|
return;
|
|
12036
12089
|
}
|
|
12037
12090
|
await channel.sendKeyboard(chatId, "Maximum runtime for this job?", [
|
|
@@ -12048,7 +12101,7 @@ async function promptTimeout(chatId, channel) {
|
|
|
12048
12101
|
}
|
|
12049
12102
|
async function promptSession(chatId, channel) {
|
|
12050
12103
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12051
|
-
await channel.sendText(chatId, "Session type: isolated (fresh, no history) or main (uses conversation context)?", "plain");
|
|
12104
|
+
await channel.sendText(chatId, "Session type: isolated (fresh, no history) or main (uses conversation context)?", { parseMode: "plain" });
|
|
12052
12105
|
return;
|
|
12053
12106
|
}
|
|
12054
12107
|
await channel.sendKeyboard(chatId, "Session type for this job?", [
|
|
@@ -12058,7 +12111,7 @@ async function promptSession(chatId, channel) {
|
|
|
12058
12111
|
}
|
|
12059
12112
|
async function promptDelivery(chatId, channel) {
|
|
12060
12113
|
if (typeof channel.sendKeyboard !== "function") {
|
|
12061
|
-
await channel.sendText(chatId, "Delivery mode: announce (send to chat), webhook (HTTP POST), or none (silent)?", "plain");
|
|
12114
|
+
await channel.sendText(chatId, "Delivery mode: announce (send to chat), webhook (HTTP POST), or none (silent)?", { parseMode: "plain" });
|
|
12062
12115
|
return;
|
|
12063
12116
|
}
|
|
12064
12117
|
await channel.sendKeyboard(chatId, "How should results be delivered?", [
|
|
@@ -12069,13 +12122,13 @@ async function promptDelivery(chatId, channel) {
|
|
|
12069
12122
|
}
|
|
12070
12123
|
async function promptTarget(chatId, channel) {
|
|
12071
12124
|
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");
|
|
12125
|
+
await channel.sendText(chatId, "Enter the chat ID or group ID for delivery (or send 'this' for this chat):", { parseMode: "plain" });
|
|
12073
12126
|
return;
|
|
12074
12127
|
}
|
|
12075
12128
|
await channel.sendKeyboard(chatId, "Where should results be sent?", [
|
|
12076
12129
|
[{ label: "This chat", data: "sched:target:this" }]
|
|
12077
12130
|
]);
|
|
12078
|
-
await channel.sendText(chatId, "Or send a chat/group ID (e.g. -100123456789 or -100123456789:topic:42):", "plain");
|
|
12131
|
+
await channel.sendText(chatId, "Or send a chat/group ID (e.g. -100123456789 or -100123456789:topic:42):", { parseMode: "plain" });
|
|
12079
12132
|
}
|
|
12080
12133
|
async function promptConfirm(chatId, channel) {
|
|
12081
12134
|
const pending = pendingJobs.get(chatId);
|
|
@@ -12106,7 +12159,7 @@ async function promptConfirm(chatId, channel) {
|
|
|
12106
12159
|
[{ label: "Edit", data: "sched:edit" }, { label: "Cancel", data: "sched:cancel" }]
|
|
12107
12160
|
]);
|
|
12108
12161
|
} else {
|
|
12109
|
-
await channel.sendText(chatId, lines.join("\n") + "\n\nSend 'confirm' to create or 'cancel' to abort.", "plain");
|
|
12162
|
+
await channel.sendText(chatId, lines.join("\n") + "\n\nSend 'confirm' to create or 'cancel' to abort.", { parseMode: "plain" });
|
|
12110
12163
|
}
|
|
12111
12164
|
}
|
|
12112
12165
|
async function finalizeJob(chatId, channel) {
|
|
@@ -12144,7 +12197,7 @@ async function finalizeJob(chatId, channel) {
|
|
|
12144
12197
|
Task: ${jobParams.description}
|
|
12145
12198
|
Schedule: ${jobParams.cron ?? "N/A"}
|
|
12146
12199
|
Timezone: ${jobParams.timezone}`,
|
|
12147
|
-
"plain"
|
|
12200
|
+
{ parseMode: "plain" }
|
|
12148
12201
|
);
|
|
12149
12202
|
} else {
|
|
12150
12203
|
const job = insertJob({ ...jobParams, chatId });
|
|
@@ -12159,17 +12212,17 @@ Task: ${job.description}
|
|
|
12159
12212
|
Schedule: ${job.cron ?? "N/A"}
|
|
12160
12213
|
Timezone: ${job.timezone}
|
|
12161
12214
|
Next run will be at the scheduled time.`,
|
|
12162
|
-
"plain"
|
|
12215
|
+
{ parseMode: "plain" }
|
|
12163
12216
|
);
|
|
12164
12217
|
}
|
|
12165
12218
|
} catch (err) {
|
|
12166
|
-
await channel.sendText(chatId, `Failed to ${editJobId ? "update" : "create"} job: ${errorMessage(err)}`, "plain");
|
|
12219
|
+
await channel.sendText(chatId, `Failed to ${editJobId ? "update" : "create"} job: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
12167
12220
|
}
|
|
12168
12221
|
}
|
|
12169
12222
|
async function startEditWizard(chatId, jobId, channel) {
|
|
12170
12223
|
const job = getJobById(jobId);
|
|
12171
12224
|
if (!job) {
|
|
12172
|
-
await channel.sendText(chatId, `Job #${jobId} not found.`, "plain");
|
|
12225
|
+
await channel.sendText(chatId, `Job #${jobId} not found.`, { parseMode: "plain" });
|
|
12173
12226
|
return;
|
|
12174
12227
|
}
|
|
12175
12228
|
const pending = {
|
|
@@ -12201,7 +12254,7 @@ Current schedule: ${schedule2}
|
|
|
12201
12254
|
Current task: ${job.description}
|
|
12202
12255
|
|
|
12203
12256
|
Send a new schedule, or type 'keep' to keep the current one:`,
|
|
12204
|
-
"plain"
|
|
12257
|
+
{ parseMode: "plain" }
|
|
12205
12258
|
);
|
|
12206
12259
|
}
|
|
12207
12260
|
var WIZARD_TIMEOUT_MS, wizardTimers, pendingJobs;
|
|
@@ -12521,22 +12574,22 @@ async function handleBackendCommand(command, chatId, channel) {
|
|
|
12521
12574
|
try {
|
|
12522
12575
|
adapter = getAdapterForChat(chatId);
|
|
12523
12576
|
} catch {
|
|
12524
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
12577
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
12525
12578
|
return;
|
|
12526
12579
|
}
|
|
12527
12580
|
const sessionId = getSessionId(chatId);
|
|
12528
12581
|
if (!sessionId) {
|
|
12529
|
-
await channel.sendText(chatId, "No active session. Start a conversation first.", "plain");
|
|
12582
|
+
await channel.sendText(chatId, "No active session. Start a conversation first.", { parseMode: "plain" });
|
|
12530
12583
|
return;
|
|
12531
12584
|
}
|
|
12532
12585
|
const cwd = getCwd(chatId) ?? `${process.env.HOME ?? "/tmp"}/.cc-claw/workspace`;
|
|
12533
12586
|
try {
|
|
12534
12587
|
const output2 = await spawnBackendCommand(adapter, command, sessionId, cwd);
|
|
12535
12588
|
const formatted = buildNativeResponse(adapter.id, command, output2);
|
|
12536
|
-
await channel.sendText(chatId, formatted, "html");
|
|
12589
|
+
await channel.sendText(chatId, formatted, { parseMode: "html" });
|
|
12537
12590
|
} catch (err) {
|
|
12538
12591
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12539
|
-
await channel.sendText(chatId, `Backend command failed: ${msg}`, "plain");
|
|
12592
|
+
await channel.sendText(chatId, `Backend command failed: ${msg}`, { parseMode: "plain" });
|
|
12540
12593
|
}
|
|
12541
12594
|
}
|
|
12542
12595
|
function spawnBackendCommand(adapter, command, sessionId, cwd) {
|
|
@@ -12620,6 +12673,7 @@ var init_pagination = __esm({
|
|
|
12620
12673
|
var propose_exports = {};
|
|
12621
12674
|
__export(propose_exports, {
|
|
12622
12675
|
buildEvolveMenuKeyboard: () => buildEvolveMenuKeyboard,
|
|
12676
|
+
buildEvolveOnboardingKeyboard: () => buildEvolveOnboardingKeyboard,
|
|
12623
12677
|
buildModelKeyboard: () => buildModelKeyboard,
|
|
12624
12678
|
buildProposalKeyboard: () => buildProposalKeyboard,
|
|
12625
12679
|
buildUndoKeyboard: () => buildUndoKeyboard,
|
|
@@ -12632,16 +12686,20 @@ function pct(ratio) {
|
|
|
12632
12686
|
return `${Math.round(ratio * 100)}%`;
|
|
12633
12687
|
}
|
|
12634
12688
|
function formatProposalCard(params) {
|
|
12635
|
-
const { category, insight, why, targetFile, confidence } = params;
|
|
12689
|
+
const { category, insight, why, targetFile, confidence, proposedAction, proposedDiff } = params;
|
|
12636
12690
|
const header2 = `[${category}] ${insight}`;
|
|
12637
|
-
const whyLine = `Why: ${why}
|
|
12691
|
+
const whyLine = why ? `Why: ${why}` : null;
|
|
12638
12692
|
const confidencePct = pct(confidence);
|
|
12639
12693
|
const showTarget = category !== "codebase" && targetFile && targetFile !== "codebase";
|
|
12640
12694
|
const targetLine = showTarget ? `Target: ${targetFile} | Confidence: ${confidencePct}` : `Confidence: ${confidencePct}`;
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12695
|
+
const lines = [header2, ""];
|
|
12696
|
+
if (whyLine) lines.push(whyLine);
|
|
12697
|
+
lines.push(targetLine);
|
|
12698
|
+
if (proposedDiff) {
|
|
12699
|
+
const actionLabel = proposedAction ? ` (${proposedAction})` : "";
|
|
12700
|
+
lines.push("", `Proposed change${actionLabel}:`, "```diff", proposedDiff, "```");
|
|
12701
|
+
}
|
|
12702
|
+
return lines.join("\n");
|
|
12645
12703
|
}
|
|
12646
12704
|
function formatNightlySummary(insights) {
|
|
12647
12705
|
const count = insights.length;
|
|
@@ -12686,7 +12744,7 @@ function buildProposalKeyboard(insightId, category) {
|
|
|
12686
12744
|
return [
|
|
12687
12745
|
[
|
|
12688
12746
|
{ label: "Show Diff", data: `evolve:diff:${insightId}`, style: "primary" },
|
|
12689
|
-
{ label: "
|
|
12747
|
+
{ label: "Discuss", data: `evolve:discuss:${insightId}` },
|
|
12690
12748
|
{ label: "Reject", data: `evolve:reject:${insightId}`, style: "danger" }
|
|
12691
12749
|
]
|
|
12692
12750
|
];
|
|
@@ -12694,25 +12752,32 @@ function buildProposalKeyboard(insightId, category) {
|
|
|
12694
12752
|
return [
|
|
12695
12753
|
[
|
|
12696
12754
|
{ label: "Apply", data: `evolve:apply:${insightId}`, style: "success" },
|
|
12697
|
-
{ label: "
|
|
12755
|
+
{ label: "Discuss", data: `evolve:discuss:${insightId}` },
|
|
12698
12756
|
{ label: "Reject", data: `evolve:reject:${insightId}`, style: "danger" }
|
|
12699
12757
|
]
|
|
12700
12758
|
];
|
|
12701
12759
|
}
|
|
12702
|
-
function
|
|
12760
|
+
function buildEvolveOnboardingKeyboard() {
|
|
12761
|
+
return [
|
|
12762
|
+
[{ label: "\u2705 Enable Self-Learning", data: "evolve:toggle", style: "success" }],
|
|
12763
|
+
[{ label: "One-Time Analysis", data: "evolve:analyze" }]
|
|
12764
|
+
];
|
|
12765
|
+
}
|
|
12766
|
+
function buildEvolveMenuKeyboard(ctx) {
|
|
12767
|
+
const reviewLabel = ctx.pendingProposals > 0 ? `Review (${ctx.pendingProposals})` : "Review";
|
|
12703
12768
|
return [
|
|
12704
12769
|
[
|
|
12705
|
-
{ label: "Analyze Now", data: "evolve:analyze", style: "success" },
|
|
12706
|
-
{ label: "
|
|
12770
|
+
{ label: "\u{1F50D} Analyze Now", data: "evolve:analyze", style: "success" },
|
|
12771
|
+
ctx.pendingProposals > 0 ? { label: reviewLabel, data: "evolve:review", style: "primary" } : { label: reviewLabel, data: "evolve:review" }
|
|
12707
12772
|
],
|
|
12708
12773
|
[
|
|
12709
12774
|
{ label: "Stats", data: "evolve:stats" },
|
|
12710
12775
|
{ label: "History", data: "evolve:history" }
|
|
12711
12776
|
],
|
|
12712
12777
|
[
|
|
12713
|
-
{ label: "
|
|
12778
|
+
{ label: "Model", data: "evolve:model" },
|
|
12714
12779
|
{ label: "Undo", data: "evolve:undo", style: "danger" },
|
|
12715
|
-
{ label: "
|
|
12780
|
+
{ label: "\u23F8 Disable", data: "evolve:toggle", style: "danger" }
|
|
12716
12781
|
]
|
|
12717
12782
|
];
|
|
12718
12783
|
}
|
|
@@ -12743,6 +12808,7 @@ var init_propose = __esm({
|
|
|
12743
12808
|
|
|
12744
12809
|
// src/router.ts
|
|
12745
12810
|
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
|
|
12811
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
12746
12812
|
import { resolve as resolvePath, join as join19 } from "path";
|
|
12747
12813
|
function parseMcpListOutput(output2) {
|
|
12748
12814
|
const results = [];
|
|
@@ -12941,7 +13007,7 @@ async function sendUnifiedUsage(chatId, channel, view) {
|
|
|
12941
13007
|
];
|
|
12942
13008
|
await channel.sendKeyboard(chatId, lines.join("\n"), buttons);
|
|
12943
13009
|
} else {
|
|
12944
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13010
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
12945
13011
|
}
|
|
12946
13012
|
}
|
|
12947
13013
|
async function sendUsageLimits(chatId, channel) {
|
|
@@ -12975,7 +13041,7 @@ async function sendUsageLimits(chatId, channel) {
|
|
|
12975
13041
|
]);
|
|
12976
13042
|
await channel.sendKeyboard(chatId, lines.join("\n"), rows);
|
|
12977
13043
|
} else {
|
|
12978
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13044
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
12979
13045
|
}
|
|
12980
13046
|
}
|
|
12981
13047
|
function getMediaRetentionMs() {
|
|
@@ -13034,6 +13100,22 @@ function pickFallbackEmoji(userMessage) {
|
|
|
13034
13100
|
}
|
|
13035
13101
|
return "\u{1F44D}";
|
|
13036
13102
|
}
|
|
13103
|
+
function parseSideQuestPrefix(text) {
|
|
13104
|
+
const match = text.match(/^(?:sq|btw):\s*/i);
|
|
13105
|
+
if (match) return { isSideQuest: true, cleanText: text.slice(match[0].length) };
|
|
13106
|
+
return { isSideQuest: false, cleanText: text };
|
|
13107
|
+
}
|
|
13108
|
+
function getActiveSideQuestCount(chatId) {
|
|
13109
|
+
return activeSideQuests.get(chatId)?.size ?? 0;
|
|
13110
|
+
}
|
|
13111
|
+
function stopAllSideQuests(chatId) {
|
|
13112
|
+
const active = activeSideQuests.get(chatId);
|
|
13113
|
+
if (active) {
|
|
13114
|
+
for (const sqId of active) {
|
|
13115
|
+
stopAgent(sqId);
|
|
13116
|
+
}
|
|
13117
|
+
}
|
|
13118
|
+
}
|
|
13037
13119
|
async function handleResponseExhaustion(responseText, chatId, msg, channel) {
|
|
13038
13120
|
const raw = responseText.replace(/\n\n🧠 \[.+$/, "").trim();
|
|
13039
13121
|
if (raw.length > 300 || !isExhaustedMessage(raw)) return false;
|
|
@@ -13122,7 +13204,7 @@ async function handleCommand(msg, channel) {
|
|
|
13122
13204
|
([cat, cmds]) => `${cat}:
|
|
13123
13205
|
${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
13124
13206
|
).join("\n\n"),
|
|
13125
|
-
"plain"
|
|
13207
|
+
{ parseMode: "plain" }
|
|
13126
13208
|
);
|
|
13127
13209
|
}
|
|
13128
13210
|
break;
|
|
@@ -13141,17 +13223,18 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13141
13223
|
await channel.sendText(
|
|
13142
13224
|
chatId,
|
|
13143
13225
|
"CC-Claw Menu:\n/newchat \xB7 /status \xB7 /backend \xB7 /model\n/jobs \xB7 /memory \xB7 /history \xB7 /help",
|
|
13144
|
-
"plain"
|
|
13226
|
+
{ parseMode: "plain" }
|
|
13145
13227
|
);
|
|
13146
13228
|
}
|
|
13147
13229
|
break;
|
|
13148
13230
|
}
|
|
13149
13231
|
case "stop": {
|
|
13150
13232
|
const stopped = stopAgent(chatId);
|
|
13233
|
+
stopAllSideQuests(chatId);
|
|
13151
13234
|
await channel.sendText(
|
|
13152
13235
|
chatId,
|
|
13153
13236
|
stopped ? "Stopping current task..." : "Nothing is running.",
|
|
13154
|
-
"plain"
|
|
13237
|
+
{ parseMode: "plain" }
|
|
13155
13238
|
);
|
|
13156
13239
|
if (stopped && typeof channel.sendKeyboard === "function") {
|
|
13157
13240
|
await channel.sendKeyboard(chatId, "", [
|
|
@@ -13174,7 +13257,7 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13174
13257
|
for (const [id, label2] of Object.entries(PERM_MODES)) {
|
|
13175
13258
|
lines.push(`${id === currentMode ? "\u2713 " : " "}/permissions ${id} \u2014 ${label2}`);
|
|
13176
13259
|
}
|
|
13177
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13260
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13178
13261
|
}
|
|
13179
13262
|
break;
|
|
13180
13263
|
}
|
|
@@ -13191,7 +13274,7 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
13191
13274
|
const lines = Object.entries(VERBOSE_LEVELS).map(
|
|
13192
13275
|
([id, label2]) => `${id === currentVerbose ? "\u2713 " : " "}${id} \u2014 ${label2}`
|
|
13193
13276
|
);
|
|
13194
|
-
await channel.sendText(chatId, ["Tool visibility:", "", ...lines].join("\n"), "plain");
|
|
13277
|
+
await channel.sendText(chatId, ["Tool visibility:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13195
13278
|
}
|
|
13196
13279
|
break;
|
|
13197
13280
|
}
|
|
@@ -13218,12 +13301,13 @@ Tap to toggle:`,
|
|
|
13218
13301
|
);
|
|
13219
13302
|
} else {
|
|
13220
13303
|
const lines = ALL_TOOLS.map((t) => `${toolsMap[t] ? "[on] " : "[off]"} ${t}`);
|
|
13221
|
-
await channel.sendText(chatId, ["Allowed tools:", "", ...lines].join("\n"), "plain");
|
|
13304
|
+
await channel.sendText(chatId, ["Allowed tools:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13222
13305
|
}
|
|
13223
13306
|
break;
|
|
13224
13307
|
}
|
|
13225
13308
|
case "new":
|
|
13226
13309
|
case "newchat": {
|
|
13310
|
+
stopAllSideQuests(chatId);
|
|
13227
13311
|
const oldSessionId = getSessionId(chatId);
|
|
13228
13312
|
const exchangeCount = getMessagePairCount(chatId);
|
|
13229
13313
|
const summarized = await summarizeSession(chatId);
|
|
@@ -13247,7 +13331,7 @@ Tap to toggle:`,
|
|
|
13247
13331
|
}
|
|
13248
13332
|
} else {
|
|
13249
13333
|
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");
|
|
13334
|
+
await channel.sendText(chatId, msg2, { parseMode: "plain" });
|
|
13251
13335
|
}
|
|
13252
13336
|
break;
|
|
13253
13337
|
}
|
|
@@ -13255,12 +13339,12 @@ Tap to toggle:`,
|
|
|
13255
13339
|
if (commandArgs?.toLowerCase() === "all") {
|
|
13256
13340
|
const pendingIds = getLoggedChatIds();
|
|
13257
13341
|
if (pendingIds.length === 0) {
|
|
13258
|
-
await channel.sendText(chatId, "No pending sessions to summarize.", "plain");
|
|
13342
|
+
await channel.sendText(chatId, "No pending sessions to summarize.", { parseMode: "plain" });
|
|
13259
13343
|
break;
|
|
13260
13344
|
}
|
|
13261
|
-
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, "plain");
|
|
13345
|
+
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, { parseMode: "plain" });
|
|
13262
13346
|
await summarizeAllPending();
|
|
13263
|
-
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, "plain");
|
|
13347
|
+
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, { parseMode: "plain" });
|
|
13264
13348
|
} else {
|
|
13265
13349
|
const pairs = getMessagePairCount(chatId);
|
|
13266
13350
|
if (pairs < 2) {
|
|
@@ -13268,16 +13352,16 @@ Tap to toggle:`,
|
|
|
13268
13352
|
await channel.sendText(
|
|
13269
13353
|
chatId,
|
|
13270
13354
|
"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"
|
|
13355
|
+
{ parseMode: "plain" }
|
|
13272
13356
|
);
|
|
13273
13357
|
} else {
|
|
13274
|
-
await channel.sendText(chatId, "Not enough conversation to summarize (need at least 2 exchanges).", "plain");
|
|
13358
|
+
await channel.sendText(chatId, "Not enough conversation to summarize (need at least 2 exchanges).", { parseMode: "plain" });
|
|
13275
13359
|
}
|
|
13276
13360
|
break;
|
|
13277
13361
|
}
|
|
13278
13362
|
const progressMsgId = await channel.sendTextReturningId?.(chatId, `Summarizing ${pairs} exchanges...`, "plain");
|
|
13279
13363
|
if (!progressMsgId) {
|
|
13280
|
-
await channel.sendText(chatId, `Summarizing ${pairs} exchanges...`, "plain");
|
|
13364
|
+
await channel.sendText(chatId, `Summarizing ${pairs} exchanges...`, { parseMode: "plain" });
|
|
13281
13365
|
}
|
|
13282
13366
|
const success2 = await summarizeSession(chatId);
|
|
13283
13367
|
if (success2) {
|
|
@@ -13311,14 +13395,14 @@ Tap to toggle:`,
|
|
|
13311
13395
|
}
|
|
13312
13396
|
}
|
|
13313
13397
|
} else {
|
|
13314
|
-
await channel.sendText(chatId, doneText, "plain");
|
|
13398
|
+
await channel.sendText(chatId, doneText, { parseMode: "plain" });
|
|
13315
13399
|
}
|
|
13316
13400
|
} else {
|
|
13317
13401
|
const failText = "Summarization failed. Session log preserved for retry.";
|
|
13318
13402
|
if (progressMsgId) {
|
|
13319
13403
|
await channel.editText?.(chatId, progressMsgId, failText, "plain");
|
|
13320
13404
|
} else {
|
|
13321
|
-
await channel.sendText(chatId, failText, "plain");
|
|
13405
|
+
await channel.sendText(chatId, failText, { parseMode: "plain" });
|
|
13322
13406
|
}
|
|
13323
13407
|
}
|
|
13324
13408
|
}
|
|
@@ -13383,6 +13467,7 @@ Tap to toggle:`,
|
|
|
13383
13467
|
const iQuick = iStats.chat;
|
|
13384
13468
|
const iDeep = iStats.agentic;
|
|
13385
13469
|
const intentLine = iTotal > 0 ? `\u26A1 ${iTotal} messages: ${iQuick} quick, ${iDeep} deep` : `\u26A1 No messages classified yet`;
|
|
13470
|
+
const sqCount = getActiveSideQuestCount(chatId);
|
|
13386
13471
|
const lines = [
|
|
13387
13472
|
`\u{1F43E} CC-Claw v${VERSION}`,
|
|
13388
13473
|
`\u23F1 Uptime: ${uptimeStr}`,
|
|
@@ -13397,6 +13482,7 @@ Tap to toggle:`,
|
|
|
13397
13482
|
`\u{1F4CB} ${sessionId ? sessionId.slice(0, 12) + "..." : "no active session"}`,
|
|
13398
13483
|
`\u{1F4C1} ${cwd ?? "default workspace"}`,
|
|
13399
13484
|
`\u{1F4D0} Context: ${ctxBar} ${usedK}K/${maxK}K (${contextPct.toFixed(1)}%)`,
|
|
13485
|
+
...sqCount > 0 ? [`\u{1F5FA} Side quests: ${sqCount} active`] : [],
|
|
13400
13486
|
``,
|
|
13401
13487
|
buildSectionHeader("Usage"),
|
|
13402
13488
|
`\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 +13504,7 @@ Tap to toggle:`,
|
|
|
13418
13504
|
]
|
|
13419
13505
|
]);
|
|
13420
13506
|
} else {
|
|
13421
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13507
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13422
13508
|
}
|
|
13423
13509
|
break;
|
|
13424
13510
|
}
|
|
@@ -13441,7 +13527,7 @@ Tap to toggle:`,
|
|
|
13441
13527
|
const lines = adapters2.map(
|
|
13442
13528
|
(a) => `${a.id === currentBackend ? "\u2713 " : " "}${a.displayName} (/backend ${a.id})`
|
|
13443
13529
|
);
|
|
13444
|
-
await channel.sendText(chatId, ["Available backends:", "", ...lines].join("\n"), "plain");
|
|
13530
|
+
await channel.sendText(chatId, ["Available backends:", "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13445
13531
|
}
|
|
13446
13532
|
break;
|
|
13447
13533
|
}
|
|
@@ -13452,14 +13538,14 @@ Tap to toggle:`,
|
|
|
13452
13538
|
if (getAllBackendIds().includes(backendId)) {
|
|
13453
13539
|
await sendBackendSwitchConfirmation(chatId, backendId, channel);
|
|
13454
13540
|
} else {
|
|
13455
|
-
await channel.sendText(chatId, `Backend "${command}" is not available.`, "plain");
|
|
13541
|
+
await channel.sendText(chatId, `Backend "${command}" is not available.`, { parseMode: "plain" });
|
|
13456
13542
|
}
|
|
13457
13543
|
break;
|
|
13458
13544
|
}
|
|
13459
13545
|
case "gemini_accounts": {
|
|
13460
13546
|
const slots = getGeminiSlots();
|
|
13461
13547
|
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");
|
|
13548
|
+
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
13549
|
break;
|
|
13464
13550
|
}
|
|
13465
13551
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13493,7 +13579,7 @@ Tap to toggle:`,
|
|
|
13493
13579
|
${list}
|
|
13494
13580
|
|
|
13495
13581
|
Rotation mode: ${currentMode}
|
|
13496
|
-
Use: /gemini_accounts <name> to pin`, "plain");
|
|
13582
|
+
Use: /gemini_accounts <name> to pin`, { parseMode: "plain" });
|
|
13497
13583
|
}
|
|
13498
13584
|
break;
|
|
13499
13585
|
}
|
|
@@ -13502,7 +13588,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13502
13588
|
if (getAllBackendIds().includes(backendId)) {
|
|
13503
13589
|
await sendBackendSwitchConfirmation(chatId, backendId, channel);
|
|
13504
13590
|
} else {
|
|
13505
|
-
await channel.sendText(chatId, `Backend "${command}" is not available.`, "plain");
|
|
13591
|
+
await channel.sendText(chatId, `Backend "${command}" is not available.`, { parseMode: "plain" });
|
|
13506
13592
|
}
|
|
13507
13593
|
break;
|
|
13508
13594
|
}
|
|
@@ -13511,7 +13597,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13511
13597
|
try {
|
|
13512
13598
|
adapter = getAdapterForChat(chatId);
|
|
13513
13599
|
} catch {
|
|
13514
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
13600
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
13515
13601
|
break;
|
|
13516
13602
|
}
|
|
13517
13603
|
const models = adapter.availableModels;
|
|
@@ -13530,7 +13616,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13530
13616
|
const lines = Object.entries(models).map(
|
|
13531
13617
|
([id, info]) => `${id === current ? "\u2713 " : " "}${id} \u2014 ${info.label}`
|
|
13532
13618
|
);
|
|
13533
|
-
await channel.sendText(chatId, [`Models (${adapter.displayName}):`, "", ...lines].join("\n"), "plain");
|
|
13619
|
+
await channel.sendText(chatId, [`Models (${adapter.displayName}):`, "", ...lines].join("\n"), { parseMode: "plain" });
|
|
13534
13620
|
}
|
|
13535
13621
|
break;
|
|
13536
13622
|
}
|
|
@@ -13562,7 +13648,7 @@ Use: /gemini_accounts <name> to pin`, "plain");
|
|
|
13562
13648
|
} else {
|
|
13563
13649
|
await channel.sendText(chatId, `Summarizer: ${currentLabel}
|
|
13564
13650
|
|
|
13565
|
-
Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain");
|
|
13651
|
+
Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, { parseMode: "plain" });
|
|
13566
13652
|
}
|
|
13567
13653
|
break;
|
|
13568
13654
|
}
|
|
@@ -13574,24 +13660,24 @@ Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain
|
|
|
13574
13660
|
if (parts.length >= 3) {
|
|
13575
13661
|
const [bk, win, val] = parts;
|
|
13576
13662
|
if (!getAllBackendIds().includes(bk)) {
|
|
13577
|
-
await channel.sendText(chatId, `Unknown backend: ${bk}. Available: ${getAllBackendIds().join(", ")}`, "plain");
|
|
13663
|
+
await channel.sendText(chatId, `Unknown backend: ${bk}. Available: ${getAllBackendIds().join(", ")}`, { parseMode: "plain" });
|
|
13578
13664
|
break;
|
|
13579
13665
|
}
|
|
13580
13666
|
if (!["hourly", "daily", "weekly"].includes(win)) {
|
|
13581
|
-
await channel.sendText(chatId, "Window must be: hourly, daily, or weekly", "plain");
|
|
13667
|
+
await channel.sendText(chatId, "Window must be: hourly, daily, or weekly", { parseMode: "plain" });
|
|
13582
13668
|
break;
|
|
13583
13669
|
}
|
|
13584
13670
|
if (val === "off") {
|
|
13585
13671
|
clearBackendLimit(bk, win);
|
|
13586
|
-
await channel.sendText(chatId, `Limit removed for ${bk} (${win}).`, "plain");
|
|
13672
|
+
await channel.sendText(chatId, `Limit removed for ${bk} (${win}).`, { parseMode: "plain" });
|
|
13587
13673
|
} else {
|
|
13588
13674
|
const tokens = parseInt(val, 10);
|
|
13589
13675
|
if (isNaN(tokens) || tokens <= 0) {
|
|
13590
|
-
await channel.sendText(chatId, "Token limit must be a positive number.", "plain");
|
|
13676
|
+
await channel.sendText(chatId, "Token limit must be a positive number.", { parseMode: "plain" });
|
|
13591
13677
|
break;
|
|
13592
13678
|
}
|
|
13593
13679
|
setBackendLimit(bk, win, tokens);
|
|
13594
|
-
await channel.sendText(chatId, `Limit set: ${bk} (${win}) = ${(tokens / 1e3).toFixed(0)}K input tokens`, "plain");
|
|
13680
|
+
await channel.sendText(chatId, `Limit set: ${bk} (${win}) = ${(tokens / 1e3).toFixed(0)}K input tokens`, { parseMode: "plain" });
|
|
13595
13681
|
}
|
|
13596
13682
|
break;
|
|
13597
13683
|
}
|
|
@@ -13609,7 +13695,7 @@ Use /summarizer auto, /summarizer off, or /summarizer <backend>:<model>`, "plain
|
|
|
13609
13695
|
current ? `Working directory: ${current}
|
|
13610
13696
|
|
|
13611
13697
|
No saved bookmarks yet. Set a directory with /cwd <path> to auto-save.` : "No working directory set. Usage: /cwd ~/projects/my-app",
|
|
13612
|
-
"plain"
|
|
13698
|
+
{ parseMode: "plain" }
|
|
13613
13699
|
);
|
|
13614
13700
|
return;
|
|
13615
13701
|
}
|
|
@@ -13622,46 +13708,46 @@ Recent directories:` : "Recent directories:";
|
|
|
13622
13708
|
} else {
|
|
13623
13709
|
const list = recents.map((r) => ` ${r.alias} \u2192 ${r.path}`).join("\n");
|
|
13624
13710
|
await channel.sendText(chatId, `${text}
|
|
13625
|
-
${list}`, "plain");
|
|
13711
|
+
${list}`, { parseMode: "plain" });
|
|
13626
13712
|
}
|
|
13627
13713
|
return;
|
|
13628
13714
|
}
|
|
13629
13715
|
if (commandArgs === "reset" || commandArgs === "clear") {
|
|
13630
13716
|
clearCwd(chatId);
|
|
13631
|
-
await channel.sendText(chatId, "Working directory cleared. Using default.", "plain");
|
|
13717
|
+
await channel.sendText(chatId, "Working directory cleared. Using default.", { parseMode: "plain" });
|
|
13632
13718
|
return;
|
|
13633
13719
|
}
|
|
13634
13720
|
if (commandArgs === "aliases") {
|
|
13635
13721
|
const all = getAllBookmarks(chatId);
|
|
13636
13722
|
if (all.length === 0) {
|
|
13637
|
-
await channel.sendText(chatId, "No bookmarks saved yet.", "plain");
|
|
13723
|
+
await channel.sendText(chatId, "No bookmarks saved yet.", { parseMode: "plain" });
|
|
13638
13724
|
return;
|
|
13639
13725
|
}
|
|
13640
13726
|
const lines = all.map((b) => ` ${b.manual ? "[manual]" : "[auto]"} ${b.alias} \u2192 ${b.path}`);
|
|
13641
13727
|
await channel.sendText(chatId, `Directory bookmarks:
|
|
13642
|
-
${lines.join("\n")}`, "plain");
|
|
13728
|
+
${lines.join("\n")}`, { parseMode: "plain" });
|
|
13643
13729
|
return;
|
|
13644
13730
|
}
|
|
13645
13731
|
if (commandArgs.startsWith("unalias ")) {
|
|
13646
13732
|
const aliasName = commandArgs.slice(8).trim();
|
|
13647
13733
|
if (!aliasName) {
|
|
13648
|
-
await channel.sendText(chatId, "Usage: /cwd unalias <name>", "plain");
|
|
13734
|
+
await channel.sendText(chatId, "Usage: /cwd unalias <name>", { parseMode: "plain" });
|
|
13649
13735
|
return;
|
|
13650
13736
|
}
|
|
13651
13737
|
const deleted = deleteBookmark(chatId, aliasName);
|
|
13652
|
-
await channel.sendText(chatId, deleted ? `Bookmark '${aliasName}' removed.` : `Bookmark '${aliasName}' not found.`, "plain");
|
|
13738
|
+
await channel.sendText(chatId, deleted ? `Bookmark '${aliasName}' removed.` : `Bookmark '${aliasName}' not found.`, { parseMode: "plain" });
|
|
13653
13739
|
return;
|
|
13654
13740
|
}
|
|
13655
13741
|
if (commandArgs.startsWith("alias ")) {
|
|
13656
13742
|
const parts = commandArgs.slice(6).trim().split(/\s+/);
|
|
13657
13743
|
if (parts.length < 2) {
|
|
13658
|
-
await channel.sendText(chatId, "Usage: /cwd alias <name> <path>", "plain");
|
|
13744
|
+
await channel.sendText(chatId, "Usage: /cwd alias <name> <path>", { parseMode: "plain" });
|
|
13659
13745
|
return;
|
|
13660
13746
|
}
|
|
13661
13747
|
const [aliasName, ...pathParts] = parts;
|
|
13662
13748
|
const aliasPath = pathParts.join(" ").replace(/^~/, process.env.HOME ?? "");
|
|
13663
13749
|
upsertBookmark(chatId, aliasName, aliasPath, true);
|
|
13664
|
-
await channel.sendText(chatId, `Bookmark saved: ${aliasName} \u2192 ${aliasPath}`, "plain");
|
|
13750
|
+
await channel.sendText(chatId, `Bookmark saved: ${aliasName} \u2192 ${aliasPath}`, { parseMode: "plain" });
|
|
13665
13751
|
return;
|
|
13666
13752
|
}
|
|
13667
13753
|
const arg = commandArgs;
|
|
@@ -13695,31 +13781,31 @@ ${lines.join("\n")}`, "plain");
|
|
|
13695
13781
|
await channel.sendKeyboard(chatId, `Multiple matches for "${arg}":`, buttons);
|
|
13696
13782
|
return;
|
|
13697
13783
|
}
|
|
13698
|
-
await channel.sendText(chatId, `Directory alias '${arg}' not found. Use /cwd aliases to see saved bookmarks.`, "plain");
|
|
13784
|
+
await channel.sendText(chatId, `Directory alias '${arg}' not found. Use /cwd aliases to see saved bookmarks.`, { parseMode: "plain" });
|
|
13699
13785
|
break;
|
|
13700
13786
|
}
|
|
13701
13787
|
case "memory": {
|
|
13702
13788
|
if (commandArgs?.startsWith("edit ")) {
|
|
13703
13789
|
const editMatch = commandArgs.match(/^edit\s+(\d+)\s+(.+)/);
|
|
13704
13790
|
if (!editMatch) {
|
|
13705
|
-
await channel.sendText(chatId, "Usage: /memory edit <id> <new content>", "plain");
|
|
13791
|
+
await channel.sendText(chatId, "Usage: /memory edit <id> <new content>", { parseMode: "plain" });
|
|
13706
13792
|
break;
|
|
13707
13793
|
}
|
|
13708
13794
|
const editId = parseInt(editMatch[1], 10);
|
|
13709
13795
|
const newContent = editMatch[2];
|
|
13710
13796
|
const mem = getMemoryById(editId);
|
|
13711
13797
|
if (!mem) {
|
|
13712
|
-
await channel.sendText(chatId, "Memory not found.", "plain");
|
|
13798
|
+
await channel.sendText(chatId, "Memory not found.", { parseMode: "plain" });
|
|
13713
13799
|
break;
|
|
13714
13800
|
}
|
|
13715
13801
|
deleteMemoryById(editId);
|
|
13716
13802
|
saveMemoryWithEmbedding(mem.trigger, newContent, mem.type);
|
|
13717
|
-
await channel.sendText(chatId, `Memory #${editId} updated.`, "plain");
|
|
13803
|
+
await channel.sendText(chatId, `Memory #${editId} updated.`, { parseMode: "plain" });
|
|
13718
13804
|
break;
|
|
13719
13805
|
}
|
|
13720
13806
|
const memories = listMemories();
|
|
13721
13807
|
if (memories.length === 0) {
|
|
13722
|
-
await channel.sendText(chatId, "No memories stored yet.", "plain");
|
|
13808
|
+
await channel.sendText(chatId, "No memories stored yet.", { parseMode: "plain" });
|
|
13723
13809
|
return;
|
|
13724
13810
|
}
|
|
13725
13811
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13728,19 +13814,19 @@ ${lines.join("\n")}`, "plain");
|
|
|
13728
13814
|
const lines = memories.map(
|
|
13729
13815
|
(m) => `- ${m.trigger}: ${m.content} (salience: ${m.salience.toFixed(2)})`
|
|
13730
13816
|
);
|
|
13731
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
13817
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
13732
13818
|
}
|
|
13733
13819
|
break;
|
|
13734
13820
|
}
|
|
13735
13821
|
case "remember": {
|
|
13736
13822
|
if (!commandArgs) {
|
|
13737
|
-
await channel.sendText(chatId, "Usage: /remember <text>", "plain");
|
|
13823
|
+
await channel.sendText(chatId, "Usage: /remember <text>", { parseMode: "plain" });
|
|
13738
13824
|
return;
|
|
13739
13825
|
}
|
|
13740
13826
|
const content = commandArgs.replace(/^that\s+/i, "");
|
|
13741
13827
|
const trigger = content.split(/\s+/).slice(0, 3).join(" ");
|
|
13742
13828
|
saveMemoryWithEmbedding(trigger, content, "semantic");
|
|
13743
|
-
await channel.sendText(chatId, "Got it, I'll remember that.", "plain");
|
|
13829
|
+
await channel.sendText(chatId, "Got it, I'll remember that.", { parseMode: "plain" });
|
|
13744
13830
|
if (typeof channel.sendKeyboard === "function") {
|
|
13745
13831
|
await channel.sendKeyboard(chatId, "", [
|
|
13746
13832
|
[{ label: "\u{1F4DA} View Memories", data: "menu:memory" }]
|
|
@@ -13750,14 +13836,14 @@ ${lines.join("\n")}`, "plain");
|
|
|
13750
13836
|
}
|
|
13751
13837
|
case "forget": {
|
|
13752
13838
|
if (!commandArgs) {
|
|
13753
|
-
await channel.sendText(chatId, "Usage: /forget <keyword>", "plain");
|
|
13839
|
+
await channel.sendText(chatId, "Usage: /forget <keyword>", { parseMode: "plain" });
|
|
13754
13840
|
return;
|
|
13755
13841
|
}
|
|
13756
13842
|
const count = forgetMemory(commandArgs);
|
|
13757
13843
|
await channel.sendText(
|
|
13758
13844
|
chatId,
|
|
13759
13845
|
count > 0 ? `Forgot ${count} memory(ies) matching "${commandArgs}".` : `No memories found matching "${commandArgs}".`,
|
|
13760
|
-
"plain"
|
|
13846
|
+
{ parseMode: "plain" }
|
|
13761
13847
|
);
|
|
13762
13848
|
break;
|
|
13763
13849
|
}
|
|
@@ -13772,7 +13858,7 @@ ${lines.join("\n")}`, "plain");
|
|
|
13772
13858
|
]);
|
|
13773
13859
|
} else {
|
|
13774
13860
|
const toggled = toggleVoice(chatId);
|
|
13775
|
-
await channel.sendText(chatId, toggled ? "Voice responses enabled." : "Voice responses disabled.", "plain");
|
|
13861
|
+
await channel.sendText(chatId, toggled ? "Voice responses enabled." : "Voice responses disabled.", { parseMode: "plain" });
|
|
13776
13862
|
}
|
|
13777
13863
|
break;
|
|
13778
13864
|
}
|
|
@@ -13791,7 +13877,7 @@ ${lines.join("\n")}`, "plain");
|
|
|
13791
13877
|
]
|
|
13792
13878
|
]);
|
|
13793
13879
|
} else {
|
|
13794
|
-
await channel.sendText(chatId, `Current Response Style: ${currentStyle}`, "plain");
|
|
13880
|
+
await channel.sendText(chatId, `Current Response Style: ${currentStyle}`, { parseMode: "plain" });
|
|
13795
13881
|
}
|
|
13796
13882
|
break;
|
|
13797
13883
|
}
|
|
@@ -13808,7 +13894,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13808
13894
|
} else {
|
|
13809
13895
|
const newSig = currentSig === "on" ? "off" : "on";
|
|
13810
13896
|
setModelSignature(chatId, newSig);
|
|
13811
|
-
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", "plain");
|
|
13897
|
+
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", { parseMode: "plain" });
|
|
13812
13898
|
}
|
|
13813
13899
|
break;
|
|
13814
13900
|
}
|
|
@@ -13818,7 +13904,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13818
13904
|
try {
|
|
13819
13905
|
adapter = getAdapterForChat(chatId);
|
|
13820
13906
|
} catch {
|
|
13821
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
13907
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
13822
13908
|
break;
|
|
13823
13909
|
}
|
|
13824
13910
|
const currentModel = getModel(chatId) ?? adapter.defaultModel;
|
|
@@ -13826,7 +13912,7 @@ Appends model + thinking level to each response.`, [
|
|
|
13826
13912
|
const currentLevel = getThinkingLevel(chatId) || "auto";
|
|
13827
13913
|
if (!modelInfo || modelInfo.thinking !== "adjustable" || !modelInfo.thinkingLevels) {
|
|
13828
13914
|
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");
|
|
13915
|
+
Use /model to pick a model with \u26A1 thinking support.`, { parseMode: "plain" });
|
|
13830
13916
|
break;
|
|
13831
13917
|
}
|
|
13832
13918
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -13844,31 +13930,31 @@ Current: ${capitalize(currentLevel)}`,
|
|
|
13844
13930
|
} else {
|
|
13845
13931
|
await channel.sendText(chatId, `Thinking: ${capitalize(currentLevel)}
|
|
13846
13932
|
Levels: ${modelInfo.thinkingLevels.join(", ")}
|
|
13847
|
-
Set via callback (keyboard required).`, "plain");
|
|
13933
|
+
Set via callback (keyboard required).`, { parseMode: "plain" });
|
|
13848
13934
|
}
|
|
13849
13935
|
break;
|
|
13850
13936
|
}
|
|
13851
13937
|
case "imagine":
|
|
13852
13938
|
case "image": {
|
|
13853
13939
|
if (!commandArgs) {
|
|
13854
|
-
await channel.sendText(chatId, "Usage: /imagine <prompt>\nExample: /imagine a cat astronaut on Mars", "plain");
|
|
13940
|
+
await channel.sendText(chatId, "Usage: /imagine <prompt>\nExample: /imagine a cat astronaut on Mars", { parseMode: "plain" });
|
|
13855
13941
|
return;
|
|
13856
13942
|
}
|
|
13857
13943
|
if (!isImageGenAvailable()) {
|
|
13858
|
-
await channel.sendText(chatId, "Image generation requires GEMINI_API_KEY. Configure it in ~/.cc-claw/.env", "plain");
|
|
13944
|
+
await channel.sendText(chatId, "Image generation requires GEMINI_API_KEY. Configure it in ~/.cc-claw/.env", { parseMode: "plain" });
|
|
13859
13945
|
return;
|
|
13860
13946
|
}
|
|
13861
|
-
await channel.sendText(chatId, "\u{1F3A8} Generating image\u2026", "plain");
|
|
13947
|
+
await channel.sendText(chatId, "\u{1F3A8} Generating image\u2026", { parseMode: "plain" });
|
|
13862
13948
|
try {
|
|
13863
13949
|
const result = await generateImage(commandArgs);
|
|
13864
13950
|
const file = await readFile5(result.filePath);
|
|
13865
13951
|
const name = result.filePath.split("/").pop() ?? "image.png";
|
|
13866
13952
|
await channel.sendFile(chatId, file, name);
|
|
13867
13953
|
if (result.text) {
|
|
13868
|
-
await channel.sendText(chatId, result.text, "plain");
|
|
13954
|
+
await channel.sendText(chatId, result.text, { parseMode: "plain" });
|
|
13869
13955
|
}
|
|
13870
13956
|
} catch (err) {
|
|
13871
|
-
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, "plain");
|
|
13957
|
+
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
13872
13958
|
}
|
|
13873
13959
|
break;
|
|
13874
13960
|
}
|
|
@@ -13877,7 +13963,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13877
13963
|
await channel.sendText(
|
|
13878
13964
|
chatId,
|
|
13879
13965
|
"Usage: /schedule <description>\nExample: /schedule every day at 9am summarize AI news\n\nThe wizard will guide you through all configuration options.",
|
|
13880
|
-
"plain"
|
|
13966
|
+
{ parseMode: "plain" }
|
|
13881
13967
|
);
|
|
13882
13968
|
return;
|
|
13883
13969
|
}
|
|
@@ -13898,7 +13984,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13898
13984
|
await channel.sendText(
|
|
13899
13985
|
chatId,
|
|
13900
13986
|
success2 ? `Job #${id} cancelled.` : `Job #${id} not found.`,
|
|
13901
|
-
"plain"
|
|
13987
|
+
{ parseMode: "plain" }
|
|
13902
13988
|
);
|
|
13903
13989
|
break;
|
|
13904
13990
|
}
|
|
@@ -13912,7 +13998,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13912
13998
|
await channel.sendText(
|
|
13913
13999
|
chatId,
|
|
13914
14000
|
paused ? `Job #${pauseId} paused. Use /resume ${pauseId} to re-enable.` : `Job #${pauseId} not found.`,
|
|
13915
|
-
"plain"
|
|
14001
|
+
{ parseMode: "plain" }
|
|
13916
14002
|
);
|
|
13917
14003
|
break;
|
|
13918
14004
|
}
|
|
@@ -13926,7 +14012,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13926
14012
|
await channel.sendText(
|
|
13927
14013
|
chatId,
|
|
13928
14014
|
resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`,
|
|
13929
|
-
"plain"
|
|
14015
|
+
{ parseMode: "plain" }
|
|
13930
14016
|
);
|
|
13931
14017
|
break;
|
|
13932
14018
|
}
|
|
@@ -13936,9 +14022,9 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13936
14022
|
return;
|
|
13937
14023
|
}
|
|
13938
14024
|
const runJobId = parseInt(commandArgs, 10);
|
|
13939
|
-
await channel.sendText(chatId, `Triggering job #${runJobId}...`, "plain");
|
|
14025
|
+
await channel.sendText(chatId, `Triggering job #${runJobId}...`, { parseMode: "plain" });
|
|
13940
14026
|
const result = await triggerJob(runJobId);
|
|
13941
|
-
await channel.sendText(chatId, result, "plain");
|
|
14027
|
+
await channel.sendText(chatId, result, { parseMode: "plain" });
|
|
13942
14028
|
break;
|
|
13943
14029
|
}
|
|
13944
14030
|
case "runs": {
|
|
@@ -13948,7 +14034,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13948
14034
|
} else {
|
|
13949
14035
|
const runs = getJobRuns(void 0, 10);
|
|
13950
14036
|
if (runs.length === 0) {
|
|
13951
|
-
await channel.sendText(chatId, "No run history yet.", "plain");
|
|
14037
|
+
await channel.sendText(chatId, "No run history yet.", { parseMode: "plain" });
|
|
13952
14038
|
return;
|
|
13953
14039
|
}
|
|
13954
14040
|
const lines = runs.map((r) => {
|
|
@@ -13959,13 +14045,13 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13959
14045
|
Tokens: ${r.usageInput}in / ${r.usageOutput}out` : "";
|
|
13960
14046
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${duration}${error3}${usage2}`;
|
|
13961
14047
|
});
|
|
13962
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
14048
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
13963
14049
|
}
|
|
13964
14050
|
break;
|
|
13965
14051
|
}
|
|
13966
14052
|
case "editjob": {
|
|
13967
14053
|
if (!commandArgs) {
|
|
13968
|
-
await channel.sendText(chatId, "Usage: /editjob <job-id>", "plain");
|
|
14054
|
+
await channel.sendText(chatId, "Usage: /editjob <job-id>", { parseMode: "plain" });
|
|
13969
14055
|
return;
|
|
13970
14056
|
}
|
|
13971
14057
|
const editId = parseInt(commandArgs, 10);
|
|
@@ -13974,7 +14060,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13974
14060
|
}
|
|
13975
14061
|
case "health": {
|
|
13976
14062
|
const report = getHealthReport();
|
|
13977
|
-
await channel.sendText(chatId, formatHealthReport(report), "plain");
|
|
14063
|
+
await channel.sendText(chatId, formatHealthReport(report), { parseMode: "plain" });
|
|
13978
14064
|
if (typeof channel.sendKeyboard === "function") {
|
|
13979
14065
|
await channel.sendKeyboard(chatId, "", [
|
|
13980
14066
|
[
|
|
@@ -13990,7 +14076,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
13990
14076
|
if (query) {
|
|
13991
14077
|
const results = searchMessageLog(chatId, query, 20);
|
|
13992
14078
|
if (results.length === 0) {
|
|
13993
|
-
await channel.sendText(chatId, `No matching history found. Try /memories ${query} for older sessions.`, "plain");
|
|
14079
|
+
await channel.sendText(chatId, `No matching history found. Try /memories ${query} for older sessions.`, { parseMode: "plain" });
|
|
13994
14080
|
break;
|
|
13995
14081
|
}
|
|
13996
14082
|
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 +14087,14 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14001
14087
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${roleLabel}: ${preview}`);
|
|
14002
14088
|
}
|
|
14003
14089
|
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");
|
|
14090
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14005
14091
|
} else {
|
|
14006
14092
|
if (typeof channel.sendKeyboard === "function") {
|
|
14007
14093
|
await sendHistoryView(chatId, channel, {});
|
|
14008
14094
|
} else {
|
|
14009
14095
|
const rows = getRecentMessageLog(chatId, 20).reverse();
|
|
14010
14096
|
if (rows.length === 0) {
|
|
14011
|
-
await channel.sendText(chatId, "No conversation history found.", "plain");
|
|
14097
|
+
await channel.sendText(chatId, "No conversation history found.", { parseMode: "plain" });
|
|
14012
14098
|
break;
|
|
14013
14099
|
}
|
|
14014
14100
|
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 +14105,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14019
14105
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${roleLabel}: ${preview}`);
|
|
14020
14106
|
}
|
|
14021
14107
|
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");
|
|
14108
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14023
14109
|
}
|
|
14024
14110
|
}
|
|
14025
14111
|
break;
|
|
@@ -14027,7 +14113,7 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14027
14113
|
case "skills": {
|
|
14028
14114
|
const skills2 = await discoverAllSkills();
|
|
14029
14115
|
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");
|
|
14116
|
+
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
14117
|
return;
|
|
14032
14118
|
}
|
|
14033
14119
|
const page = commandArgs ? parseInt(commandArgs, 10) || 1 : 1;
|
|
@@ -14036,16 +14122,16 @@ Set via callback (keyboard required).`, "plain");
|
|
|
14036
14122
|
}
|
|
14037
14123
|
case "skill-install": {
|
|
14038
14124
|
if (!commandArgs) {
|
|
14039
|
-
await channel.sendText(chatId, "Usage: /skill-install <github-url>\nExample: /skill-install jacob-bd/universal-skills-manager", "plain");
|
|
14125
|
+
await channel.sendText(chatId, "Usage: /skill-install <github-url>\nExample: /skill-install jacob-bd/universal-skills-manager", { parseMode: "plain" });
|
|
14040
14126
|
return;
|
|
14041
14127
|
}
|
|
14042
|
-
await channel.sendText(chatId, `Installing skill from ${commandArgs}...`, "plain");
|
|
14128
|
+
await channel.sendText(chatId, `Installing skill from ${commandArgs}...`, { parseMode: "plain" });
|
|
14043
14129
|
const result = await installSkillFromGitHub(commandArgs);
|
|
14044
14130
|
if (result.success) {
|
|
14045
14131
|
await channel.sendText(chatId, `Skill "${result.skillName}" installed to ~/.cc-claw/workspace/skills/
|
|
14046
|
-
Use /skills to see it.`, "plain");
|
|
14132
|
+
Use /skills to see it.`, { parseMode: "plain" });
|
|
14047
14133
|
} else {
|
|
14048
|
-
await channel.sendText(chatId, `Installation failed: ${result.error}`, "plain");
|
|
14134
|
+
await channel.sendText(chatId, `Installation failed: ${result.error}`, { parseMode: "plain" });
|
|
14049
14135
|
}
|
|
14050
14136
|
break;
|
|
14051
14137
|
}
|
|
@@ -14079,10 +14165,10 @@ Use /skills to see it.`, "plain");
|
|
|
14079
14165
|
}
|
|
14080
14166
|
} else {
|
|
14081
14167
|
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");
|
|
14168
|
+
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
14169
|
} else {
|
|
14084
14170
|
const lines = ["Authorized chats:", "", ...aliases.map((a) => ` ${a.alias} -> ${a.chatId}`)];
|
|
14085
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
14171
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
14086
14172
|
}
|
|
14087
14173
|
}
|
|
14088
14174
|
break;
|
|
@@ -14092,12 +14178,12 @@ Use /skills to see it.`, "plain");
|
|
|
14092
14178
|
const targetChatId = parts[1];
|
|
14093
14179
|
const alias = parts.slice(2).join("-").toLowerCase();
|
|
14094
14180
|
setChatAlias(alias, targetChatId);
|
|
14095
|
-
await channel.sendText(chatId, `Alias set: ${alias} -> ${targetChatId}`, "plain");
|
|
14181
|
+
await channel.sendText(chatId, `Alias set: ${alias} -> ${targetChatId}`, { parseMode: "plain" });
|
|
14096
14182
|
} else if (parts[0] === "remove" && parts[1]) {
|
|
14097
14183
|
const removed = removeChatAlias(parts[1]);
|
|
14098
|
-
await channel.sendText(chatId, removed ? `Alias "${parts[1]}" removed.` : `Alias "${parts[1]}" not found.`, "plain");
|
|
14184
|
+
await channel.sendText(chatId, removed ? `Alias "${parts[1]}" removed.` : `Alias "${parts[1]}" not found.`, { parseMode: "plain" });
|
|
14099
14185
|
} 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");
|
|
14186
|
+
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
14187
|
}
|
|
14102
14188
|
break;
|
|
14103
14189
|
}
|
|
@@ -14111,7 +14197,7 @@ Use /skills to see it.`, "plain");
|
|
|
14111
14197
|
if (typeof channel.sendKeyboard === "function") {
|
|
14112
14198
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14113
14199
|
} else {
|
|
14114
|
-
await channel.sendText(chatId, "Heartbeat enabled. I'll check in periodically.", "plain");
|
|
14200
|
+
await channel.sendText(chatId, "Heartbeat enabled. I'll check in periodically.", { parseMode: "plain" });
|
|
14115
14201
|
}
|
|
14116
14202
|
break;
|
|
14117
14203
|
}
|
|
@@ -14121,14 +14207,14 @@ Use /skills to see it.`, "plain");
|
|
|
14121
14207
|
if (typeof channel.sendKeyboard === "function") {
|
|
14122
14208
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14123
14209
|
} else {
|
|
14124
|
-
await channel.sendText(chatId, "Heartbeat disabled.", "plain");
|
|
14210
|
+
await channel.sendText(chatId, "Heartbeat disabled.", { parseMode: "plain" });
|
|
14125
14211
|
}
|
|
14126
14212
|
break;
|
|
14127
14213
|
}
|
|
14128
14214
|
case "interval": {
|
|
14129
14215
|
const ms = parseIntervalToMs(value ?? "30m");
|
|
14130
14216
|
if (!ms || ms < 6e4) {
|
|
14131
|
-
await channel.sendText(chatId, "Invalid interval. Use e.g. 15m, 30m, 1h, 2h", "plain");
|
|
14217
|
+
await channel.sendText(chatId, "Invalid interval. Use e.g. 15m, 30m, 1h, 2h", { parseMode: "plain" });
|
|
14132
14218
|
break;
|
|
14133
14219
|
}
|
|
14134
14220
|
setHeartbeatConfig(chatId, { intervalMs: ms });
|
|
@@ -14138,14 +14224,14 @@ Use /skills to see it.`, "plain");
|
|
|
14138
14224
|
if (typeof channel.sendKeyboard === "function") {
|
|
14139
14225
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14140
14226
|
} else {
|
|
14141
|
-
await channel.sendText(chatId, `Heartbeat interval set to ${ms / 6e4} minutes.`, "plain");
|
|
14227
|
+
await channel.sendText(chatId, `Heartbeat interval set to ${ms / 6e4} minutes.`, { parseMode: "plain" });
|
|
14142
14228
|
}
|
|
14143
14229
|
break;
|
|
14144
14230
|
}
|
|
14145
14231
|
case "hours": {
|
|
14146
14232
|
const hourMatch = (value ?? "").match(/^(\d{1,2})-(\d{1,2})$/);
|
|
14147
14233
|
if (!hourMatch) {
|
|
14148
|
-
await channel.sendText(chatId, "Usage: /heartbeat hours 8-22", "plain");
|
|
14234
|
+
await channel.sendText(chatId, "Usage: /heartbeat hours 8-22", { parseMode: "plain" });
|
|
14149
14235
|
break;
|
|
14150
14236
|
}
|
|
14151
14237
|
const hbStart = `${hourMatch[1].padStart(2, "0")}:00`;
|
|
@@ -14154,7 +14240,7 @@ Use /skills to see it.`, "plain");
|
|
|
14154
14240
|
if (typeof channel.sendKeyboard === "function") {
|
|
14155
14241
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14156
14242
|
} else {
|
|
14157
|
-
await channel.sendText(chatId, `Active hours: ${hbStart} - ${hbEnd}`, "plain");
|
|
14243
|
+
await channel.sendText(chatId, `Active hours: ${hbStart} - ${hbEnd}`, { parseMode: "plain" });
|
|
14158
14244
|
}
|
|
14159
14245
|
break;
|
|
14160
14246
|
}
|
|
@@ -14162,7 +14248,7 @@ Use /skills to see it.`, "plain");
|
|
|
14162
14248
|
if (typeof channel.sendKeyboard === "function") {
|
|
14163
14249
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14164
14250
|
} else {
|
|
14165
|
-
await channel.sendText(chatId, formatHeartbeatStatus(chatId), "plain");
|
|
14251
|
+
await channel.sendText(chatId, formatHeartbeatStatus(chatId), { parseMode: "plain" });
|
|
14166
14252
|
}
|
|
14167
14253
|
}
|
|
14168
14254
|
break;
|
|
@@ -14170,7 +14256,7 @@ Use /skills to see it.`, "plain");
|
|
|
14170
14256
|
if (typeof channel.sendKeyboard === "function") {
|
|
14171
14257
|
await sendHeartbeatKeyboard(chatId, channel);
|
|
14172
14258
|
} else {
|
|
14173
|
-
await channel.sendText(chatId, formatHeartbeatStatus(chatId), "plain");
|
|
14259
|
+
await channel.sendText(chatId, formatHeartbeatStatus(chatId), { parseMode: "plain" });
|
|
14174
14260
|
}
|
|
14175
14261
|
break;
|
|
14176
14262
|
}
|
|
@@ -14185,7 +14271,7 @@ Use /skills to see it.`, "plain");
|
|
|
14185
14271
|
} catch {
|
|
14186
14272
|
}
|
|
14187
14273
|
clearSession(chatId);
|
|
14188
|
-
await channel.sendText(chatId, `Agent mode set to <b>${modeArg}</b>. Session cleared.`, "html");
|
|
14274
|
+
await channel.sendText(chatId, `Agent mode set to <b>${modeArg}</b>. Session cleared.`, { parseMode: "html" });
|
|
14189
14275
|
} else if (typeof channel.sendKeyboard === "function") {
|
|
14190
14276
|
const current = getAgentMode(chatId);
|
|
14191
14277
|
await channel.sendKeyboard(chatId, `Agent mode: <b>${current}</b>
|
|
@@ -14199,7 +14285,7 @@ Choose a mode:`, [
|
|
|
14199
14285
|
]);
|
|
14200
14286
|
} else {
|
|
14201
14287
|
const current = getAgentMode(chatId);
|
|
14202
|
-
await channel.sendText(chatId, `Agent mode: ${current}. Use /agents mode <auto|native|claw> to change.`, "plain");
|
|
14288
|
+
await channel.sendText(chatId, `Agent mode: ${current}. Use /agents mode <auto|native|claw> to change.`, { parseMode: "plain" });
|
|
14203
14289
|
}
|
|
14204
14290
|
return;
|
|
14205
14291
|
}
|
|
@@ -14212,7 +14298,7 @@ Choose a mode:`, [
|
|
|
14212
14298
|
ORDER BY createdAt DESC LIMIT 20
|
|
14213
14299
|
`).all(chatId);
|
|
14214
14300
|
if (events.length === 0) {
|
|
14215
|
-
await channel.sendText(chatId, "No native sub-agent activity in the last 24h.", "plain");
|
|
14301
|
+
await channel.sendText(chatId, "No native sub-agent activity in the last 24h.", { parseMode: "plain" });
|
|
14216
14302
|
} else {
|
|
14217
14303
|
const lines2 = events.map((e) => {
|
|
14218
14304
|
const d = e.detail ? JSON.parse(e.detail) : {};
|
|
@@ -14220,7 +14306,7 @@ Choose a mode:`, [
|
|
|
14220
14306
|
});
|
|
14221
14307
|
await channel.sendText(chatId, `<b>Native agent history (24h)</b>
|
|
14222
14308
|
|
|
14223
|
-
${lines2.join("\n")}`, "html");
|
|
14309
|
+
${lines2.join("\n")}`, { parseMode: "html" });
|
|
14224
14310
|
}
|
|
14225
14311
|
return;
|
|
14226
14312
|
}
|
|
@@ -14237,7 +14323,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14237
14323
|
const runners2 = getAllRunners();
|
|
14238
14324
|
const runnerMap = new Map(runners2.map((r) => [r.id, r]));
|
|
14239
14325
|
if (agents2.length === 0) {
|
|
14240
|
-
await channel.sendText(chatId, "<b>Active Agents</b>\n\nNo active agents.", "html");
|
|
14326
|
+
await channel.sendText(chatId, "<b>Active Agents</b>\n\nNo active agents.", { parseMode: "html" });
|
|
14241
14327
|
break;
|
|
14242
14328
|
}
|
|
14243
14329
|
const { getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
@@ -14271,7 +14357,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14271
14357
|
lines.push("");
|
|
14272
14358
|
}
|
|
14273
14359
|
lines.push(`Total: ${agents2.length} agent(s) (${runningCount} running, ${queuedCount} queued)`);
|
|
14274
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14360
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14275
14361
|
if (typeof channel.sendKeyboard === "function") {
|
|
14276
14362
|
const agentButtons = [];
|
|
14277
14363
|
for (const a of agents2) {
|
|
@@ -14290,7 +14376,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14290
14376
|
const db3 = getDb();
|
|
14291
14377
|
const orch = getActiveOrchestration(db3, chatId);
|
|
14292
14378
|
if (!orch) {
|
|
14293
|
-
await channel.sendText(chatId, "<b>Task Board</b>\n\nNo active orchestration. Start a task to create one.", "html");
|
|
14379
|
+
await channel.sendText(chatId, "<b>Task Board</b>\n\nNo active orchestration. Start a task to create one.", { parseMode: "html" });
|
|
14294
14380
|
break;
|
|
14295
14381
|
}
|
|
14296
14382
|
const tasks = listTasksByOrchestration(db3, orch.id);
|
|
@@ -14325,7 +14411,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14325
14411
|
if (lines.length === 2) {
|
|
14326
14412
|
lines.push("No tasks yet.");
|
|
14327
14413
|
}
|
|
14328
|
-
await channel.sendText(chatId, lines.join("\n").trimEnd(), "html");
|
|
14414
|
+
await channel.sendText(chatId, lines.join("\n").trimEnd(), { parseMode: "html" });
|
|
14329
14415
|
if (typeof channel.sendKeyboard === "function" && tasks.length > 0) {
|
|
14330
14416
|
const taskButtons = [];
|
|
14331
14417
|
const viewable = tasks.filter((t) => t.status === "pending" || t.status === "in_progress");
|
|
@@ -14346,7 +14432,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14346
14432
|
const db4 = getDb();
|
|
14347
14433
|
const agents3 = listActiveAgents(db4);
|
|
14348
14434
|
if (agents3.length === 0) {
|
|
14349
|
-
await channel.sendText(chatId, "No active agents to stop.", "plain");
|
|
14435
|
+
await channel.sendText(chatId, "No active agents to stop.", { parseMode: "plain" });
|
|
14350
14436
|
break;
|
|
14351
14437
|
}
|
|
14352
14438
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -14374,7 +14460,7 @@ ${lines2.join("\n")}`, "html");
|
|
|
14374
14460
|
|
|
14375
14461
|
${agentLines.join("\n")}`, buttons);
|
|
14376
14462
|
} else {
|
|
14377
|
-
await channel.sendText(chatId, "Usage: /stopagent <id>\nUse first 8 chars of agent ID or full ID.", "plain");
|
|
14463
|
+
await channel.sendText(chatId, "Usage: /stopagent <id>\nUse first 8 chars of agent ID or full ID.", { parseMode: "plain" });
|
|
14378
14464
|
}
|
|
14379
14465
|
break;
|
|
14380
14466
|
}
|
|
@@ -14383,16 +14469,16 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14383
14469
|
const id = commandArgs.trim();
|
|
14384
14470
|
const match = agents2.find((a) => a.id === id || a.id.startsWith(id));
|
|
14385
14471
|
if (!match) {
|
|
14386
|
-
await channel.sendText(chatId, `No active agent found matching "${id}". Use /agents to list.`, "plain");
|
|
14472
|
+
await channel.sendText(chatId, `No active agent found matching "${id}". Use /agents to list.`, { parseMode: "plain" });
|
|
14387
14473
|
break;
|
|
14388
14474
|
}
|
|
14389
14475
|
const ok = cancelAgent(match.id);
|
|
14390
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
14476
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
14391
14477
|
break;
|
|
14392
14478
|
}
|
|
14393
14479
|
case "stopall": {
|
|
14394
14480
|
const count = cancelAllAgents(chatId);
|
|
14395
|
-
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", "plain");
|
|
14481
|
+
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", { parseMode: "plain" });
|
|
14396
14482
|
if (count > 0 && typeof channel.sendKeyboard === "function") {
|
|
14397
14483
|
await channel.sendKeyboard(chatId, "", [
|
|
14398
14484
|
[
|
|
@@ -14406,7 +14492,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14406
14492
|
case "runners": {
|
|
14407
14493
|
const runners2 = getAllRunners();
|
|
14408
14494
|
if (runners2.length === 0) {
|
|
14409
|
-
await channel.sendText(chatId, "<b>Registered Runners</b>\n\nNo runners registered.", "html");
|
|
14495
|
+
await channel.sendText(chatId, "<b>Registered Runners</b>\n\nNo runners registered.", { parseMode: "html" });
|
|
14410
14496
|
break;
|
|
14411
14497
|
}
|
|
14412
14498
|
const lines = ["<b>Registered Runners</b>", ""];
|
|
@@ -14414,7 +14500,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14414
14500
|
const specialties = r.capabilities.specialties?.join(", ") ?? "";
|
|
14415
14501
|
lines.push(`\u2022 <b>${r.id}</b> (${r.displayName}) \u2014 ${specialties}`);
|
|
14416
14502
|
}
|
|
14417
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14503
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14418
14504
|
break;
|
|
14419
14505
|
}
|
|
14420
14506
|
case "mcp":
|
|
@@ -14483,7 +14569,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14483
14569
|
} else {
|
|
14484
14570
|
lines.splice(1, 0, `<i>${connectedCount}/${totalCount} connected</i>`);
|
|
14485
14571
|
}
|
|
14486
|
-
await channel.sendText(chatId, lines.join("\n"), "html");
|
|
14572
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "html" });
|
|
14487
14573
|
break;
|
|
14488
14574
|
}
|
|
14489
14575
|
case "cron": {
|
|
@@ -14502,7 +14588,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14502
14588
|
}
|
|
14503
14589
|
const id = parseInt(cronSubArgs, 10);
|
|
14504
14590
|
const ok = cancelJob(id);
|
|
14505
|
-
await channel.sendText(chatId, ok ? `Job #${id} cancelled.` : `Job #${id} not found.`, "plain");
|
|
14591
|
+
await channel.sendText(chatId, ok ? `Job #${id} cancelled.` : `Job #${id} not found.`, { parseMode: "plain" });
|
|
14506
14592
|
break;
|
|
14507
14593
|
}
|
|
14508
14594
|
case "pause": {
|
|
@@ -14512,7 +14598,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14512
14598
|
}
|
|
14513
14599
|
const pauseId = parseInt(cronSubArgs, 10);
|
|
14514
14600
|
const paused = pauseJob(pauseId);
|
|
14515
|
-
await channel.sendText(chatId, paused ? `Job #${pauseId} paused.` : `Job #${pauseId} not found.`, "plain");
|
|
14601
|
+
await channel.sendText(chatId, paused ? `Job #${pauseId} paused.` : `Job #${pauseId} not found.`, { parseMode: "plain" });
|
|
14516
14602
|
break;
|
|
14517
14603
|
}
|
|
14518
14604
|
case "resume": {
|
|
@@ -14522,7 +14608,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14522
14608
|
}
|
|
14523
14609
|
const resumeId = parseInt(cronSubArgs, 10);
|
|
14524
14610
|
const resumed = resumeJob(resumeId);
|
|
14525
|
-
await channel.sendText(chatId, resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`, "plain");
|
|
14611
|
+
await channel.sendText(chatId, resumed ? `Job #${resumeId} resumed.` : `Job #${resumeId} not found.`, { parseMode: "plain" });
|
|
14526
14612
|
break;
|
|
14527
14613
|
}
|
|
14528
14614
|
case "run": {
|
|
@@ -14531,9 +14617,9 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14531
14617
|
return;
|
|
14532
14618
|
}
|
|
14533
14619
|
const runId = parseInt(cronSubArgs, 10);
|
|
14534
|
-
await channel.sendText(chatId, `Triggering job #${runId}...`, "plain");
|
|
14620
|
+
await channel.sendText(chatId, `Triggering job #${runId}...`, { parseMode: "plain" });
|
|
14535
14621
|
const runResult = await triggerJob(runId);
|
|
14536
|
-
await channel.sendText(chatId, runResult, "plain");
|
|
14622
|
+
await channel.sendText(chatId, runResult, { parseMode: "plain" });
|
|
14537
14623
|
break;
|
|
14538
14624
|
}
|
|
14539
14625
|
case "runs": {
|
|
@@ -14543,20 +14629,20 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14543
14629
|
} else {
|
|
14544
14630
|
const cronRuns2 = getJobRuns(void 0, 10);
|
|
14545
14631
|
if (cronRuns2.length === 0) {
|
|
14546
|
-
await channel.sendText(chatId, "No run history.", "plain");
|
|
14632
|
+
await channel.sendText(chatId, "No run history.", { parseMode: "plain" });
|
|
14547
14633
|
return;
|
|
14548
14634
|
}
|
|
14549
14635
|
const runLines = cronRuns2.map((r) => {
|
|
14550
14636
|
const dur = r.durationMs ? ` (${(r.durationMs / 1e3).toFixed(1)}s)` : "";
|
|
14551
14637
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${dur}`;
|
|
14552
14638
|
});
|
|
14553
|
-
await channel.sendText(chatId, runLines.join("\n\n"), "plain");
|
|
14639
|
+
await channel.sendText(chatId, runLines.join("\n\n"), { parseMode: "plain" });
|
|
14554
14640
|
}
|
|
14555
14641
|
break;
|
|
14556
14642
|
}
|
|
14557
14643
|
case "edit": {
|
|
14558
14644
|
if (!cronSubArgs) {
|
|
14559
|
-
await channel.sendText(chatId, "Usage: /cron edit <id>", "plain");
|
|
14645
|
+
await channel.sendText(chatId, "Usage: /cron edit <id>", { parseMode: "plain" });
|
|
14560
14646
|
return;
|
|
14561
14647
|
}
|
|
14562
14648
|
const editId = parseInt(cronSubArgs, 10);
|
|
@@ -14565,7 +14651,7 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14565
14651
|
}
|
|
14566
14652
|
case "health": {
|
|
14567
14653
|
const report = getHealthReport();
|
|
14568
|
-
await channel.sendText(chatId, formatHealthReport(report), "plain");
|
|
14654
|
+
await channel.sendText(chatId, formatHealthReport(report), { parseMode: "plain" });
|
|
14569
14655
|
break;
|
|
14570
14656
|
}
|
|
14571
14657
|
default:
|
|
@@ -14577,84 +14663,112 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14577
14663
|
const testMsg = commandArgs?.trim() || "hey";
|
|
14578
14664
|
const result = classifyIntent(testMsg, chatId);
|
|
14579
14665
|
await channel.sendText(chatId, `Intent: ${result}
|
|
14580
|
-
Message: "${testMsg}"`, "plain");
|
|
14666
|
+
Message: "${testMsg}"`, { parseMode: "plain" });
|
|
14581
14667
|
break;
|
|
14582
14668
|
}
|
|
14583
14669
|
case "evolve": {
|
|
14584
|
-
const {
|
|
14585
|
-
const
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
|
|
14670
|
+
const { getReflectionStatus: getRefStatus, getUnprocessedSignalCount: getUnprocessedSignalCount2, getPendingInsightCount: getPendingInsightCount2, getLastAnalysisTime: getLastAnalysisTime2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14671
|
+
const isActive = getRefStatus(getDb(), chatId) === "active";
|
|
14672
|
+
if (!isActive) {
|
|
14673
|
+
const text = [
|
|
14674
|
+
"Self-Learning & Evolution",
|
|
14675
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
14676
|
+
"",
|
|
14677
|
+
"Teach your assistant to improve over time.",
|
|
14678
|
+
"",
|
|
14679
|
+
"When enabled, CC-Claw watches for corrections,",
|
|
14680
|
+
"preferences, and frustration in your messages,",
|
|
14681
|
+
"then proposes changes to its personality and",
|
|
14682
|
+
"behavior files (SOUL.md, USER.md).",
|
|
14683
|
+
"",
|
|
14684
|
+
"You review and approve every change."
|
|
14685
|
+
].join("\n");
|
|
14686
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14687
|
+
const { buildEvolveOnboardingKeyboard: buildEvolveOnboardingKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14688
|
+
await channel.sendKeyboard(chatId, text, buildEvolveOnboardingKeyboard2());
|
|
14689
|
+
} else {
|
|
14690
|
+
await channel.sendText(chatId, text + "\n\nUse /evolve enable to activate.", { parseMode: "plain" });
|
|
14691
|
+
}
|
|
14692
|
+
} else {
|
|
14693
|
+
const signals = getUnprocessedSignalCount2(getDb(), chatId);
|
|
14694
|
+
const pending = getPendingInsightCount2(getDb(), chatId);
|
|
14593
14695
|
const lastTime = getLastAnalysisTime2(getDb(), chatId);
|
|
14594
|
-
let
|
|
14696
|
+
let lastText = "never";
|
|
14595
14697
|
if (lastTime) {
|
|
14596
14698
|
const diffMs = Date.now() - (/* @__PURE__ */ new Date(lastTime + "Z")).getTime();
|
|
14597
14699
|
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
|
-
}
|
|
14700
|
+
if (diffHours < 1) lastText = "< 1 hour ago";
|
|
14701
|
+
else if (diffHours < 24) lastText = `${diffHours}h ago`;
|
|
14702
|
+
else lastText = `${Math.floor(diffHours / 24)}d ago`;
|
|
14604
14703
|
}
|
|
14605
|
-
const
|
|
14606
|
-
"
|
|
14704
|
+
const dashText = [
|
|
14705
|
+
"Self-Learning & Evolution",
|
|
14607
14706
|
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
14608
14707
|
"",
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14612
|
-
`Unprocessed signals: ${signalCount}`,
|
|
14613
|
-
`Last analysis: ${lastAnalysisText}`
|
|
14708
|
+
`\u2705 Active`,
|
|
14709
|
+
`Signals: ${signals} pending \xB7 Proposals: ${pending}`,
|
|
14710
|
+
`Last analysis: ${lastText}`
|
|
14614
14711
|
].join("\n");
|
|
14615
|
-
|
|
14616
|
-
{
|
|
14617
|
-
{
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14712
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14713
|
+
const { buildEvolveMenuKeyboard: buildEvolveMenuKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14714
|
+
await channel.sendKeyboard(chatId, dashText, buildEvolveMenuKeyboard2({ pendingProposals: pending, unprocessedSignals: signals }));
|
|
14715
|
+
} else {
|
|
14716
|
+
await channel.sendText(chatId, dashText, { parseMode: "plain" });
|
|
14717
|
+
}
|
|
14718
|
+
}
|
|
14719
|
+
break;
|
|
14720
|
+
}
|
|
14721
|
+
case "reflect": {
|
|
14722
|
+
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
14723
|
+
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14724
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
14725
|
+
try {
|
|
14726
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
14727
|
+
if (insights.length === 0) {
|
|
14728
|
+
const { getReflectionStatus: getRefStatus } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14729
|
+
const isFrozen = getRefStatus(getDb(), chatId) === "frozen";
|
|
14730
|
+
if (isFrozen) {
|
|
14731
|
+
const msg2 = "No insights found. Self-learning is disabled \u2014\nenable it with /evolve so feedback signals are\ncaptured automatically between analyses.";
|
|
14732
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
14733
|
+
await channel.sendKeyboard(chatId, msg2, [[
|
|
14734
|
+
{ label: "Open /evolve", data: "evolve:menu", style: "primary" }
|
|
14735
|
+
]]);
|
|
14736
|
+
} else {
|
|
14737
|
+
await channel.sendText(chatId, msg2, { parseMode: "plain" });
|
|
14738
|
+
}
|
|
14627
14739
|
} else {
|
|
14628
|
-
|
|
14629
|
-
await channel.sendText(chatId, formatNightlySummary2(items), "plain");
|
|
14740
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
14630
14741
|
}
|
|
14631
|
-
}
|
|
14632
|
-
|
|
14742
|
+
} else {
|
|
14743
|
+
const items = insights.map((ins, i) => ({ id: i + 1, category: ins.category, insight: ins.insight }));
|
|
14744
|
+
await channel.sendText(chatId, formatNightlySummary2(items) + "\n\nUse /evolve to review and apply proposals.", { parseMode: "plain" });
|
|
14633
14745
|
}
|
|
14746
|
+
} catch (e) {
|
|
14747
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
14634
14748
|
}
|
|
14635
14749
|
break;
|
|
14636
14750
|
}
|
|
14637
14751
|
default:
|
|
14638
|
-
await channel.sendText(chatId, `Unknown command: /${command}. Type /help for available commands.`, "plain");
|
|
14752
|
+
await channel.sendText(chatId, `Unknown command: /${command}. Type /help for available commands.`, { parseMode: "plain" });
|
|
14639
14753
|
}
|
|
14640
14754
|
}
|
|
14641
14755
|
async function handleVoice(msg, channel) {
|
|
14642
14756
|
const { chatId, fileName } = msg;
|
|
14643
|
-
await channel.sendText(chatId, "Transcribing voice message...", "plain");
|
|
14757
|
+
await channel.sendText(chatId, "Transcribing voice message...", { parseMode: "plain" });
|
|
14644
14758
|
try {
|
|
14645
14759
|
const audioBuffer = await channel.downloadFile(fileName);
|
|
14646
14760
|
const transcript = await transcribeAudio(audioBuffer);
|
|
14647
14761
|
if (!transcript) {
|
|
14648
|
-
await channel.sendText(chatId, "Couldn't transcribe the voice message.", "plain");
|
|
14762
|
+
await channel.sendText(chatId, "Couldn't transcribe the voice message.", { parseMode: "plain" });
|
|
14649
14763
|
return;
|
|
14650
14764
|
}
|
|
14651
14765
|
const vBackendId = getBackend(chatId) ?? "claude";
|
|
14652
14766
|
const vLimitMsg = checkBackendLimits(vBackendId);
|
|
14653
14767
|
if (vLimitMsg) {
|
|
14654
|
-
await channel.sendText(chatId, vLimitMsg, "plain");
|
|
14768
|
+
await channel.sendText(chatId, vLimitMsg, { parseMode: "plain" });
|
|
14655
14769
|
return;
|
|
14656
14770
|
}
|
|
14657
|
-
await channel.sendText(chatId, "Thinking...", "plain");
|
|
14771
|
+
await channel.sendText(chatId, "Thinking...", { parseMode: "plain" });
|
|
14658
14772
|
const mode = getMode(chatId);
|
|
14659
14773
|
const vModel = resolveModel(chatId);
|
|
14660
14774
|
const vVerbose = getVerboseLevel(chatId);
|
|
@@ -14666,7 +14780,7 @@ async function handleVoice(msg, channel) {
|
|
|
14666
14780
|
await sendResponse(chatId, channel, voiceResponse, msg.messageId);
|
|
14667
14781
|
} catch (err) {
|
|
14668
14782
|
error("[router] Voice error:", err);
|
|
14669
|
-
await channel.sendText(chatId, `Voice processing error: ${errorMessage(err)}`, "plain");
|
|
14783
|
+
await channel.sendText(chatId, `Voice processing error: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
14670
14784
|
}
|
|
14671
14785
|
}
|
|
14672
14786
|
async function handleMedia(msg, channel) {
|
|
@@ -14674,15 +14788,15 @@ async function handleMedia(msg, channel) {
|
|
|
14674
14788
|
const mBackendId = getBackend(chatId) ?? "claude";
|
|
14675
14789
|
const mLimitMsg = checkBackendLimits(mBackendId);
|
|
14676
14790
|
if (mLimitMsg) {
|
|
14677
|
-
await channel.sendText(chatId, mLimitMsg, "plain");
|
|
14791
|
+
await channel.sendText(chatId, mLimitMsg, { parseMode: "plain" });
|
|
14678
14792
|
return;
|
|
14679
14793
|
}
|
|
14680
|
-
await channel.sendText(chatId, "Processing your file...", "plain");
|
|
14794
|
+
await channel.sendText(chatId, "Processing your file...", { parseMode: "plain" });
|
|
14681
14795
|
try {
|
|
14682
14796
|
if (msg.type === "video") {
|
|
14683
14797
|
const fileId = msg.metadata?.fileId ?? fileName;
|
|
14684
14798
|
if (!fileId) {
|
|
14685
|
-
await channel.sendText(chatId, "Could not retrieve video file ID.", "plain");
|
|
14799
|
+
await channel.sendText(chatId, "Could not retrieve video file ID.", { parseMode: "plain" });
|
|
14686
14800
|
return;
|
|
14687
14801
|
}
|
|
14688
14802
|
const videoBuffer = await channel.downloadFile(fileId);
|
|
@@ -14774,11 +14888,12 @@ ${content}
|
|
|
14774
14888
|
await sendResponse(chatId, channel, mediaResponse, msg.messageId);
|
|
14775
14889
|
} catch (err) {
|
|
14776
14890
|
error("[router] Media error:", err);
|
|
14777
|
-
await channel.sendText(chatId, `Error processing file: ${errorMessage(err)}`, "plain");
|
|
14891
|
+
await channel.sendText(chatId, `Error processing file: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
14778
14892
|
}
|
|
14779
14893
|
}
|
|
14780
14894
|
async function handleText(msg, channel) {
|
|
14781
|
-
const { chatId
|
|
14895
|
+
const { chatId } = msg;
|
|
14896
|
+
let { text } = msg;
|
|
14782
14897
|
if (hasActiveProfile(chatId)) {
|
|
14783
14898
|
await handleProfileText(chatId, text, channel);
|
|
14784
14899
|
return;
|
|
@@ -14786,7 +14901,7 @@ async function handleText(msg, channel) {
|
|
|
14786
14901
|
if (hasPendingWizard(chatId)) {
|
|
14787
14902
|
if (text.toLowerCase() === "cancel") {
|
|
14788
14903
|
cancelWizard(chatId);
|
|
14789
|
-
await channel.sendText(chatId, "Scheduling cancelled.", "plain");
|
|
14904
|
+
await channel.sendText(chatId, "Scheduling cancelled.", { parseMode: "plain" });
|
|
14790
14905
|
return;
|
|
14791
14906
|
}
|
|
14792
14907
|
if (text.toLowerCase() === "confirm") {
|
|
@@ -14796,19 +14911,39 @@ async function handleText(msg, channel) {
|
|
|
14796
14911
|
await handleWizardText(chatId, text, channel);
|
|
14797
14912
|
return;
|
|
14798
14913
|
}
|
|
14914
|
+
const discussingInsightId = activeProposalDiscussion.get(chatId);
|
|
14915
|
+
if (discussingInsightId !== void 0) {
|
|
14916
|
+
if (text.toLowerCase() === "done") {
|
|
14917
|
+
activeProposalDiscussion.delete(chatId);
|
|
14918
|
+
const { getInsightById: getInsightById2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14919
|
+
const { formatProposalCard: formatProposalCard2, buildProposalKeyboard: buildProposalKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14920
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
14921
|
+
const insight = getInsightById2(getDb2(), discussingInsightId);
|
|
14922
|
+
if (insight && insight.status === "pending") {
|
|
14923
|
+
const card = formatProposalCard2(insight);
|
|
14924
|
+
const kb = buildProposalKeyboard2(insight.id, insight.category);
|
|
14925
|
+
await channel.sendKeyboard(chatId, "Discussion complete. Updated proposal:\n\n" + card, kb);
|
|
14926
|
+
} else {
|
|
14927
|
+
await channel.sendText(chatId, "Discussion ended.", { parseMode: "plain" });
|
|
14928
|
+
}
|
|
14929
|
+
return;
|
|
14930
|
+
}
|
|
14931
|
+
await handleProposalDiscussion(chatId, discussingInsightId, text, channel);
|
|
14932
|
+
return;
|
|
14933
|
+
}
|
|
14799
14934
|
const rememberMatch = text.match(/^remember\s+(?:that\s+)?(.+)/i);
|
|
14800
14935
|
if (rememberMatch) {
|
|
14801
14936
|
const content = rememberMatch[1];
|
|
14802
14937
|
const trigger = content.split(/\s+/).slice(0, 3).join(" ");
|
|
14803
14938
|
saveMemoryWithEmbedding(trigger, content, "semantic");
|
|
14804
|
-
await channel.sendText(chatId, "Got it, I'll remember that.", "plain");
|
|
14939
|
+
await channel.sendText(chatId, "Got it, I'll remember that.", { parseMode: "plain" });
|
|
14805
14940
|
return;
|
|
14806
14941
|
}
|
|
14807
14942
|
const model2 = resolveModel(chatId);
|
|
14808
14943
|
const backendId = getBackend(chatId) ?? "claude";
|
|
14809
14944
|
const limitMsg = checkBackendLimits(backendId);
|
|
14810
14945
|
if (limitMsg) {
|
|
14811
|
-
await channel.sendText(chatId, limitMsg, "plain");
|
|
14946
|
+
await channel.sendText(chatId, limitMsg, { parseMode: "plain" });
|
|
14812
14947
|
return;
|
|
14813
14948
|
}
|
|
14814
14949
|
let intent = classifyIntent(text, chatId);
|
|
@@ -14830,18 +14965,32 @@ async function handleText(msg, channel) {
|
|
|
14830
14965
|
const lastWarn = dashboardClawWarnings.get(chatId) ?? 0;
|
|
14831
14966
|
if (Date.now() - lastWarn > 3e5) {
|
|
14832
14967
|
dashboardClawWarnings.set(chatId, Date.now());
|
|
14833
|
-
await channel.sendText(chatId, "\u26A0\uFE0F CC-Claw orchestration requires DASHBOARD_ENABLED=1. Using native agents.", "plain");
|
|
14968
|
+
await channel.sendText(chatId, "\u26A0\uFE0F CC-Claw orchestration requires DASHBOARD_ENABLED=1. Using native agents.", { parseMode: "plain" });
|
|
14834
14969
|
}
|
|
14835
14970
|
effectiveAgentMode = "native";
|
|
14836
14971
|
}
|
|
14972
|
+
const { isSideQuest: hasSqPrefix, cleanText: sqCleanText } = parseSideQuestPrefix(text);
|
|
14973
|
+
if (hasSqPrefix && isChatBusy(chatId)) {
|
|
14974
|
+
const sqMsg = { ...msg, text: sqCleanText };
|
|
14975
|
+
handleSideQuest(chatId, sqMsg, channel).catch(
|
|
14976
|
+
(err) => error(`[router] Side quest error for ${chatId}:`, err)
|
|
14977
|
+
);
|
|
14978
|
+
return;
|
|
14979
|
+
}
|
|
14980
|
+
if (hasSqPrefix) {
|
|
14981
|
+
text = sqCleanText;
|
|
14982
|
+
}
|
|
14837
14983
|
if (isChatBusy(chatId) && !bypassBusyCheck.delete(chatId)) {
|
|
14838
14984
|
if (typeof channel.sendKeyboard === "function") {
|
|
14839
14985
|
pendingInterrupts.set(chatId, { msg, channel });
|
|
14840
|
-
await channel.sendKeyboard(chatId, "\u23F3 Agent is working on a request
|
|
14986
|
+
await channel.sendKeyboard(chatId, "\u23F3 Agent is working on a request. You can queue, interrupt, or start a parallel task.", [
|
|
14841
14987
|
[
|
|
14842
|
-
{ label: "\u{1F4E5} Queue
|
|
14988
|
+
{ label: "\u{1F4E5} Queue", data: `interrupt:queue:${chatId}` },
|
|
14843
14989
|
{ label: "\u26A1 Send now", data: `interrupt:now:${chatId}` }
|
|
14844
14990
|
],
|
|
14991
|
+
[
|
|
14992
|
+
{ label: "\u{1F5FA} Side quest \u2014 run in parallel", data: `interrupt:sidequest:${chatId}` }
|
|
14993
|
+
],
|
|
14845
14994
|
[
|
|
14846
14995
|
{ label: "\u{1F5D1} Don't send", data: `interrupt:discard:${chatId}` }
|
|
14847
14996
|
]
|
|
@@ -14897,7 +15046,7 @@ async function handleText(msg, channel) {
|
|
|
14897
15046
|
const toSlot = slots.find((s) => (s.label || `slot-${s.id}`) === to);
|
|
14898
15047
|
const fromIcon = fromSlot?.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
14899
15048
|
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(() => {
|
|
15049
|
+
channel.sendText(cid, `\u26A0\uFE0F Quota reached on ${fromIcon} ${from} \u2014 switched to ${toIcon} ${to}. Context saved.`, { parseMode: "plain" }).catch(() => {
|
|
14901
15050
|
});
|
|
14902
15051
|
}
|
|
14903
15052
|
});
|
|
@@ -14933,6 +15082,9 @@ async function handleText(msg, channel) {
|
|
|
14933
15082
|
return;
|
|
14934
15083
|
}
|
|
14935
15084
|
if (await handleResponseExhaustion(responseText, chatId, msg, channel)) return;
|
|
15085
|
+
if (activeSideQuests.has(chatId) && responseText && !responseText.startsWith("(No response")) {
|
|
15086
|
+
responseText = "\u{1F4CB} <b>Main task</b>\n\n" + responseText;
|
|
15087
|
+
}
|
|
14936
15088
|
responseText = ensureReaction(responseText, cleanText || text);
|
|
14937
15089
|
await sendResponse(chatId, channel, responseText, msg.messageId);
|
|
14938
15090
|
try {
|
|
@@ -14959,7 +15111,7 @@ async function handleText(msg, channel) {
|
|
|
14959
15111
|
];
|
|
14960
15112
|
await channel.sendKeyboard(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}). Switch backend?`, rows);
|
|
14961
15113
|
} else {
|
|
14962
|
-
await channel.sendText(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}).`, "plain");
|
|
15114
|
+
await channel.sendText(chatId, `\u26A0\uFE0F No eligible slots for rotation mode (${modeLabel}).`, { parseMode: "plain" });
|
|
14963
15115
|
}
|
|
14964
15116
|
return;
|
|
14965
15117
|
} else if (errMsg.includes(GEMINI_ALL_SLOTS_COOLDOWN_MSG)) {
|
|
@@ -14971,7 +15123,7 @@ async function handleText(msg, channel) {
|
|
|
14971
15123
|
];
|
|
14972
15124
|
await channel.sendKeyboard(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}. Switch backend?`, rows);
|
|
14973
15125
|
} else {
|
|
14974
|
-
await channel.sendText(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}.`, "plain");
|
|
15126
|
+
await channel.sendText(chatId, `\u26A0\uFE0F All eligible slots in cooldown. Next available in ~${timeLeft}.`, { parseMode: "plain" });
|
|
14975
15127
|
}
|
|
14976
15128
|
return;
|
|
14977
15129
|
}
|
|
@@ -14980,7 +15132,7 @@ async function handleText(msg, channel) {
|
|
|
14980
15132
|
if (await handleResponseExhaustion(errMsg, chatId, msg, channel)) return;
|
|
14981
15133
|
}
|
|
14982
15134
|
const userMsg = diagnoseAgentError(errMsg, chatId);
|
|
14983
|
-
await channel.sendText(chatId, userMsg, "plain");
|
|
15135
|
+
await channel.sendText(chatId, userMsg, { parseMode: "plain" });
|
|
14984
15136
|
} finally {
|
|
14985
15137
|
typingActive = false;
|
|
14986
15138
|
const pending = pendingInterrupts.get(chatId);
|
|
@@ -15006,6 +15158,140 @@ After installing, restart the service: cc-claw service restart`;
|
|
|
15006
15158
|
}
|
|
15007
15159
|
return `Error: ${msg}`;
|
|
15008
15160
|
}
|
|
15161
|
+
async function handleProposalDiscussion(chatId, insightId, userQuestion, channel) {
|
|
15162
|
+
const { getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15163
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
15164
|
+
const insight = getInsightById2(getDb2(), insightId);
|
|
15165
|
+
if (!insight) {
|
|
15166
|
+
activeProposalDiscussion.delete(chatId);
|
|
15167
|
+
await channel.sendText(chatId, "Proposal not found. Discussion ended.", { parseMode: "plain" });
|
|
15168
|
+
return;
|
|
15169
|
+
}
|
|
15170
|
+
const prompt = [
|
|
15171
|
+
`You are reviewing a self-learning proposal with the user. They want to discuss it before deciding whether to apply, modify, or reject it.`,
|
|
15172
|
+
``,
|
|
15173
|
+
`Current proposal:`,
|
|
15174
|
+
`- Category: ${insight.category}`,
|
|
15175
|
+
`- Insight: ${insight.insight}`,
|
|
15176
|
+
`- Why: ${insight.why ?? "not specified"}`,
|
|
15177
|
+
`- Target file: ${insight.targetFile ?? "not specified"}`,
|
|
15178
|
+
`- Proposed action: ${insight.proposedAction ?? "not specified"}`,
|
|
15179
|
+
`- Proposed diff: ${insight.proposedDiff ?? "none"}`,
|
|
15180
|
+
`- Confidence: ${Math.round(insight.confidence * 100)}%`,
|
|
15181
|
+
``,
|
|
15182
|
+
`The user asks: "${userQuestion}"`,
|
|
15183
|
+
``,
|
|
15184
|
+
`Answer their question honestly. If they suggest retargeting to a different file or modifying the proposal, agree if it makes sense and output one of these markers:`,
|
|
15185
|
+
`- [RETARGET:filepath] \u2014 to change the target file (e.g., [RETARGET:skills/newsroom/SKILL.md])`,
|
|
15186
|
+
`- [REVISE_DIFF:new diff text] \u2014 to update the proposed change`,
|
|
15187
|
+
`- [REVISE_ACTION:action] \u2014 to change the action type (append/replace/etc.)`,
|
|
15188
|
+
``,
|
|
15189
|
+
`Only output markers when the user explicitly asks for a change. Otherwise just discuss.`,
|
|
15190
|
+
`Keep responses concise \u2014 this is a quick review conversation, not an essay.`
|
|
15191
|
+
].join("\n");
|
|
15192
|
+
try {
|
|
15193
|
+
await channel.sendTyping?.(chatId);
|
|
15194
|
+
const response = await askAgent(chatId, prompt, {
|
|
15195
|
+
bootstrapTier: "chat",
|
|
15196
|
+
maxTurns: 1,
|
|
15197
|
+
timeoutMs: 6e4
|
|
15198
|
+
});
|
|
15199
|
+
const responseText = response.text ?? "";
|
|
15200
|
+
const retargetMatch = responseText.match(/\[RETARGET:([^\]]+)\]/);
|
|
15201
|
+
const reviseDiffMatch = responseText.match(/\[REVISE_DIFF:([^\]]+)\]/);
|
|
15202
|
+
const reviseActionMatch = responseText.match(/\[REVISE_ACTION:([^\]]+)\]/);
|
|
15203
|
+
if (retargetMatch || reviseDiffMatch || reviseActionMatch) {
|
|
15204
|
+
const newTarget = retargetMatch?.[1]?.trim() ?? insight.targetFile ?? "";
|
|
15205
|
+
const newDiff = reviseDiffMatch?.[1]?.trim() ?? insight.proposedDiff ?? null;
|
|
15206
|
+
const newAction = reviseActionMatch?.[1]?.trim() ?? insight.proposedAction ?? null;
|
|
15207
|
+
updateInsightProposal2(getDb2(), insightId, newTarget, newDiff, newAction);
|
|
15208
|
+
}
|
|
15209
|
+
const cleanText = responseText.replace(/\[RETARGET:[^\]]+\]/g, "").replace(/\[REVISE_DIFF:[^\]]+\]/g, "").replace(/\[REVISE_ACTION:[^\]]+\]/g, "").trim();
|
|
15210
|
+
if (cleanText) {
|
|
15211
|
+
await channel.sendText(chatId, cleanText);
|
|
15212
|
+
}
|
|
15213
|
+
await channel.sendKeyboard(chatId, "Continue discussing, or type 'done' to finish.", [
|
|
15214
|
+
[{ label: "Done \u2014 show updated proposal", data: `evolve:discuss-done:${insightId}` }]
|
|
15215
|
+
]);
|
|
15216
|
+
} catch (err) {
|
|
15217
|
+
await channel.sendText(chatId, `Discussion error: ${err.message}`, { parseMode: "plain" });
|
|
15218
|
+
}
|
|
15219
|
+
}
|
|
15220
|
+
async function handleSideQuest(parentChatId, msg, channel) {
|
|
15221
|
+
const sqId = `sq:${parentChatId}:${randomUUID3()}`;
|
|
15222
|
+
const active = activeSideQuests.get(parentChatId) ?? /* @__PURE__ */ new Set();
|
|
15223
|
+
if (active.size >= MAX_SIDE_QUESTS) {
|
|
15224
|
+
await channel.sendText(parentChatId, `Side quest slots full (${active.size} running). Queue this or wait for one to finish.`, { parseMode: "plain" });
|
|
15225
|
+
return;
|
|
15226
|
+
}
|
|
15227
|
+
active.add(sqId);
|
|
15228
|
+
activeSideQuests.set(parentChatId, active);
|
|
15229
|
+
await channel.sendKeyboard?.(parentChatId, "\u{1F5FA} Starting side quest\u2026", [
|
|
15230
|
+
[{ label: "\u274C Cancel", data: `sq:cancel:${sqId}` }]
|
|
15231
|
+
]);
|
|
15232
|
+
const startTime = Date.now();
|
|
15233
|
+
let typingActive = true;
|
|
15234
|
+
const typingLoop = async () => {
|
|
15235
|
+
while (typingActive) {
|
|
15236
|
+
try {
|
|
15237
|
+
await channel.sendTyping?.(parentChatId);
|
|
15238
|
+
} catch {
|
|
15239
|
+
}
|
|
15240
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
15241
|
+
}
|
|
15242
|
+
};
|
|
15243
|
+
typingLoop().catch(() => {
|
|
15244
|
+
});
|
|
15245
|
+
try {
|
|
15246
|
+
const backend2 = getBackend(parentChatId);
|
|
15247
|
+
const model2 = getModel(parentChatId);
|
|
15248
|
+
const permMode = getMode(parentChatId);
|
|
15249
|
+
const response = await askAgent(sqId, msg.text ?? "", {
|
|
15250
|
+
cwd: getCwd(parentChatId) ?? void 0,
|
|
15251
|
+
model: model2 ?? void 0,
|
|
15252
|
+
permMode,
|
|
15253
|
+
backend: backend2 ?? void 0,
|
|
15254
|
+
settingsSourceChatId: parentChatId,
|
|
15255
|
+
agentMode: "native",
|
|
15256
|
+
maxTurns: 10,
|
|
15257
|
+
timeoutMs: 3e5,
|
|
15258
|
+
bootstrapTier: "full"
|
|
15259
|
+
});
|
|
15260
|
+
typingActive = false;
|
|
15261
|
+
const userText = msg.text ?? "";
|
|
15262
|
+
const truncated = userText.length > 60 ? userText.slice(0, 57) + "\u2026" : userText;
|
|
15263
|
+
const header2 = `\u{1F5FA} <b>Side quest: "${truncated}"</b>
|
|
15264
|
+
|
|
15265
|
+
`;
|
|
15266
|
+
const responseText = header2 + (response.text ?? "");
|
|
15267
|
+
await sendResponse(parentChatId, channel, responseText, msg.messageId, typeof msg.messageId === "string" ? parseInt(msg.messageId) : void 0);
|
|
15268
|
+
const adapterForLog = backend2 ? getAdapter(backend2) : getAdapterForChat(parentChatId);
|
|
15269
|
+
appendToLog(parentChatId, `[side quest] ${userText}`, `[side quest] ${response.text ?? ""}`, adapterForLog.id, model2 ?? null, null);
|
|
15270
|
+
if (response.usage) {
|
|
15271
|
+
addUsage(parentChatId, response.usage.input, response.usage.output, response.usage.cacheRead, model2 ?? void 0, backend2 ?? void 0);
|
|
15272
|
+
}
|
|
15273
|
+
try {
|
|
15274
|
+
const { detectAndLogSignals: detectAndLogSignals2 } = await Promise.resolve().then(() => (init_detect(), detect_exports));
|
|
15275
|
+
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(parentChatId);
|
|
15276
|
+
detectAndLogSignals2(parentChatId, userText, response.text ?? "", {
|
|
15277
|
+
backendId: adapter.id,
|
|
15278
|
+
model: model2 ?? adapter.defaultModel
|
|
15279
|
+
});
|
|
15280
|
+
} catch {
|
|
15281
|
+
}
|
|
15282
|
+
} catch (err) {
|
|
15283
|
+
typingActive = false;
|
|
15284
|
+
await channel.sendText(parentChatId, `\u{1F5FA} Side quest failed: ${err.message}`, { parseMode: "plain" });
|
|
15285
|
+
} finally {
|
|
15286
|
+
typingActive = false;
|
|
15287
|
+
const activeSet = activeSideQuests.get(parentChatId);
|
|
15288
|
+
if (activeSet) {
|
|
15289
|
+
activeSet.delete(sqId);
|
|
15290
|
+
if (activeSet.size === 0) activeSideQuests.delete(parentChatId);
|
|
15291
|
+
}
|
|
15292
|
+
clearSession(sqId);
|
|
15293
|
+
}
|
|
15294
|
+
}
|
|
15009
15295
|
function formatToolStart(toolName, input, level) {
|
|
15010
15296
|
if (level === "normal") {
|
|
15011
15297
|
const path = input.file_path ?? input.path ?? input.file ?? "";
|
|
@@ -15078,11 +15364,11 @@ function makeToolActionCallback(chatId, channel, level) {
|
|
|
15078
15364
|
return async (toolName, input, result) => {
|
|
15079
15365
|
if (result === void 0) {
|
|
15080
15366
|
const msg = formatToolStart(toolName, input, level);
|
|
15081
|
-
await channel.sendText(chatId, msg, "plain").catch(() => {
|
|
15367
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" }).catch(() => {
|
|
15082
15368
|
});
|
|
15083
15369
|
} else if (level === "verbose") {
|
|
15084
15370
|
const msg = formatToolResult(toolName, result);
|
|
15085
|
-
if (msg) await channel.sendText(chatId, msg, "plain").catch(() => {
|
|
15371
|
+
if (msg) await channel.sendText(chatId, msg, { parseMode: "plain" }).catch(() => {
|
|
15086
15372
|
});
|
|
15087
15373
|
}
|
|
15088
15374
|
};
|
|
@@ -15133,11 +15419,11 @@ async function processImageGenerations(chatId, channel, text) {
|
|
|
15133
15419
|
const name = result.filePath.split("/").pop() ?? "image.png";
|
|
15134
15420
|
await channel.sendFile(chatId, file, name);
|
|
15135
15421
|
if (result.text) {
|
|
15136
|
-
await channel.sendText(chatId, result.text, "plain");
|
|
15422
|
+
await channel.sendText(chatId, result.text, { parseMode: "plain" });
|
|
15137
15423
|
}
|
|
15138
15424
|
} catch (err) {
|
|
15139
15425
|
error(`[router] Image generation failed for "${prompt.slice(0, 50)}":`, err);
|
|
15140
|
-
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, "plain");
|
|
15426
|
+
await channel.sendText(chatId, `Image generation failed: ${errorMessage(err)}`, { parseMode: "plain" });
|
|
15141
15427
|
}
|
|
15142
15428
|
}
|
|
15143
15429
|
return text.replace(pattern, "").trim();
|
|
@@ -15164,7 +15450,7 @@ async function processReaction(chatId, channel, text, messageId) {
|
|
|
15164
15450
|
}
|
|
15165
15451
|
return text.replace(/\[REACT:(.+?)\]/g, "").trim();
|
|
15166
15452
|
}
|
|
15167
|
-
async function sendResponse(chatId, channel, text, messageId) {
|
|
15453
|
+
async function sendResponse(chatId, channel, text, messageId, replyToMessageId) {
|
|
15168
15454
|
text = await processReaction(chatId, channel, text, messageId);
|
|
15169
15455
|
const { cleanText: afterUpdates, updates } = extractUserUpdates(text);
|
|
15170
15456
|
for (const { key, value } of updates) {
|
|
@@ -15209,14 +15495,14 @@ async function sendResponse(chatId, channel, text, messageId) {
|
|
|
15209
15495
|
error("[router] TTS failed, falling back to text:", err);
|
|
15210
15496
|
}
|
|
15211
15497
|
}
|
|
15212
|
-
await channel.sendText(chatId, cleanText);
|
|
15498
|
+
await channel.sendText(chatId, cleanText, replyToMessageId ? { replyToMessageId } : void 0);
|
|
15213
15499
|
}
|
|
15214
15500
|
function isImageExt(ext) {
|
|
15215
15501
|
return ["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"].includes(ext);
|
|
15216
15502
|
}
|
|
15217
15503
|
async function sendVoiceConfigKeyboard(chatId, channel) {
|
|
15218
15504
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15219
|
-
await channel.sendText(chatId, "Voice configuration requires an interactive channel (Telegram).", "plain");
|
|
15505
|
+
await channel.sendText(chatId, "Voice configuration requires an interactive channel (Telegram).", { parseMode: "plain" });
|
|
15220
15506
|
return;
|
|
15221
15507
|
}
|
|
15222
15508
|
const config2 = getVoiceConfig(chatId);
|
|
@@ -15282,7 +15568,7 @@ async function sendBackendSwitchConfirmation(chatId, target, channel) {
|
|
|
15282
15568
|
const current = getBackend(chatId);
|
|
15283
15569
|
const targetAdapter = getAdapter(target);
|
|
15284
15570
|
if (current === target) {
|
|
15285
|
-
await channel.sendText(chatId, `Already using ${targetAdapter.displayName}.`, "plain");
|
|
15571
|
+
await channel.sendText(chatId, `Already using ${targetAdapter.displayName}.`, { parseMode: "plain" });
|
|
15286
15572
|
return;
|
|
15287
15573
|
}
|
|
15288
15574
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -15306,7 +15592,7 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15306
15592
|
const targetAdapter = getAdapter(backendId);
|
|
15307
15593
|
const pairCount = getMessagePairCount(chatId);
|
|
15308
15594
|
if (pairCount >= 2) {
|
|
15309
|
-
await channel.sendText(chatId, `\u23F3 Saving context...`, "plain");
|
|
15595
|
+
await channel.sendText(chatId, `\u23F3 Saving context...`, { parseMode: "plain" });
|
|
15310
15596
|
}
|
|
15311
15597
|
const summarized = await summarizeWithFallbackChain(chatId, backendId);
|
|
15312
15598
|
const bridge = buildContextBridge(chatId);
|
|
@@ -15314,9 +15600,9 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15314
15600
|
setPendingContextBridge(chatId, bridge);
|
|
15315
15601
|
}
|
|
15316
15602
|
if (summarized) {
|
|
15317
|
-
await channel.sendText(chatId, "\u{1F4BE} Context saved \u2014 session summarized to memory.", "plain");
|
|
15603
|
+
await channel.sendText(chatId, "\u{1F4BE} Context saved \u2014 session summarized to memory.", { parseMode: "plain" });
|
|
15318
15604
|
} else if (bridge) {
|
|
15319
|
-
await channel.sendText(chatId, "\u{1F4AC} Context preserved.", "plain");
|
|
15605
|
+
await channel.sendText(chatId, "\u{1F4AC} Context preserved.", { parseMode: "plain" });
|
|
15320
15606
|
}
|
|
15321
15607
|
clearSession(chatId);
|
|
15322
15608
|
clearModel(chatId);
|
|
@@ -15324,7 +15610,7 @@ async function doBackendSwitch(chatId, backendId, channel) {
|
|
|
15324
15610
|
clearChatGeminiSlot(chatId);
|
|
15325
15611
|
setBackend(chatId, backendId);
|
|
15326
15612
|
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");
|
|
15613
|
+
await channel.sendText(chatId, `\u2705 Switched to ${targetAdapter.displayName}. Ready!`, { parseMode: "plain" });
|
|
15328
15614
|
}
|
|
15329
15615
|
async function sendHistoryView(chatId, channel, filter) {
|
|
15330
15616
|
const limit = filter.limit ?? 10;
|
|
@@ -15341,7 +15627,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15341
15627
|
}
|
|
15342
15628
|
const userMsgs = rows.filter((r) => r.role === "user").slice(0, limit);
|
|
15343
15629
|
if (userMsgs.length === 0) {
|
|
15344
|
-
await channel.sendText(chatId, "No conversation history found.", "plain");
|
|
15630
|
+
await channel.sendText(chatId, "No conversation history found.", { parseMode: "plain" });
|
|
15345
15631
|
return;
|
|
15346
15632
|
}
|
|
15347
15633
|
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 +15636,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15350
15636
|
const preview = row.content.slice(0, 80) + (row.content.length > 80 ? "\u2026" : "");
|
|
15351
15637
|
lines.push(`[${row.backend ?? "?"} \xB7 ${date}] ${preview}`);
|
|
15352
15638
|
}
|
|
15353
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
15639
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
15354
15640
|
const filterRow = [
|
|
15355
15641
|
{ label: "Show More (25)", data: "hist:recent:25" },
|
|
15356
15642
|
{ label: "Today", data: "hist:today" },
|
|
@@ -15366,7 +15652,7 @@ async function sendHistoryView(chatId, channel, filter) {
|
|
|
15366
15652
|
async function sendMemoryPage(chatId, channel, page) {
|
|
15367
15653
|
const memories = listMemories();
|
|
15368
15654
|
if (memories.length === 0) {
|
|
15369
|
-
await channel.sendText(chatId, "No memories stored yet.", "plain");
|
|
15655
|
+
await channel.sendText(chatId, "No memories stored yet.", { parseMode: "plain" });
|
|
15370
15656
|
return;
|
|
15371
15657
|
}
|
|
15372
15658
|
const pageSize = 10;
|
|
@@ -15442,7 +15728,7 @@ async function sendHeartbeatKeyboard(chatId, channel) {
|
|
|
15442
15728
|
async function sendForgetPicker(chatId, channel, page) {
|
|
15443
15729
|
const memories = listMemories();
|
|
15444
15730
|
if (memories.length === 0) {
|
|
15445
|
-
await channel.sendText(chatId, "No memories to forget.", "plain");
|
|
15731
|
+
await channel.sendText(chatId, "No memories to forget.", { parseMode: "plain" });
|
|
15446
15732
|
return;
|
|
15447
15733
|
}
|
|
15448
15734
|
const { text, buttons } = buildPaginatedKeyboard({
|
|
@@ -15478,7 +15764,7 @@ function getJobStatusLabel(job) {
|
|
|
15478
15764
|
async function sendJobsBoard(chatId, channel, page) {
|
|
15479
15765
|
const jobs = listJobs();
|
|
15480
15766
|
if (jobs.length === 0) {
|
|
15481
|
-
await channel.sendText(chatId, "No scheduled jobs.\n\nCreate one: /schedule <description>", "plain");
|
|
15767
|
+
await channel.sendText(chatId, "No scheduled jobs.\n\nCreate one: /schedule <description>", { parseMode: "plain" });
|
|
15482
15768
|
return;
|
|
15483
15769
|
}
|
|
15484
15770
|
if (typeof channel.sendKeyboard !== "function") {
|
|
@@ -15489,7 +15775,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15489
15775
|
return `#${j.id} [${status}] ${schedule2}${tz}
|
|
15490
15776
|
${j.description}`;
|
|
15491
15777
|
});
|
|
15492
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
15778
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
15493
15779
|
return;
|
|
15494
15780
|
}
|
|
15495
15781
|
const headerLines = [];
|
|
@@ -15534,7 +15820,7 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15534
15820
|
[{ label: "Refresh List", data: "job:back" }]
|
|
15535
15821
|
]);
|
|
15536
15822
|
} else {
|
|
15537
|
-
await channel.sendText(chatId, "Job not found.", "plain");
|
|
15823
|
+
await channel.sendText(chatId, "Job not found.", { parseMode: "plain" });
|
|
15538
15824
|
}
|
|
15539
15825
|
return;
|
|
15540
15826
|
}
|
|
@@ -15560,7 +15846,7 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15560
15846
|
];
|
|
15561
15847
|
const text = lines.join("\n");
|
|
15562
15848
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15563
|
-
await channel.sendText(chatId, text, "plain");
|
|
15849
|
+
await channel.sendText(chatId, text, { parseMode: "plain" });
|
|
15564
15850
|
return;
|
|
15565
15851
|
}
|
|
15566
15852
|
const actionRow1 = [
|
|
@@ -15590,7 +15876,7 @@ async function sendJobRunsView(chatId, jobId, channel, page) {
|
|
|
15590
15876
|
[{ label: "\u2190 Back to Job", data: `job:view:${jobId}` }]
|
|
15591
15877
|
]);
|
|
15592
15878
|
} else {
|
|
15593
|
-
await channel.sendText(chatId, msg, "plain");
|
|
15879
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
15594
15880
|
}
|
|
15595
15881
|
return;
|
|
15596
15882
|
}
|
|
@@ -15601,7 +15887,7 @@ async function sendJobRunsView(chatId, jobId, channel, page) {
|
|
|
15601
15887
|
Error: ${r.error.slice(0, 100)}` : "";
|
|
15602
15888
|
return `#${r.jobId} [${r.status}] ${formatLocalDateTime(r.startedAt)}${duration}${error3}`;
|
|
15603
15889
|
});
|
|
15604
|
-
await channel.sendText(chatId, lines.join("\n\n"), "plain");
|
|
15890
|
+
await channel.sendText(chatId, lines.join("\n\n"), { parseMode: "plain" });
|
|
15605
15891
|
return;
|
|
15606
15892
|
}
|
|
15607
15893
|
const statusEmoji = {
|
|
@@ -15648,11 +15934,11 @@ async function sendJobPicker(chatId, channel, action) {
|
|
|
15648
15934
|
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
15935
|
if (jobs.length === 0) {
|
|
15650
15936
|
const msg = action === "resume" ? "No paused jobs." : action === "pause" ? "No active jobs to pause." : "No active jobs.";
|
|
15651
|
-
await channel.sendText(chatId, msg, "plain");
|
|
15937
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
15652
15938
|
return;
|
|
15653
15939
|
}
|
|
15654
15940
|
if (typeof channel.sendKeyboard !== "function") {
|
|
15655
|
-
await channel.sendText(chatId, `Usage: /${action} <job-id>`, "plain");
|
|
15941
|
+
await channel.sendText(chatId, `Usage: /${action} <job-id>`, { parseMode: "plain" });
|
|
15656
15942
|
return;
|
|
15657
15943
|
}
|
|
15658
15944
|
const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
|
|
@@ -15723,7 +16009,7 @@ async function handleCallback(chatId, data, channel) {
|
|
|
15723
16009
|
const previous = getBackend(chatId);
|
|
15724
16010
|
if (chosen === previous) {
|
|
15725
16011
|
const adapter = getAdapter(chosen);
|
|
15726
|
-
await channel.sendText(chatId, `Already using ${adapter.displayName}.`, "plain");
|
|
16012
|
+
await channel.sendText(chatId, `Already using ${adapter.displayName}.`, { parseMode: "plain" });
|
|
15727
16013
|
return;
|
|
15728
16014
|
}
|
|
15729
16015
|
await sendBackendSwitchConfirmation(chatId, chosen, channel);
|
|
@@ -15737,14 +16023,14 @@ async function handleCallback(chatId, data, channel) {
|
|
|
15737
16023
|
if (!getAllBackendIds().includes(chosen)) return;
|
|
15738
16024
|
await doBackendSwitch(chatId, chosen, channel);
|
|
15739
16025
|
} else if (data.startsWith("backend_cancel:") || data === "backend_cancel") {
|
|
15740
|
-
await channel.sendText(chatId, "Switch cancelled.", "plain");
|
|
16026
|
+
await channel.sendText(chatId, "Switch cancelled.", { parseMode: "plain" });
|
|
15741
16027
|
} else if (data.startsWith("model:")) {
|
|
15742
16028
|
const chosen = data.slice(6);
|
|
15743
16029
|
let adapter;
|
|
15744
16030
|
try {
|
|
15745
16031
|
adapter = getAdapterForChat(chatId);
|
|
15746
16032
|
} catch {
|
|
15747
|
-
await channel.sendText(chatId, "No backend set. Use /backend first.", "plain");
|
|
16033
|
+
await channel.sendText(chatId, "No backend set. Use /backend first.", { parseMode: "plain" });
|
|
15748
16034
|
return;
|
|
15749
16035
|
}
|
|
15750
16036
|
const modelInfo = adapter.availableModels[chosen];
|
|
@@ -15766,30 +16052,30 @@ Select thinking/effort level:`,
|
|
|
15766
16052
|
thinkingButtons
|
|
15767
16053
|
);
|
|
15768
16054
|
} else {
|
|
15769
|
-
await channel.sendText(chatId, `Model set to ${modelInfo.label}. Session continues.`, "plain");
|
|
16055
|
+
await channel.sendText(chatId, `Model set to ${modelInfo.label}. Session continues.`, { parseMode: "plain" });
|
|
15770
16056
|
}
|
|
15771
16057
|
} else {
|
|
15772
|
-
await channel.sendText(chatId, `Model switched to ${modelInfo.label}. Session continues.`, "plain");
|
|
16058
|
+
await channel.sendText(chatId, `Model switched to ${modelInfo.label}. Session continues.`, { parseMode: "plain" });
|
|
15773
16059
|
}
|
|
15774
16060
|
} else if (data.startsWith("thinking:")) {
|
|
15775
16061
|
const level = data.slice(9);
|
|
15776
16062
|
setThinkingLevel(chatId, level);
|
|
15777
16063
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Thinking level set to ${level}`, detail: { field: "thinking", value: level } });
|
|
15778
16064
|
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");
|
|
16065
|
+
await channel.sendText(chatId, `Thinking level set to: ${label2}`, { parseMode: "plain" });
|
|
15780
16066
|
} else if (data.startsWith("summarizer:")) {
|
|
15781
16067
|
const rest = data.slice(11);
|
|
15782
16068
|
if (rest === "auto") {
|
|
15783
16069
|
clearSummarizer(chatId);
|
|
15784
|
-
await channel.sendText(chatId, "Summarizer set to auto (uses active backend).", "plain");
|
|
16070
|
+
await channel.sendText(chatId, "Summarizer set to auto (uses active backend).", { parseMode: "plain" });
|
|
15785
16071
|
} else if (rest === "off") {
|
|
15786
16072
|
setSummarizer(chatId, "off", null);
|
|
15787
|
-
await channel.sendText(chatId, "Session summarization disabled.", "plain");
|
|
16073
|
+
await channel.sendText(chatId, "Session summarization disabled.", { parseMode: "plain" });
|
|
15788
16074
|
} else {
|
|
15789
16075
|
const [bk, ...modelParts] = rest.split(":");
|
|
15790
16076
|
const mdl = modelParts.join(":") || null;
|
|
15791
16077
|
setSummarizer(chatId, bk, mdl);
|
|
15792
|
-
await channel.sendText(chatId, `Summarizer pinned to ${bk}:${mdl ?? "default"}.`, "plain");
|
|
16078
|
+
await channel.sendText(chatId, `Summarizer pinned to ${bk}:${mdl ?? "default"}.`, { parseMode: "plain" });
|
|
15793
16079
|
}
|
|
15794
16080
|
} else if (data.startsWith("perms:")) {
|
|
15795
16081
|
let chosen = data.slice(6);
|
|
@@ -15797,7 +16083,7 @@ Select thinking/effort level:`,
|
|
|
15797
16083
|
if (!PERM_MODES[chosen]) return;
|
|
15798
16084
|
const previous = getMode(chatId);
|
|
15799
16085
|
if (chosen === previous) {
|
|
15800
|
-
await channel.sendText(chatId, `Already in ${chosen} mode.`, "plain");
|
|
16086
|
+
await channel.sendText(chatId, `Already in ${chosen} mode.`, { parseMode: "plain" });
|
|
15801
16087
|
return;
|
|
15802
16088
|
}
|
|
15803
16089
|
setMode(chatId, chosen);
|
|
@@ -15806,14 +16092,14 @@ Select thinking/effort level:`,
|
|
|
15806
16092
|
chatId,
|
|
15807
16093
|
`Permission mode: ${chosen}
|
|
15808
16094
|
${PERM_MODES[chosen]}`,
|
|
15809
|
-
"plain"
|
|
16095
|
+
{ parseMode: "plain" }
|
|
15810
16096
|
);
|
|
15811
16097
|
} else if (data.startsWith("perm:escalate:")) {
|
|
15812
16098
|
const targetMode = data.slice(14);
|
|
15813
16099
|
if (!PERM_MODES[targetMode]) return;
|
|
15814
16100
|
setMode(chatId, targetMode);
|
|
15815
16101
|
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");
|
|
16102
|
+
await channel.sendText(chatId, `Switched to ${targetMode} mode. Re-processing your request...`, { parseMode: "plain" });
|
|
15817
16103
|
const pending = getPendingEscalation(chatId);
|
|
15818
16104
|
if (pending) {
|
|
15819
16105
|
removePendingEscalation(chatId);
|
|
@@ -15821,12 +16107,12 @@ ${PERM_MODES[chosen]}`,
|
|
|
15821
16107
|
}
|
|
15822
16108
|
} else if (data === "perm:deny") {
|
|
15823
16109
|
removePendingEscalation(chatId);
|
|
15824
|
-
await channel.sendText(chatId, "Keeping current mode.", "plain");
|
|
16110
|
+
await channel.sendText(chatId, "Keeping current mode.", { parseMode: "plain" });
|
|
15825
16111
|
} else if (data.startsWith("verbose:")) {
|
|
15826
16112
|
const chosen = data.slice(8);
|
|
15827
16113
|
if (!VERBOSE_LEVELS[chosen]) return;
|
|
15828
16114
|
setVerboseLevel(chatId, chosen);
|
|
15829
|
-
await channel.sendText(chatId, `Tool visibility: ${VERBOSE_LEVELS[chosen]}`, "plain");
|
|
16115
|
+
await channel.sendText(chatId, `Tool visibility: ${VERBOSE_LEVELS[chosen]}`, { parseMode: "plain" });
|
|
15830
16116
|
} else if (data.startsWith("tool:toggle:")) {
|
|
15831
16117
|
const toolName = data.slice(12);
|
|
15832
16118
|
if (!ALL_TOOLS.includes(toolName)) return;
|
|
@@ -15834,11 +16120,11 @@ ${PERM_MODES[chosen]}`,
|
|
|
15834
16120
|
await channel.sendText(
|
|
15835
16121
|
chatId,
|
|
15836
16122
|
`${newState ? "\u2705" : "\u274C"} ${toolName} ${newState ? "enabled" : "disabled"}`,
|
|
15837
|
-
"plain"
|
|
16123
|
+
{ parseMode: "plain" }
|
|
15838
16124
|
);
|
|
15839
16125
|
} else if (data === "tool:reset") {
|
|
15840
16126
|
resetTools(chatId);
|
|
15841
|
-
await channel.sendText(chatId, "Tool configuration reset \u2014 all tools enabled.", "plain");
|
|
16127
|
+
await channel.sendText(chatId, "Tool configuration reset \u2014 all tools enabled.", { parseMode: "plain" });
|
|
15842
16128
|
} else if (data.startsWith("sched:")) {
|
|
15843
16129
|
await handleWizardCallback(chatId, data, channel);
|
|
15844
16130
|
} else if (data.startsWith("profile:")) {
|
|
@@ -15847,9 +16133,9 @@ ${PERM_MODES[chosen]}`,
|
|
|
15847
16133
|
const parts = data.slice(11).split(":");
|
|
15848
16134
|
if (parts[0] === "yes" && parts.length >= 3) {
|
|
15849
16135
|
appendToUserProfile(parts[1], parts.slice(2).join(":"));
|
|
15850
|
-
await channel.sendText(chatId, `Preference saved: ${parts[1]}`, "plain");
|
|
16136
|
+
await channel.sendText(chatId, `Preference saved: ${parts[1]}`, { parseMode: "plain" });
|
|
15851
16137
|
} else {
|
|
15852
|
-
await channel.sendText(chatId, "Preference not saved.", "plain");
|
|
16138
|
+
await channel.sendText(chatId, "Preference not saved.", { parseMode: "plain" });
|
|
15853
16139
|
}
|
|
15854
16140
|
} else if (data.startsWith("shell:")) {
|
|
15855
16141
|
const parts = data.split(":");
|
|
@@ -15858,7 +16144,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15858
16144
|
if (action === "confirm") {
|
|
15859
16145
|
const pending = getPendingCommand(id);
|
|
15860
16146
|
if (!pending) {
|
|
15861
|
-
await channel.sendText(chatId, "Confirmation expired. Please re-send the command.", "plain");
|
|
16147
|
+
await channel.sendText(chatId, "Confirmation expired. Please re-send the command.", { parseMode: "plain" });
|
|
15862
16148
|
return;
|
|
15863
16149
|
}
|
|
15864
16150
|
removePendingCommand(id);
|
|
@@ -15869,27 +16155,27 @@ ${PERM_MODES[chosen]}`,
|
|
|
15869
16155
|
}
|
|
15870
16156
|
} else if (action === "cancel") {
|
|
15871
16157
|
removePendingCommand(id);
|
|
15872
|
-
await channel.sendText(chatId, "Command cancelled.", "plain");
|
|
16158
|
+
await channel.sendText(chatId, "Command cancelled.", { parseMode: "plain" });
|
|
15873
16159
|
}
|
|
15874
16160
|
} else if (data.startsWith("cwd:")) {
|
|
15875
16161
|
const parts = data.split(":");
|
|
15876
16162
|
const action = parts[1];
|
|
15877
16163
|
const targetChatId = parts.slice(2).join(":");
|
|
15878
16164
|
if (action === "keep") {
|
|
15879
|
-
await channel.sendText(chatId, "Session kept. The agent will continue with existing context.", "plain");
|
|
16165
|
+
await channel.sendText(chatId, "Session kept. The agent will continue with existing context.", { parseMode: "plain" });
|
|
15880
16166
|
} else if (action === "summarize") {
|
|
15881
16167
|
await summarizeSession(targetChatId);
|
|
15882
16168
|
clearSession(targetChatId);
|
|
15883
|
-
await channel.sendText(chatId, "Session summarized and reset. Context preserved in memory.", "plain");
|
|
16169
|
+
await channel.sendText(chatId, "Session summarized and reset. Context preserved in memory.", { parseMode: "plain" });
|
|
15884
16170
|
} else if (action === "reset") {
|
|
15885
16171
|
clearSession(targetChatId);
|
|
15886
|
-
await channel.sendText(chatId, "Session reset. Clean slate.", "plain");
|
|
16172
|
+
await channel.sendText(chatId, "Session reset. Clean slate.", { parseMode: "plain" });
|
|
15887
16173
|
}
|
|
15888
16174
|
} else if (data.startsWith("cwdpick:")) {
|
|
15889
16175
|
const alias = data.slice(8);
|
|
15890
16176
|
const bookmark = getBookmark(chatId, alias);
|
|
15891
16177
|
if (!bookmark) {
|
|
15892
|
-
await channel.sendText(chatId, `Bookmark '${alias}' no longer exists.`, "plain");
|
|
16178
|
+
await channel.sendText(chatId, `Bookmark '${alias}' no longer exists.`, { parseMode: "plain" });
|
|
15893
16179
|
return;
|
|
15894
16180
|
}
|
|
15895
16181
|
setCwd(chatId, bookmark.path);
|
|
@@ -15904,22 +16190,36 @@ ${PERM_MODES[chosen]}`,
|
|
|
15904
16190
|
if (action === "now" && pending) {
|
|
15905
16191
|
pendingInterrupts.delete(targetChatId);
|
|
15906
16192
|
stopAgent(targetChatId);
|
|
15907
|
-
await channel.sendText(chatId, "\u26A1 Stopping current task and processing your message\u2026", "plain");
|
|
16193
|
+
await channel.sendText(chatId, "\u26A1 Stopping current task and processing your message\u2026", { parseMode: "plain" });
|
|
15908
16194
|
bypassBusyCheck.add(targetChatId);
|
|
15909
16195
|
handleMessage(pending.msg, pending.channel).catch(() => {
|
|
15910
16196
|
});
|
|
15911
16197
|
} else if (action === "queue" && pending) {
|
|
15912
16198
|
pendingInterrupts.delete(targetChatId);
|
|
15913
16199
|
bypassBusyCheck.add(targetChatId);
|
|
15914
|
-
await channel.sendText(chatId, "\u{1F4E5} Message queued \u2014 will process after current task.", "plain");
|
|
16200
|
+
await channel.sendText(chatId, "\u{1F4E5} Message queued \u2014 will process after current task.", { parseMode: "plain" });
|
|
15915
16201
|
handleMessage(pending.msg, pending.channel).catch(() => {
|
|
15916
16202
|
});
|
|
16203
|
+
} else if (action === "sidequest") {
|
|
16204
|
+
const pending2 = pendingInterrupts.get(targetChatId);
|
|
16205
|
+
if (pending2) {
|
|
16206
|
+
pendingInterrupts.delete(targetChatId);
|
|
16207
|
+
handleSideQuest(targetChatId, pending2.msg, pending2.channel).catch(
|
|
16208
|
+
(err) => error(`[router] Side quest error for ${targetChatId}:`, err)
|
|
16209
|
+
);
|
|
16210
|
+
} else {
|
|
16211
|
+
await channel.sendText(chatId, "Main task finished \u2014 your message was already processed.", { parseMode: "plain" });
|
|
16212
|
+
}
|
|
15917
16213
|
} else if (action === "discard") {
|
|
15918
16214
|
pendingInterrupts.delete(targetChatId);
|
|
15919
|
-
await channel.sendText(chatId, "\u{1F5D1} Message discarded.", "plain");
|
|
16215
|
+
await channel.sendText(chatId, "\u{1F5D1} Message discarded.", { parseMode: "plain" });
|
|
15920
16216
|
} else {
|
|
15921
|
-
await channel.sendText(chatId, "Message already processed or expired.", "plain");
|
|
16217
|
+
await channel.sendText(chatId, "Message already processed or expired.", { parseMode: "plain" });
|
|
15922
16218
|
}
|
|
16219
|
+
} else if (data.startsWith("sq:cancel:")) {
|
|
16220
|
+
const sqId = data.slice("sq:cancel:".length);
|
|
16221
|
+
stopAgent(sqId);
|
|
16222
|
+
await channel.sendText(chatId, "\u{1F5FA} Side quest cancelled.", { parseMode: "plain" });
|
|
15923
16223
|
} else if (data.startsWith("fallback:")) {
|
|
15924
16224
|
const parts = data.split(":");
|
|
15925
16225
|
const targetBackend = parts[1];
|
|
@@ -15927,7 +16227,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15927
16227
|
const pendingMsg = pendingFallbackMessages.get(targetChatId);
|
|
15928
16228
|
if (targetBackend === "wait") {
|
|
15929
16229
|
pendingFallbackMessages.delete(targetChatId);
|
|
15930
|
-
await channel.sendText(chatId, "OK \u2014 you can switch manually with /backend when ready.", "plain");
|
|
16230
|
+
await channel.sendText(chatId, "OK \u2014 you can switch manually with /backend when ready.", { parseMode: "plain" });
|
|
15931
16231
|
} else if (pendingMsg) {
|
|
15932
16232
|
pendingFallbackMessages.delete(targetChatId);
|
|
15933
16233
|
if (pendingMsg.agentMode) pendingMsg.msg.agentMode = pendingMsg.agentMode;
|
|
@@ -15937,10 +16237,10 @@ ${PERM_MODES[chosen]}`,
|
|
|
15937
16237
|
clearSession(targetChatId);
|
|
15938
16238
|
setBackend(targetChatId, targetBackend);
|
|
15939
16239
|
const adapter = getAdapter(targetBackend);
|
|
15940
|
-
await channel.sendText(chatId, `Switched to ${adapter.displayName}. Resending your message\u2026`, "plain");
|
|
16240
|
+
await channel.sendText(chatId, `Switched to ${adapter.displayName}. Resending your message\u2026`, { parseMode: "plain" });
|
|
15941
16241
|
await handleMessage(pendingMsg.msg, pendingMsg.channel);
|
|
15942
16242
|
} else {
|
|
15943
|
-
await channel.sendText(chatId, "Fallback expired. Use /backend to switch manually.", "plain");
|
|
16243
|
+
await channel.sendText(chatId, "Fallback expired. Use /backend to switch manually.", { parseMode: "plain" });
|
|
15944
16244
|
}
|
|
15945
16245
|
} else if (data.startsWith("voice:")) {
|
|
15946
16246
|
const action = data.slice(6);
|
|
@@ -15948,7 +16248,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15948
16248
|
const current = isVoiceEnabled(chatId);
|
|
15949
16249
|
const desired = action === "on";
|
|
15950
16250
|
if (current !== desired) toggleVoice(chatId);
|
|
15951
|
-
await channel.sendText(chatId, desired ? "\u{1F50A} Voice responses enabled." : "\u{1F507} Voice responses disabled.", "plain");
|
|
16251
|
+
await channel.sendText(chatId, desired ? "\u{1F50A} Voice responses enabled." : "\u{1F507} Voice responses disabled.", { parseMode: "plain" });
|
|
15952
16252
|
}
|
|
15953
16253
|
} else if (data.startsWith("style:")) {
|
|
15954
16254
|
const selectedStyle = data.split(":")[1];
|
|
@@ -15963,7 +16263,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15963
16263
|
]
|
|
15964
16264
|
]);
|
|
15965
16265
|
}
|
|
15966
|
-
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, "plain");
|
|
16266
|
+
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, { parseMode: "plain" });
|
|
15967
16267
|
}
|
|
15968
16268
|
} else if (data.startsWith("agentmode:")) {
|
|
15969
16269
|
const mode = data.split(":")[1];
|
|
@@ -15974,7 +16274,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
15974
16274
|
} catch {
|
|
15975
16275
|
}
|
|
15976
16276
|
clearSession(chatId);
|
|
15977
|
-
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, "html");
|
|
16277
|
+
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
|
|
15978
16278
|
}
|
|
15979
16279
|
return;
|
|
15980
16280
|
} else if (data.startsWith("agents:")) {
|
|
@@ -15985,11 +16285,11 @@ ${PERM_MODES[chosen]}`,
|
|
|
15985
16285
|
const agents2 = listActiveAgents(db3);
|
|
15986
16286
|
const match = agents2.find((a) => a.id.startsWith(shortId));
|
|
15987
16287
|
if (!match) {
|
|
15988
|
-
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped. Use /agents to refresh.`, "plain");
|
|
16288
|
+
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped. Use /agents to refresh.`, { parseMode: "plain" });
|
|
15989
16289
|
return;
|
|
15990
16290
|
}
|
|
15991
16291
|
const ok = cancelAgent(match.id);
|
|
15992
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
16292
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
15993
16293
|
} else if (rest === "tasks") {
|
|
15994
16294
|
const synth = { chatId, messageId: "", text: "", senderName: "User", type: "command", source: "telegram", command: "tasks", commandArgs: "" };
|
|
15995
16295
|
await handleCommand(synth, channel);
|
|
@@ -16003,16 +16303,16 @@ ${PERM_MODES[chosen]}`,
|
|
|
16003
16303
|
const agents2 = listActiveAgents(db3);
|
|
16004
16304
|
const match = agents2.find((a) => a.id.startsWith(shortId));
|
|
16005
16305
|
if (!match) {
|
|
16006
|
-
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped.`, "plain");
|
|
16306
|
+
await channel.sendText(chatId, `Agent ${shortId} not found or already stopped.`, { parseMode: "plain" });
|
|
16007
16307
|
return;
|
|
16008
16308
|
}
|
|
16009
16309
|
const ok = cancelAgent(match.id);
|
|
16010
|
-
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", "plain");
|
|
16310
|
+
await channel.sendText(chatId, ok ? `Agent ${match.id.slice(0, 8)} cancelled.` : "Could not cancel agent.", { parseMode: "plain" });
|
|
16011
16311
|
} else if (rest === "all") {
|
|
16012
16312
|
const count = cancelAllAgents(chatId);
|
|
16013
|
-
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", "plain");
|
|
16313
|
+
await channel.sendText(chatId, count > 0 ? `Cancelled ${count} agent(s).` : "No active agents to cancel.", { parseMode: "plain" });
|
|
16014
16314
|
} else if (rest === "cancel") {
|
|
16015
|
-
await channel.sendText(chatId, "Cancelled.", "plain");
|
|
16315
|
+
await channel.sendText(chatId, "Cancelled.", { parseMode: "plain" });
|
|
16016
16316
|
}
|
|
16017
16317
|
return;
|
|
16018
16318
|
} else if (data.startsWith("tasks:")) {
|
|
@@ -16022,7 +16322,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
16022
16322
|
const db3 = getDb();
|
|
16023
16323
|
const task = getTask(db3, taskId);
|
|
16024
16324
|
if (!task) {
|
|
16025
|
-
await channel.sendText(chatId, "Task not found or outdated. Use /tasks to refresh.", "plain");
|
|
16325
|
+
await channel.sendText(chatId, "Task not found or outdated. Use /tasks to refresh.", { parseMode: "plain" });
|
|
16026
16326
|
return;
|
|
16027
16327
|
}
|
|
16028
16328
|
const STATUS_EMOJI_TASK = {
|
|
@@ -16046,7 +16346,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
16046
16346
|
task.result ? `
|
|
16047
16347
|
Result: ${task.result.slice(0, 500)}` : ""
|
|
16048
16348
|
].filter(Boolean);
|
|
16049
|
-
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
16349
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
16050
16350
|
}
|
|
16051
16351
|
return;
|
|
16052
16352
|
} else if (data.startsWith("grotation:")) {
|
|
@@ -16056,25 +16356,25 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16056
16356
|
if (mode === "accounts") {
|
|
16057
16357
|
const oauthSlots = getGeminiSlots().filter((s) => s.enabled && s.slotType === "oauth");
|
|
16058
16358
|
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");
|
|
16359
|
+
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
16360
|
return;
|
|
16061
16361
|
}
|
|
16062
16362
|
} else if (mode === "keys") {
|
|
16063
16363
|
const keySlots = getGeminiSlots().filter((s) => s.enabled && s.slotType === "api_key");
|
|
16064
16364
|
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");
|
|
16365
|
+
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
16366
|
return;
|
|
16067
16367
|
}
|
|
16068
16368
|
}
|
|
16069
16369
|
setGeminiRotationMode(mode);
|
|
16070
16370
|
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");
|
|
16371
|
+
await channel.sendText(chatId, `Rotation mode set to <b>${modeLabels[mode]}</b>.`, { parseMode: "html" });
|
|
16072
16372
|
return;
|
|
16073
16373
|
} else if (data.startsWith("gslot:")) {
|
|
16074
16374
|
const val = data.split(":")[1];
|
|
16075
16375
|
if (val === "auto") {
|
|
16076
16376
|
clearChatGeminiSlot(chatId);
|
|
16077
|
-
await channel.sendText(chatId, "Gemini slot set to <b>\u{1F504} auto rotation</b>.", "html");
|
|
16377
|
+
await channel.sendText(chatId, "Gemini slot set to <b>\u{1F504} auto rotation</b>.", { parseMode: "html" });
|
|
16078
16378
|
} else {
|
|
16079
16379
|
const slotId = parseInt(val, 10);
|
|
16080
16380
|
const slots = getGeminiSlots();
|
|
@@ -16083,14 +16383,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16083
16383
|
pinChatGeminiSlot(chatId, slotId);
|
|
16084
16384
|
const label2 = slot.label || `slot-${slot.id}`;
|
|
16085
16385
|
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");
|
|
16386
|
+
await channel.sendText(chatId, `Pinned to ${icon} <b>${label2}</b>`, { parseMode: "html" });
|
|
16087
16387
|
}
|
|
16088
16388
|
}
|
|
16089
16389
|
return;
|
|
16090
16390
|
} else if (data === "gopen:accounts") {
|
|
16091
16391
|
const slots = getGeminiSlots();
|
|
16092
16392
|
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");
|
|
16393
|
+
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
16394
|
return;
|
|
16095
16395
|
}
|
|
16096
16396
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16122,7 +16422,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16122
16422
|
await channel.sendText(
|
|
16123
16423
|
chatId,
|
|
16124
16424
|
value === "on" ? "\u{1F9E0} Model signature enabled. Each response will show the active model and thinking level." : "Model signature disabled.",
|
|
16125
|
-
"plain"
|
|
16425
|
+
{ parseMode: "plain" }
|
|
16126
16426
|
);
|
|
16127
16427
|
} else if (data.startsWith("vcfg:")) {
|
|
16128
16428
|
const parts = data.slice(5).split(":");
|
|
@@ -16134,14 +16434,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16134
16434
|
await channel.sendText(
|
|
16135
16435
|
chatId,
|
|
16136
16436
|
"\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"
|
|
16437
|
+
{ parseMode: "markdown" }
|
|
16138
16438
|
);
|
|
16139
16439
|
}
|
|
16140
16440
|
if (provider === "elevenlabs" && !process.env.ELEVENLABS_API_KEY) {
|
|
16141
16441
|
await channel.sendText(
|
|
16142
16442
|
chatId,
|
|
16143
16443
|
"\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"
|
|
16444
|
+
{ parseMode: "markdown" }
|
|
16145
16445
|
);
|
|
16146
16446
|
}
|
|
16147
16447
|
const defaultVoice = provider === "grok" ? "eve" : provider === "macos" ? "Samantha" : "21m00Tcm4TlvDq8ikWAM";
|
|
@@ -16153,7 +16453,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16153
16453
|
const config2 = getVoiceConfig(chatId);
|
|
16154
16454
|
setVoiceProvider(chatId, config2.provider, voiceId);
|
|
16155
16455
|
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");
|
|
16456
|
+
await channel.sendText(chatId, `\u2705 Voice set to: ${voiceName}`, { parseMode: "plain" });
|
|
16157
16457
|
}
|
|
16158
16458
|
} else if (data.startsWith("skills:page:")) {
|
|
16159
16459
|
const page = parseInt(data.slice(12), 10);
|
|
@@ -16172,7 +16472,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16172
16472
|
const skills2 = await discoverAllSkills();
|
|
16173
16473
|
const skill = skillSource ? skills2.find((s) => s.name === skillName && s.source === skillSource) : skills2.find((s) => s.name === skillName);
|
|
16174
16474
|
if (!skill) {
|
|
16175
|
-
await channel.sendText(chatId, `Skill "${skillName}" not found.`, "plain");
|
|
16475
|
+
await channel.sendText(chatId, `Skill "${skillName}" not found.`, { parseMode: "plain" });
|
|
16176
16476
|
return;
|
|
16177
16477
|
}
|
|
16178
16478
|
const activeBackend = getBackend(chatId) ?? "claude";
|
|
@@ -16180,13 +16480,13 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16180
16480
|
await channel.sendText(
|
|
16181
16481
|
chatId,
|
|
16182
16482
|
`Note: "${skillName}" lists compatible backends as [${skill.compatibleBackends.join(", ")}], but active backend is ${activeBackend}. Proceeding anyway.`,
|
|
16183
|
-
"plain"
|
|
16483
|
+
{ parseMode: "plain" }
|
|
16184
16484
|
);
|
|
16185
16485
|
}
|
|
16186
16486
|
const raw = await readFile5(skill.filePath, "utf-8");
|
|
16187
16487
|
const skillContent = stripFrontmatter2(raw);
|
|
16188
16488
|
const tags = skill.sources.join(", ");
|
|
16189
|
-
await channel.sendText(chatId, `Loading skill: ${skillName} [${tags}]...`, "plain");
|
|
16489
|
+
await channel.sendText(chatId, `Loading skill: ${skillName} [${tags}]...`, { parseMode: "plain" });
|
|
16190
16490
|
const skillModel = resolveModel(chatId);
|
|
16191
16491
|
const sMode = getMode(chatId);
|
|
16192
16492
|
const sVerbose = getVerboseLevel(chatId);
|
|
@@ -16199,19 +16499,65 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16199
16499
|
const action = parts[1];
|
|
16200
16500
|
const idStr = parts[2];
|
|
16201
16501
|
switch (action) {
|
|
16502
|
+
case "menu": {
|
|
16503
|
+
const { getReflectionStatus: getRefStatus, getUnprocessedSignalCount: getUnprocessedSignalCount2, getPendingInsightCount: getPendingInsightCount2, getLastAnalysisTime: getLastAnalysisTime2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16504
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16505
|
+
const menuActive = getRefStatus(getDb2(), chatId) === "active";
|
|
16506
|
+
if (!menuActive) {
|
|
16507
|
+
const { buildEvolveOnboardingKeyboard: buildEvolveOnboardingKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16508
|
+
const text = [
|
|
16509
|
+
"Self-Learning & Evolution",
|
|
16510
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
16511
|
+
"",
|
|
16512
|
+
"Teach your assistant to improve over time.",
|
|
16513
|
+
"",
|
|
16514
|
+
"When enabled, CC-Claw watches for corrections,",
|
|
16515
|
+
"preferences, and frustration in your messages,",
|
|
16516
|
+
"then proposes changes to its personality and",
|
|
16517
|
+
"behavior files (SOUL.md, USER.md).",
|
|
16518
|
+
"",
|
|
16519
|
+
"You review and approve every change."
|
|
16520
|
+
].join("\n");
|
|
16521
|
+
await channel.sendKeyboard(chatId, text, buildEvolveOnboardingKeyboard2());
|
|
16522
|
+
} else {
|
|
16523
|
+
const { buildEvolveMenuKeyboard: buildEvolveMenuKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16524
|
+
const signals = getUnprocessedSignalCount2(getDb2(), chatId);
|
|
16525
|
+
const pending = getPendingInsightCount2(getDb2(), chatId);
|
|
16526
|
+
const lastTime = getLastAnalysisTime2(getDb2(), chatId);
|
|
16527
|
+
let lastText = "never";
|
|
16528
|
+
if (lastTime) {
|
|
16529
|
+
const diffMs = Date.now() - (/* @__PURE__ */ new Date(lastTime + "Z")).getTime();
|
|
16530
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
16531
|
+
if (diffHours < 1) lastText = "< 1 hour ago";
|
|
16532
|
+
else if (diffHours < 24) lastText = `${diffHours}h ago`;
|
|
16533
|
+
else lastText = `${Math.floor(diffHours / 24)}d ago`;
|
|
16534
|
+
}
|
|
16535
|
+
const lines = [
|
|
16536
|
+
"Self-Learning & Evolution",
|
|
16537
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
16538
|
+
"",
|
|
16539
|
+
`\u2705 Active`,
|
|
16540
|
+
`Signals: ${signals} pending \xB7 Proposals: ${pending}`,
|
|
16541
|
+
`Last analysis: ${lastText}`
|
|
16542
|
+
];
|
|
16543
|
+
await channel.sendKeyboard(chatId, lines.join("\n"), buildEvolveMenuKeyboard2({ pendingProposals: pending, unprocessedSignals: signals }));
|
|
16544
|
+
}
|
|
16545
|
+
break;
|
|
16546
|
+
}
|
|
16202
16547
|
case "analyze": {
|
|
16203
16548
|
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
16204
16549
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16205
|
-
await channel.sendText(chatId, "Analyzing recent interactions...", "plain");
|
|
16550
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
16206
16551
|
try {
|
|
16207
|
-
const insights = await runAnalysis2(chatId);
|
|
16552
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
16208
16553
|
if (insights.length === 0) {
|
|
16209
|
-
await channel.sendText(chatId, "No new insights from recent interactions.", "plain");
|
|
16554
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
16210
16555
|
} else {
|
|
16211
|
-
|
|
16556
|
+
const nightlyItems = insights.map((ins, i) => ({ id: i + 1, ...ins }));
|
|
16557
|
+
await channel.sendText(chatId, formatNightlySummary2(nightlyItems), { parseMode: "plain" });
|
|
16212
16558
|
}
|
|
16213
16559
|
} catch (e) {
|
|
16214
|
-
await channel.sendText(chatId, `Analysis failed: ${e}`, "plain");
|
|
16560
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
16215
16561
|
}
|
|
16216
16562
|
break;
|
|
16217
16563
|
}
|
|
@@ -16221,7 +16567,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16221
16567
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16222
16568
|
const pending = getPendingInsights2(getDb2(), chatId);
|
|
16223
16569
|
if (pending.length === 0) {
|
|
16224
|
-
await channel.sendText(chatId, "No pending proposals.", "plain");
|
|
16570
|
+
await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
|
|
16225
16571
|
} else {
|
|
16226
16572
|
for (const insight of pending.slice(0, 5)) {
|
|
16227
16573
|
const card = formatProposalCard2(insight);
|
|
@@ -16229,7 +16575,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16229
16575
|
await channel.sendKeyboard(chatId, card, kb);
|
|
16230
16576
|
}
|
|
16231
16577
|
if (pending.length > 5) {
|
|
16232
|
-
await channel.sendText(chatId, `${pending.length - 5} more proposals. Run /evolve again to see next batch.`, "plain");
|
|
16578
|
+
await channel.sendText(chatId, `${pending.length - 5} more proposals. Run /evolve again to see next batch.`, { parseMode: "plain" });
|
|
16233
16579
|
}
|
|
16234
16580
|
}
|
|
16235
16581
|
break;
|
|
@@ -16240,25 +16586,48 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16240
16586
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16241
16587
|
const insight = getInsightById2(getDb2(), parseInt(idStr, 10));
|
|
16242
16588
|
if (insight?.proposedDiff) {
|
|
16243
|
-
await channel.sendText(chatId, formatDiffCodeBlock2(insight.proposedDiff), "plain");
|
|
16589
|
+
await channel.sendText(chatId, formatDiffCodeBlock2(insight.proposedDiff), { parseMode: "plain" });
|
|
16244
16590
|
}
|
|
16245
16591
|
break;
|
|
16246
16592
|
}
|
|
16247
16593
|
case "apply": {
|
|
16248
16594
|
const { applyInsight: applyInsight2 } = await Promise.resolve().then(() => (init_apply(), apply_exports));
|
|
16249
16595
|
const result = await applyInsight2(parseInt(idStr, 10));
|
|
16250
|
-
await channel.sendText(chatId, result.message, "plain");
|
|
16596
|
+
await channel.sendText(chatId, result.message, { parseMode: "plain" });
|
|
16251
16597
|
break;
|
|
16252
16598
|
}
|
|
16253
16599
|
case "skip": {
|
|
16254
|
-
await channel.sendText(chatId, "Skipped \u2014 will show again next review.", "plain");
|
|
16600
|
+
await channel.sendText(chatId, "Skipped \u2014 will show again next review.", { parseMode: "plain" });
|
|
16601
|
+
break;
|
|
16602
|
+
}
|
|
16603
|
+
case "discuss": {
|
|
16604
|
+
const insId = parseInt(idStr, 10);
|
|
16605
|
+
activeProposalDiscussion.set(chatId, insId);
|
|
16606
|
+
await channel.sendKeyboard(chatId, `Discussing proposal #${insId}. Send your questions \u2014 type "done" when finished.`, [
|
|
16607
|
+
[{ label: "Done", data: `evolve:discuss-done:${insId}` }]
|
|
16608
|
+
]);
|
|
16609
|
+
break;
|
|
16610
|
+
}
|
|
16611
|
+
case "discuss-done": {
|
|
16612
|
+
activeProposalDiscussion.delete(chatId);
|
|
16613
|
+
const { getInsightById: getIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16614
|
+
const { formatProposalCard: fmtCard, buildProposalKeyboard: buildKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16615
|
+
const { getDb: getDatabase } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16616
|
+
const ins = getIns(getDatabase(), parseInt(idStr, 10));
|
|
16617
|
+
if (ins && ins.status === "pending") {
|
|
16618
|
+
const card = fmtCard(ins);
|
|
16619
|
+
const kb = buildKb(ins.id, ins.category);
|
|
16620
|
+
await channel.sendKeyboard(chatId, "Updated proposal:\n\n" + card, kb);
|
|
16621
|
+
} else {
|
|
16622
|
+
await channel.sendText(chatId, "Discussion ended.", { parseMode: "plain" });
|
|
16623
|
+
}
|
|
16255
16624
|
break;
|
|
16256
16625
|
}
|
|
16257
16626
|
case "reject": {
|
|
16258
16627
|
const { updateInsightStatus: updateInsightStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16259
16628
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16260
16629
|
updateInsightStatus2(getDb2(), parseInt(idStr, 10), "rejected");
|
|
16261
|
-
await channel.sendText(chatId, "Rejected. Won't propose similar changes.", "plain");
|
|
16630
|
+
await channel.sendText(chatId, "Rejected. Won't propose similar changes.", { parseMode: "plain" });
|
|
16262
16631
|
break;
|
|
16263
16632
|
}
|
|
16264
16633
|
case "stats": {
|
|
@@ -16268,12 +16637,23 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16268
16637
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16269
16638
|
const reportData = buildGrowthReportData2(getDb2(), chatId, 30);
|
|
16270
16639
|
const modelData = buildModelPerformanceData2(getDb2(), chatId, 30);
|
|
16271
|
-
|
|
16640
|
+
const metricsForReport = {
|
|
16641
|
+
correctionsBefore: reportData.avgCorrectionsFirstHalf,
|
|
16642
|
+
correctionsAfter: reportData.avgCorrectionsSecondHalf,
|
|
16643
|
+
praiseRatio: reportData.praiseRatio,
|
|
16644
|
+
insightsApplied: reportData.totalInsightsApplied,
|
|
16645
|
+
pendingCount: reportData.pendingCount,
|
|
16646
|
+
topInsight: reportData.topInsightId != null ? {
|
|
16647
|
+
insight: `#${reportData.topInsightId}`,
|
|
16648
|
+
effectiveness: reportData.topInsightEffectiveness ?? 0
|
|
16649
|
+
} : null
|
|
16650
|
+
};
|
|
16651
|
+
let report = formatGrowthReport2(metricsForReport, modelData);
|
|
16272
16652
|
const drift = calculateDrift2(chatId);
|
|
16273
16653
|
if (drift && (drift.soulDrift > 0.5 || drift.userDrift > 0.5)) {
|
|
16274
16654
|
report += "\n\nSOUL.md has changed significantly since reflection started.\nTap History in /evolve to review all applied changes.";
|
|
16275
16655
|
}
|
|
16276
|
-
await channel.sendText(chatId, report, "plain");
|
|
16656
|
+
await channel.sendText(chatId, report, { parseMode: "plain" });
|
|
16277
16657
|
break;
|
|
16278
16658
|
}
|
|
16279
16659
|
case "history": {
|
|
@@ -16293,7 +16673,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16293
16673
|
msg += `#${i.id} [${i.category}] ${i.insight}
|
|
16294
16674
|
`;
|
|
16295
16675
|
});
|
|
16296
|
-
await channel.sendText(chatId, msg, "plain");
|
|
16676
|
+
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
16297
16677
|
break;
|
|
16298
16678
|
}
|
|
16299
16679
|
case "toggle": {
|
|
@@ -16311,12 +16691,12 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16311
16691
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
16312
16692
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16313
16693
|
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");
|
|
16694
|
+
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
16695
|
} else {
|
|
16316
|
-
setReflectionStatus2(getDb2(), chatId, "frozen",
|
|
16696
|
+
setReflectionStatus2(getDb2(), chatId, "frozen", void 0, void 0);
|
|
16317
16697
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16318
16698
|
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");
|
|
16699
|
+
await channel.sendText(chatId, "\u26D4 Self-learning disabled. No signals will be collected.", { parseMode: "plain" });
|
|
16320
16700
|
}
|
|
16321
16701
|
break;
|
|
16322
16702
|
}
|
|
@@ -16324,14 +16704,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16324
16704
|
if (idStr) {
|
|
16325
16705
|
const { rollbackInsight: rollbackInsight2 } = await Promise.resolve().then(() => (init_apply(), apply_exports));
|
|
16326
16706
|
const result = await rollbackInsight2(parseInt(idStr, 10));
|
|
16327
|
-
await channel.sendText(chatId, result.message, "plain");
|
|
16707
|
+
await channel.sendText(chatId, result.message, { parseMode: "plain" });
|
|
16328
16708
|
} else {
|
|
16329
16709
|
const { getAppliedInsights: getAppliedInsights2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16330
16710
|
const { buildUndoKeyboard: buildUndoKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16331
16711
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16332
16712
|
const applied = getAppliedInsights2(getDb2(), chatId, 10);
|
|
16333
16713
|
if (applied.length === 0) {
|
|
16334
|
-
await channel.sendText(chatId, "No applied insights to undo.", "plain");
|
|
16714
|
+
await channel.sendText(chatId, "No applied insights to undo.", { parseMode: "plain" });
|
|
16335
16715
|
} else {
|
|
16336
16716
|
const kb = buildUndoKeyboard2(applied);
|
|
16337
16717
|
await channel.sendKeyboard(chatId, "Select an insight to undo:", kb);
|
|
@@ -16344,7 +16724,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16344
16724
|
const { setReflectionModelConfig: setReflectionModelConfig2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16345
16725
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16346
16726
|
setReflectionModelConfig2(getDb2(), chatId, idStr);
|
|
16347
|
-
await channel.sendText(chatId, `Analysis model set to: ${idStr}`, "plain");
|
|
16727
|
+
await channel.sendText(chatId, `Analysis model set to: ${idStr}`, { parseMode: "plain" });
|
|
16348
16728
|
} else {
|
|
16349
16729
|
const { getReflectionModelConfig: getReflectionModelConfig2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16350
16730
|
const { buildModelKeyboard: buildModelKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
@@ -16362,16 +16742,16 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16362
16742
|
if (action === "all") {
|
|
16363
16743
|
const pendingIds = getLoggedChatIds();
|
|
16364
16744
|
if (pendingIds.length === 0) {
|
|
16365
|
-
await channel.sendText(chatId, "No pending sessions to summarize.", "plain");
|
|
16745
|
+
await channel.sendText(chatId, "No pending sessions to summarize.", { parseMode: "plain" });
|
|
16366
16746
|
return;
|
|
16367
16747
|
}
|
|
16368
|
-
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, "plain");
|
|
16748
|
+
await channel.sendText(chatId, `Summarizing ${pendingIds.length} pending session(s)...`, { parseMode: "plain" });
|
|
16369
16749
|
await summarizeAllPending();
|
|
16370
|
-
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, "plain");
|
|
16750
|
+
await channel.sendText(chatId, `Done. ${pendingIds.length} session(s) summarized and saved to memory.`, { parseMode: "plain" });
|
|
16371
16751
|
} else if (action === "undo") {
|
|
16372
16752
|
const pending = pendingSummaryUndo.get(chatId);
|
|
16373
16753
|
if (!pending) {
|
|
16374
|
-
await channel.sendText(chatId, "Undo window expired.", "plain");
|
|
16754
|
+
await channel.sendText(chatId, "Undo window expired.", { parseMode: "plain" });
|
|
16375
16755
|
return;
|
|
16376
16756
|
}
|
|
16377
16757
|
clearTimeout(pending.timer);
|
|
@@ -16389,20 +16769,20 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16389
16769
|
if (action === "go") {
|
|
16390
16770
|
const { runAnalysis: runAnalysis2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
16391
16771
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16392
|
-
await channel.sendText(chatId, "Analyzing recent interactions...", "plain");
|
|
16772
|
+
await channel.sendText(chatId, "Analyzing recent interactions...", { parseMode: "plain" });
|
|
16393
16773
|
try {
|
|
16394
|
-
const insights = await runAnalysis2(chatId);
|
|
16774
|
+
const insights = await runAnalysis2(chatId, { force: true });
|
|
16395
16775
|
if (insights.length === 0) {
|
|
16396
|
-
await channel.sendText(chatId, "No new insights from recent interactions.", "plain");
|
|
16776
|
+
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
16397
16777
|
} else {
|
|
16398
16778
|
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");
|
|
16779
|
+
await channel.sendText(chatId, formatNightlySummary2(items) + "\n\nUse /evolve to review and apply proposals.", { parseMode: "plain" });
|
|
16400
16780
|
}
|
|
16401
16781
|
} catch (e) {
|
|
16402
|
-
await channel.sendText(chatId, `Analysis failed: ${e}`, "plain");
|
|
16782
|
+
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
16403
16783
|
}
|
|
16404
16784
|
} else if (action === "cancel") {
|
|
16405
|
-
await channel.sendText(chatId, "Reflection cancelled.", "plain");
|
|
16785
|
+
await channel.sendText(chatId, "Reflection cancelled.", { parseMode: "plain" });
|
|
16406
16786
|
}
|
|
16407
16787
|
return;
|
|
16408
16788
|
} else if (data.startsWith("chats:")) {
|
|
@@ -16432,7 +16812,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16432
16812
|
} else if (action === "remove") {
|
|
16433
16813
|
const aliases = getAllChatAliases();
|
|
16434
16814
|
if (aliases.length === 0) {
|
|
16435
|
-
await channel.sendText(chatId, "No aliases to remove.", "plain");
|
|
16815
|
+
await channel.sendText(chatId, "No aliases to remove.", { parseMode: "plain" });
|
|
16436
16816
|
return;
|
|
16437
16817
|
}
|
|
16438
16818
|
const aliasButtons = aliases.map((a, i) => [{ label: a.alias, data: `chats:remove:${i}` }]);
|
|
@@ -16442,12 +16822,12 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16442
16822
|
const idx = parseInt(action.slice(7), 10);
|
|
16443
16823
|
const aliases = getAllChatAliases();
|
|
16444
16824
|
if (isNaN(idx) || idx < 0 || idx >= aliases.length) {
|
|
16445
|
-
await channel.sendText(chatId, "This data is outdated. Use /chats to refresh.", "plain");
|
|
16825
|
+
await channel.sendText(chatId, "This data is outdated. Use /chats to refresh.", { parseMode: "plain" });
|
|
16446
16826
|
return;
|
|
16447
16827
|
}
|
|
16448
16828
|
const alias = aliases[idx].alias;
|
|
16449
16829
|
const removed = removeChatAlias(alias);
|
|
16450
|
-
await channel.sendText(chatId, removed ? `Alias "${alias}" removed.` : `Alias "${alias}" not found.`, "plain");
|
|
16830
|
+
await channel.sendText(chatId, removed ? `Alias "${alias}" removed.` : `Alias "${alias}" not found.`, { parseMode: "plain" });
|
|
16451
16831
|
}
|
|
16452
16832
|
return;
|
|
16453
16833
|
} else if (data.startsWith("hist:")) {
|
|
@@ -16478,7 +16858,7 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16478
16858
|
[{ label: "Refresh List", data: "forget:page:1" }]
|
|
16479
16859
|
]);
|
|
16480
16860
|
} else {
|
|
16481
|
-
await channel.sendText(chatId, "This memory no longer exists.", "plain");
|
|
16861
|
+
await channel.sendText(chatId, "This memory no longer exists.", { parseMode: "plain" });
|
|
16482
16862
|
}
|
|
16483
16863
|
return;
|
|
16484
16864
|
}
|
|
@@ -16499,10 +16879,10 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16499
16879
|
await channel.sendText(
|
|
16500
16880
|
chatId,
|
|
16501
16881
|
deleted ? "Memory deleted." : "Memory not found \u2014 already deleted.",
|
|
16502
|
-
"plain"
|
|
16882
|
+
{ parseMode: "plain" }
|
|
16503
16883
|
);
|
|
16504
16884
|
} else if (rest === "cancel") {
|
|
16505
|
-
await channel.sendText(chatId, "Cancelled.", "plain");
|
|
16885
|
+
await channel.sendText(chatId, "Cancelled.", { parseMode: "plain" });
|
|
16506
16886
|
}
|
|
16507
16887
|
return;
|
|
16508
16888
|
} else if (data.startsWith("mem:")) {
|
|
@@ -16519,7 +16899,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16519
16899
|
[{ label: "Refresh List", data: "mem:page:1" }]
|
|
16520
16900
|
]);
|
|
16521
16901
|
} else {
|
|
16522
|
-
await channel.sendText(chatId, "This memory no longer exists.", "plain");
|
|
16902
|
+
await channel.sendText(chatId, "This memory no longer exists.", { parseMode: "plain" });
|
|
16523
16903
|
}
|
|
16524
16904
|
return;
|
|
16525
16905
|
}
|
|
@@ -16544,13 +16924,13 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16544
16924
|
await channel.sendText(
|
|
16545
16925
|
chatId,
|
|
16546
16926
|
deleted ? "Memory deleted." : "Memory not found \u2014 already deleted.",
|
|
16547
|
-
"plain"
|
|
16927
|
+
{ parseMode: "plain" }
|
|
16548
16928
|
);
|
|
16549
16929
|
} else if (rest.startsWith("forget:")) {
|
|
16550
16930
|
const id = parseInt(rest.slice(7), 10);
|
|
16551
16931
|
const memory2 = getMemoryById(id);
|
|
16552
16932
|
if (!memory2) {
|
|
16553
|
-
await channel.sendText(chatId, "Memory not found.", "plain");
|
|
16933
|
+
await channel.sendText(chatId, "Memory not found.", { parseMode: "plain" });
|
|
16554
16934
|
return;
|
|
16555
16935
|
}
|
|
16556
16936
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16568,7 +16948,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16568
16948
|
}
|
|
16569
16949
|
} else if (rest.startsWith("edit:")) {
|
|
16570
16950
|
const id = parseInt(rest.slice(5), 10);
|
|
16571
|
-
await channel.sendText(chatId, `Type: /memory edit ${id} <new content>`, "plain");
|
|
16951
|
+
await channel.sendText(chatId, `Type: /memory edit ${id} <new content>`, { parseMode: "plain" });
|
|
16572
16952
|
} else if (rest === "back") {
|
|
16573
16953
|
await sendMemoryPage(chatId, channel, 1);
|
|
16574
16954
|
} else if (rest === "showall") {
|
|
@@ -16606,7 +16986,7 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16606
16986
|
if (rest === "undo") {
|
|
16607
16987
|
const pending = pendingNewchatUndo.get(chatId);
|
|
16608
16988
|
if (!pending) {
|
|
16609
|
-
await channel.sendText(chatId, "Undo window expired.", "plain");
|
|
16989
|
+
await channel.sendText(chatId, "Undo window expired.", { parseMode: "plain" });
|
|
16610
16990
|
return;
|
|
16611
16991
|
}
|
|
16612
16992
|
clearTimeout(pending.timer);
|
|
@@ -16637,13 +17017,13 @@ Salience: ${memory2.salience.toFixed(2)} | Created: ${memory2.created_at.slice(0
|
|
|
16637
17017
|
clearBackendLimit(bid, win);
|
|
16638
17018
|
}
|
|
16639
17019
|
}
|
|
16640
|
-
await channel.sendText(chatId, "All usage limits cleared.", "plain");
|
|
17020
|
+
await channel.sendText(chatId, "All usage limits cleared.", { parseMode: "plain" });
|
|
16641
17021
|
await sendUnifiedUsage(chatId, channel, "session");
|
|
16642
17022
|
} else if (rest.startsWith("limits:set:")) {
|
|
16643
17023
|
const bid = rest.slice(11);
|
|
16644
17024
|
await channel.sendText(chatId, `Set limit for ${bid}:
|
|
16645
17025
|
/limits ${bid} daily <tokens>
|
|
16646
|
-
Example: /limits ${bid} daily 500000`, "plain");
|
|
17026
|
+
Example: /limits ${bid} daily 500000`, { parseMode: "plain" });
|
|
16647
17027
|
}
|
|
16648
17028
|
return;
|
|
16649
17029
|
} else if (data.startsWith("job:")) {
|
|
@@ -16655,14 +17035,14 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16655
17035
|
await sendJobDetail(chatId, id, channel);
|
|
16656
17036
|
} else if (rest.startsWith("run:")) {
|
|
16657
17037
|
const id = parseInt(rest.slice(4), 10);
|
|
16658
|
-
await channel.sendText(chatId, `Triggering job #${id}...`, "plain");
|
|
17038
|
+
await channel.sendText(chatId, `Triggering job #${id}...`, { parseMode: "plain" });
|
|
16659
17039
|
const result = await triggerJob(id);
|
|
16660
17040
|
if (typeof channel.sendKeyboard === "function") {
|
|
16661
17041
|
await channel.sendKeyboard(chatId, result, [
|
|
16662
17042
|
[{ label: "\u2190 Back to Job", data: `job:view:${id}` }]
|
|
16663
17043
|
]);
|
|
16664
17044
|
} else {
|
|
16665
|
-
await channel.sendText(chatId, result, "plain");
|
|
17045
|
+
await channel.sendText(chatId, result, { parseMode: "plain" });
|
|
16666
17046
|
}
|
|
16667
17047
|
} else if (rest.startsWith("pause:")) {
|
|
16668
17048
|
const id = parseInt(rest.slice(6), 10);
|
|
@@ -16670,7 +17050,7 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16670
17050
|
if (paused) {
|
|
16671
17051
|
await sendJobDetail(chatId, id, channel);
|
|
16672
17052
|
} else {
|
|
16673
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
17053
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16674
17054
|
}
|
|
16675
17055
|
} else if (rest.startsWith("resume:")) {
|
|
16676
17056
|
const id = parseInt(rest.slice(7), 10);
|
|
@@ -16678,22 +17058,22 @@ Example: /limits ${bid} daily 500000`, "plain");
|
|
|
16678
17058
|
if (resumed) {
|
|
16679
17059
|
await sendJobDetail(chatId, id, channel);
|
|
16680
17060
|
} else {
|
|
16681
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
17061
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16682
17062
|
}
|
|
16683
17063
|
} else if (rest.startsWith("cancel:confirm:")) {
|
|
16684
17064
|
const id = parseInt(rest.slice(15), 10);
|
|
16685
17065
|
const cancelled = cancelJob(id);
|
|
16686
17066
|
if (cancelled) {
|
|
16687
|
-
await channel.sendText(chatId, `Job #${id} cancelled.`, "plain");
|
|
17067
|
+
await channel.sendText(chatId, `Job #${id} cancelled.`, { parseMode: "plain" });
|
|
16688
17068
|
await sendJobsBoard(chatId, channel, 1);
|
|
16689
17069
|
} else {
|
|
16690
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
17070
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16691
17071
|
}
|
|
16692
17072
|
} else if (rest.startsWith("cancel:")) {
|
|
16693
17073
|
const id = parseInt(rest.slice(7), 10);
|
|
16694
17074
|
const job = getJobById(id);
|
|
16695
17075
|
if (!job) {
|
|
16696
|
-
await channel.sendText(chatId, `Job #${id} not found.`, "plain");
|
|
17076
|
+
await channel.sendText(chatId, `Job #${id} not found.`, { parseMode: "plain" });
|
|
16697
17077
|
return;
|
|
16698
17078
|
}
|
|
16699
17079
|
if (typeof channel.sendKeyboard === "function") {
|
|
@@ -16747,7 +17127,7 @@ Command: ${command}`,
|
|
|
16747
17127
|
);
|
|
16748
17128
|
} else {
|
|
16749
17129
|
await channel.sendText(chatId, `\u26A0\uFE0F Destructive command blocked: ${command}
|
|
16750
|
-
No keyboard available to confirm.`, "plain");
|
|
17130
|
+
No keyboard available to confirm.`, { parseMode: "plain" });
|
|
16751
17131
|
}
|
|
16752
17132
|
return;
|
|
16753
17133
|
}
|
|
@@ -16764,9 +17144,9 @@ No keyboard available to confirm.`, "plain");
|
|
|
16764
17144
|
if (shouldSendAsFile(formatted)) {
|
|
16765
17145
|
const buffer = Buffer.from(result.output, "utf-8");
|
|
16766
17146
|
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");
|
|
17147
|
+
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, { parseMode: "plain" });
|
|
16768
17148
|
} else {
|
|
16769
|
-
await channel.sendText(chatId, formatted, "html");
|
|
17149
|
+
await channel.sendText(chatId, formatted, { parseMode: "html" });
|
|
16770
17150
|
}
|
|
16771
17151
|
}
|
|
16772
17152
|
async function handleRawShell(command, chatId, channel, skipGuard = false) {
|
|
@@ -16785,7 +17165,7 @@ Command: ${command}`,
|
|
|
16785
17165
|
);
|
|
16786
17166
|
} else {
|
|
16787
17167
|
await channel.sendText(chatId, `\u26A0\uFE0F Destructive command blocked: ${command}
|
|
16788
|
-
No keyboard available to confirm.`, "plain");
|
|
17168
|
+
No keyboard available to confirm.`, { parseMode: "plain" });
|
|
16789
17169
|
}
|
|
16790
17170
|
return;
|
|
16791
17171
|
}
|
|
@@ -16802,9 +17182,9 @@ No keyboard available to confirm.`, "plain");
|
|
|
16802
17182
|
if (shouldSendAsFile(formatted)) {
|
|
16803
17183
|
const buffer = Buffer.from(result.output, "utf-8");
|
|
16804
17184
|
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");
|
|
17185
|
+
await channel.sendText(chatId, `Output too long (${result.output.length} chars), sent as file.`, { parseMode: "plain" });
|
|
16806
17186
|
} else {
|
|
16807
|
-
await channel.sendText(chatId, formatted, "plain");
|
|
17187
|
+
await channel.sendText(chatId, formatted, { parseMode: "plain" });
|
|
16808
17188
|
}
|
|
16809
17189
|
}
|
|
16810
17190
|
async function sendCwdSessionChoice(chatId, path, channel) {
|
|
@@ -16823,7 +17203,7 @@ What would you like to do?`,
|
|
|
16823
17203
|
);
|
|
16824
17204
|
} else {
|
|
16825
17205
|
await channel.sendText(chatId, `Working directory set to: ${path}
|
|
16826
|
-
Session kept.`, "plain");
|
|
17206
|
+
Session kept.`, { parseMode: "plain" });
|
|
16827
17207
|
}
|
|
16828
17208
|
}
|
|
16829
17209
|
function parseIntervalToMs(input) {
|
|
@@ -16884,7 +17264,7 @@ async function sendSkillsPage(chatId, channel, skills2, page) {
|
|
|
16884
17264
|
const header3 = totalPages > 1 ? `Skills (page ${safePage}/${totalPages}, ${skills2.length} total):` : "Available skills:";
|
|
16885
17265
|
const footer = totalPages > 1 ? `
|
|
16886
17266
|
Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
16887
|
-
await channel.sendText(chatId, [header3, "", ...lines, footer].join("\n"), "plain");
|
|
17267
|
+
await channel.sendText(chatId, [header3, "", ...lines, footer].join("\n"), { parseMode: "plain" });
|
|
16888
17268
|
return;
|
|
16889
17269
|
}
|
|
16890
17270
|
const buttons = pageSkills.map((s) => {
|
|
@@ -16901,7 +17281,7 @@ Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
|
16901
17281
|
const header2 = totalPages > 1 ? `${skills2.length} skills (page ${safePage}/${totalPages}). Select one to invoke:` : `${skills2.length} skills available. Select one to invoke:`;
|
|
16902
17282
|
await channel.sendKeyboard(chatId, header2, buttons);
|
|
16903
17283
|
}
|
|
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;
|
|
17284
|
+
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS, activeProposalDiscussion, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
|
|
16905
17285
|
var init_router = __esm({
|
|
16906
17286
|
"src/router.ts"() {
|
|
16907
17287
|
"use strict";
|
|
@@ -17040,6 +17420,9 @@ var init_router = __esm({
|
|
|
17040
17420
|
];
|
|
17041
17421
|
pendingInterrupts = /* @__PURE__ */ new Map();
|
|
17042
17422
|
bypassBusyCheck = /* @__PURE__ */ new Set();
|
|
17423
|
+
activeSideQuests = /* @__PURE__ */ new Map();
|
|
17424
|
+
MAX_SIDE_QUESTS = 2;
|
|
17425
|
+
activeProposalDiscussion = /* @__PURE__ */ new Map();
|
|
17043
17426
|
pendingFallbackMessages = /* @__PURE__ */ new Map();
|
|
17044
17427
|
dashboardClawWarnings = /* @__PURE__ */ new Map();
|
|
17045
17428
|
pendingSummaryUndo = /* @__PURE__ */ new Map();
|
|
@@ -17502,9 +17885,64 @@ Use the CC-Claw CLI when you need to:
|
|
|
17502
17885
|
|
|
17503
17886
|
## Telegram Quick Reference
|
|
17504
17887
|
|
|
17505
|
-
|
|
17506
|
-
- \`/
|
|
17507
|
-
-
|
|
17888
|
+
**Navigation & help:**
|
|
17889
|
+
- \`/menu\` (\`/m\`) \u2014 Home screen keyboard
|
|
17890
|
+
- \`/help\` (\`/start\`) \u2014 Help categories keyboard
|
|
17891
|
+
- \`/usage\` \u2014 Unified cost, limits, usage (\`/cost\` and \`/limits\` are aliases)
|
|
17892
|
+
- \`@botname <query>\` \u2014 Inline mode: memory/history search from any chat
|
|
17893
|
+
|
|
17894
|
+
**Session & history:**
|
|
17895
|
+
- \`/newchat\` (\`/new\`) \u2014 Start fresh conversation (with undo)
|
|
17896
|
+
- \`/summarize\` \u2014 Save session to memory (\`/summarize all\` for all pending)
|
|
17897
|
+
- \`/history\` \u2014 Recent messages (\`/history <query>\` for FTS search)
|
|
17898
|
+
- \`/stop\` \u2014 Cancel running task + any active side quests
|
|
17899
|
+
|
|
17900
|
+
**Side quests (parallel execution):**
|
|
17901
|
+
- \`sq: <message>\` or \`btw: <message>\` \u2014 Run in parallel while agent is busy (full tool access, shared context, max 2 concurrent, 5-min timeout)
|
|
17902
|
+
- Also available as "Side quest" button on the interrupt keyboard
|
|
17903
|
+
|
|
17904
|
+
**Backend & model:**
|
|
17905
|
+
- \`/backend\` \u2014 Backend picker keyboard
|
|
17906
|
+
- \`/claude\`, \`/gemini\`, \`/codex\`, \`/cursor\` \u2014 Switch directly
|
|
17907
|
+
- \`/model\` \u2014 Model picker keyboard
|
|
17908
|
+
- \`/thinking\` (\`/think\`) \u2014 Thinking level picker
|
|
17909
|
+
|
|
17910
|
+
**Settings keyboards:**
|
|
17911
|
+
- \`/permissions\` \u2014 Permission mode (yolo/safe/readonly/plan)
|
|
17912
|
+
- \`/tools\` \u2014 Enable/disable tools (safe mode)
|
|
17913
|
+
- \`/response_style\` \u2014 Concise / normal / detailed
|
|
17914
|
+
- \`/model_signature\` \u2014 Show/hide model name on responses
|
|
17915
|
+
- \`/agents mode\` \u2014 Agent mode (auto/native/claw)
|
|
17916
|
+
- \`/voice_config\` \u2014 Voice provider settings
|
|
17917
|
+
|
|
17918
|
+
**Memory:**
|
|
17919
|
+
- \`/remember <text>\` \u2014 Save a memory
|
|
17920
|
+
- \`/forget <keyword>\` \u2014 Delete memories
|
|
17921
|
+
- \`/memories\` \u2014 List memories
|
|
17922
|
+
|
|
17923
|
+
**Scheduling (interactive wizards):**
|
|
17924
|
+
- \`/schedule <description>\` \u2014 Create job via wizard
|
|
17925
|
+
- \`/jobs\` \u2014 Paginated job board
|
|
17926
|
+
- \`/editjob\` \u2014 Edit job wizard
|
|
17927
|
+
- \`/cancel\`, \`/pause\`, \`/resume\`, \`/run\`, \`/runs\` \u2014 Job action shortcuts
|
|
17928
|
+
- \`/health\` \u2014 Scheduler health
|
|
17929
|
+
|
|
17930
|
+
**Agents:**
|
|
17931
|
+
- \`/agents\` \u2014 Agent dashboard
|
|
17932
|
+
- \`/agents history\` \u2014 Recent sub-agent activity
|
|
17933
|
+
- \`/tasks\` \u2014 Task board
|
|
17934
|
+
- \`/stopagent\` \u2014 Interactive agent picker to stop
|
|
17935
|
+
- \`/stopall\` \u2014 Cancel all agents
|
|
17936
|
+
- \`/runners\` \u2014 List CLI runners
|
|
17937
|
+
|
|
17938
|
+
**Other:**
|
|
17939
|
+
- \`/imagine <prompt>\` (\`/image\`) \u2014 Generate image (requires GEMINI_API_KEY)
|
|
17940
|
+
- \`/skills\` \u2014 List skills
|
|
17941
|
+
- \`/skill-install <url>\` \u2014 Install skill from GitHub
|
|
17942
|
+
- \`/evolve\` \u2014 Self-learning interactive keyboard
|
|
17943
|
+
- \`/reflect\` \u2014 Trigger reflection analysis
|
|
17944
|
+
- \`/gemini_accounts\` \u2014 Gemini credential rotation management
|
|
17945
|
+
- \`/setup-profile\` \u2014 User profile setup wizard
|
|
17508
17946
|
|
|
17509
17947
|
## Command Reference
|
|
17510
17948
|
|
|
@@ -17516,6 +17954,7 @@ cc-claw doctor --json # Health checks (DB, CLIs, env, disk)
|
|
|
17516
17954
|
cc-claw doctor --fix --json # Auto-repair common issues
|
|
17517
17955
|
cc-claw logs -f # Follow daemon logs
|
|
17518
17956
|
cc-claw logs --error # Show error log
|
|
17957
|
+
cc-claw logs --lines 50 # Show last N lines
|
|
17519
17958
|
\`\`\`
|
|
17520
17959
|
|
|
17521
17960
|
### Backend & Model
|
|
@@ -17532,8 +17971,10 @@ cc-claw model set claude-opus-4-6 # Switch model
|
|
|
17532
17971
|
\`\`\`bash
|
|
17533
17972
|
cc-claw chat send "What is 2+2?" --json # Send message, get response
|
|
17534
17973
|
cc-claw chat send "analyze this" --stream # Stream response tokens
|
|
17535
|
-
cc-claw chat
|
|
17536
|
-
cc-claw
|
|
17974
|
+
cc-claw chat send "msg" --backend gemini --model gemini-3-flash-preview # Override backend/model
|
|
17975
|
+
cc-claw chat send "msg" --thinking high --cwd /path # Override thinking/cwd
|
|
17976
|
+
cc-claw chat stop # Cancel running task + side quests
|
|
17977
|
+
cc-claw tui --model claude-opus-4-6 # Interactive chat with model override
|
|
17537
17978
|
\`\`\`
|
|
17538
17979
|
|
|
17539
17980
|
### Memory
|
|
@@ -17541,6 +17982,7 @@ cc-claw tui # Interactive terminal chat
|
|
|
17541
17982
|
cc-claw memory list --json # All memories with salience
|
|
17542
17983
|
cc-claw memory search "topic" --json # Search memories
|
|
17543
17984
|
cc-claw memory history --json # Session summaries
|
|
17985
|
+
cc-claw memory history --limit 20 --json # Limit results
|
|
17544
17986
|
cc-claw memory add "key" "value" # Save a memory (needs daemon)
|
|
17545
17987
|
cc-claw memory forget "keyword" # Delete memories (needs daemon)
|
|
17546
17988
|
\`\`\`
|
|
@@ -17555,7 +17997,8 @@ cc-claw session new # Clear session (newchat + summarize)
|
|
|
17555
17997
|
\`\`\`bash
|
|
17556
17998
|
cc-claw cron list --json # All scheduled jobs
|
|
17557
17999
|
cc-claw cron health --json # Scheduler health
|
|
17558
|
-
cc-claw cron runs --json # Run history
|
|
18000
|
+
cc-claw cron runs --json # Run history (all jobs)
|
|
18001
|
+
cc-claw cron runs 3 --limit 10 --json # Run history for job #3
|
|
17559
18002
|
cc-claw cron create --description "Morning briefing" --cron "0 9 * * *" --backend claude
|
|
17560
18003
|
cc-claw cron edit 3 --model gemini-3-flash-preview # Change job model
|
|
17561
18004
|
cc-claw cron edit 3 --backend gemini --model gemini-3-flash-preview # Change backend + model
|
|
@@ -17572,6 +18015,7 @@ cc-claw cron run 3 # Trigger immediately
|
|
|
17572
18015
|
\`\`\`bash
|
|
17573
18016
|
cc-claw agents list --json # Active sub-agents
|
|
17574
18017
|
cc-claw agents spawn --runner claude --task "review code" --json
|
|
18018
|
+
cc-claw agents spawn --runner gemini --task "analyze" --model gemini-3-flash-preview --role worker
|
|
17575
18019
|
cc-claw agents cancel <id> # Cancel agent
|
|
17576
18020
|
cc-claw agents cancel-all # Cancel all
|
|
17577
18021
|
cc-claw tasks list --json # Task board
|
|
@@ -17584,6 +18028,8 @@ cc-claw config list --json # All runtime config
|
|
|
17584
18028
|
cc-claw config get backend --json # Specific config value
|
|
17585
18029
|
cc-claw config set backend gemini # Set config (needs daemon)
|
|
17586
18030
|
cc-claw config env --json # Static .env values (redacted)
|
|
18031
|
+
cc-claw config response-style # Get current response style
|
|
18032
|
+
cc-claw config response-style detailed # Set response style (concise/normal/detailed)
|
|
17587
18033
|
\`\`\`
|
|
17588
18034
|
|
|
17589
18035
|
### Usage & Cost
|
|
@@ -17656,6 +18102,37 @@ cc-claw summarizer set off # Disable summarization
|
|
|
17656
18102
|
cc-claw summarizer set claude:claude-haiku-4-5 # Pin specific backend:model
|
|
17657
18103
|
\`\`\`
|
|
17658
18104
|
|
|
18105
|
+
### Gemini Credentials
|
|
18106
|
+
\`\`\`bash
|
|
18107
|
+
cc-claw gemini list --json # Show all credential slots (API keys + OAuth accounts)
|
|
18108
|
+
cc-claw gemini add-key --label "work" # Add an API key slot
|
|
18109
|
+
cc-claw gemini add-account --label "personal" # Add OAuth account (browser sign-in)
|
|
18110
|
+
cc-claw gemini remove <id-or-label> # Remove a credential slot
|
|
18111
|
+
cc-claw gemini enable <id-or-label> # Enable a disabled slot
|
|
18112
|
+
cc-claw gemini disable <id-or-label> # Disable a slot (skip in rotation)
|
|
18113
|
+
cc-claw gemini reorder <id-or-label> <priority> # Change rotation priority
|
|
18114
|
+
cc-claw gemini rotation # Get current rotation mode
|
|
18115
|
+
cc-claw gemini rotation all # Set mode (off/all/accounts/keys)
|
|
18116
|
+
\`\`\`
|
|
18117
|
+
|
|
18118
|
+
### Self-Learning (evolve)
|
|
18119
|
+
\`\`\`bash
|
|
18120
|
+
cc-claw evolve --json # Status overview
|
|
18121
|
+
cc-claw evolve analyze # Trigger reflection analysis
|
|
18122
|
+
cc-claw evolve list --json # Pending proposals
|
|
18123
|
+
cc-claw evolve get <id> --json # Show proposal with diff
|
|
18124
|
+
cc-claw evolve apply <id> # Apply a proposal
|
|
18125
|
+
cc-claw evolve reject <id> # Reject a proposal
|
|
18126
|
+
cc-claw evolve undo <id> # Rollback applied insight
|
|
18127
|
+
cc-claw evolve on # Enable self-learning
|
|
18128
|
+
cc-claw evolve off # Disable self-learning
|
|
18129
|
+
cc-claw evolve model auto # Set analysis model (auto/pinned/cheap)
|
|
18130
|
+
cc-claw evolve model pinned --backend claude --model claude-haiku-4-5
|
|
18131
|
+
cc-claw evolve stats --days 30 --json # Growth report
|
|
18132
|
+
cc-claw evolve history --json # Applied/rejected insight history
|
|
18133
|
+
cc-claw evolve history --status applied --limit 10 # Filter history
|
|
18134
|
+
\`\`\`
|
|
18135
|
+
|
|
17659
18136
|
### Chat Aliases
|
|
17660
18137
|
\`\`\`bash
|
|
17661
18138
|
cc-claw chats list --json # Authorized chats and aliases
|
|
@@ -17678,8 +18155,7 @@ cc-claw mcps list --json # Registered MCP servers
|
|
|
17678
18155
|
\`\`\`bash
|
|
17679
18156
|
cc-claw db stats --json # Row counts, file size, WAL status
|
|
17680
18157
|
cc-claw db path # Print DB file location
|
|
17681
|
-
cc-claw db backup
|
|
17682
|
-
cc-claw db prune # Prune old data
|
|
18158
|
+
cc-claw db backup [path] # Create backup (optional destination)
|
|
17683
18159
|
\`\`\`
|
|
17684
18160
|
|
|
17685
18161
|
### Service Management
|
|
@@ -17697,6 +18173,7 @@ cc-claw service uninstall # Remove service
|
|
|
17697
18173
|
cc-claw setup # Interactive configuration wizard
|
|
17698
18174
|
cc-claw tui # Interactive terminal chat
|
|
17699
18175
|
cc-claw completion --shell zsh # Generate shell completions (bash/zsh/fish)
|
|
18176
|
+
cc-claw completion --shell zsh --install # Show install instructions
|
|
17700
18177
|
cc-claw --ai # Generate/install SKILL.md for AI tools
|
|
17701
18178
|
\`\`\`
|
|
17702
18179
|
|
|
@@ -17873,7 +18350,7 @@ async function main() {
|
|
|
17873
18350
|
pendingSummarizeNotify = () => {
|
|
17874
18351
|
if (primaryChatId) {
|
|
17875
18352
|
for (const ch of channelRegistry.list()) {
|
|
17876
|
-
ch.sendText(primaryChatId, "\u{1F504} Restarted \u2014 your conversations were summarized and saved.", "plain").catch(() => {
|
|
18353
|
+
ch.sendText(primaryChatId, "\u{1F504} Restarted \u2014 your conversations were summarized and saved.", { parseMode: "plain" }).catch(() => {
|
|
17877
18354
|
});
|
|
17878
18355
|
}
|
|
17879
18356
|
}
|
|
@@ -17900,7 +18377,7 @@ async function main() {
|
|
|
17900
18377
|
setNotifyCallback((chatId, message) => {
|
|
17901
18378
|
notifyQueue = notifyQueue.then(async () => {
|
|
17902
18379
|
for (const ch of channelRegistry.list()) {
|
|
17903
|
-
await ch.sendText(chatId, `\u{1F916} ${message}`, "plain").catch(() => {
|
|
18380
|
+
await ch.sendText(chatId, `\u{1F916} ${message}`, { parseMode: "plain" }).catch(() => {
|
|
17904
18381
|
});
|
|
17905
18382
|
}
|
|
17906
18383
|
await new Promise((r) => setTimeout(r, 300));
|