cc-claw 0.18.0 → 0.18.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 +699 -275
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var VERSION;
|
|
|
33
33
|
var init_version = __esm({
|
|
34
34
|
"src/version.ts"() {
|
|
35
35
|
"use strict";
|
|
36
|
-
VERSION = true ? "0.18.
|
|
36
|
+
VERSION = true ? "0.18.1" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -57,6 +57,7 @@ __export(paths_exports, {
|
|
|
57
57
|
LOG_PATH: () => LOG_PATH,
|
|
58
58
|
MEDIA_PATH: () => MEDIA_PATH,
|
|
59
59
|
RUNNERS_PATH: () => RUNNERS_PATH,
|
|
60
|
+
SESSION_LOGS_PATH: () => SESSION_LOGS_PATH,
|
|
60
61
|
SKILLS_PATH: () => SKILLS_PATH,
|
|
61
62
|
WORKSPACE_PATH: () => WORKSPACE_PATH
|
|
62
63
|
});
|
|
@@ -70,7 +71,7 @@ function resolveRealHome() {
|
|
|
70
71
|
}
|
|
71
72
|
return homedir();
|
|
72
73
|
}
|
|
73
|
-
var CC_CLAW_HOME, ENV_PATH, DATA_PATH, DB_PATH, LOGS_PATH, LOG_PATH, ERROR_LOG_PATH, IDENTITY_PATH, WORKSPACE_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH, MEDIA_PATH;
|
|
74
|
+
var CC_CLAW_HOME, ENV_PATH, DATA_PATH, DB_PATH, LOGS_PATH, LOG_PATH, ERROR_LOG_PATH, IDENTITY_PATH, WORKSPACE_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH, SESSION_LOGS_PATH, MEDIA_PATH;
|
|
74
75
|
var init_paths = __esm({
|
|
75
76
|
"src/paths.ts"() {
|
|
76
77
|
"use strict";
|
|
@@ -86,6 +87,7 @@ var init_paths = __esm({
|
|
|
86
87
|
SKILLS_PATH = join2(WORKSPACE_PATH, "skills");
|
|
87
88
|
RUNNERS_PATH = join2(CC_CLAW_HOME, "runners");
|
|
88
89
|
AGENTS_PATH = join2(CC_CLAW_HOME, "agents");
|
|
90
|
+
SESSION_LOGS_PATH = join2(LOGS_PATH, "sessions");
|
|
89
91
|
MEDIA_PATH = join2(CC_CLAW_HOME, "media");
|
|
90
92
|
}
|
|
91
93
|
});
|
|
@@ -1749,6 +1751,12 @@ function initSchema(db3) {
|
|
|
1749
1751
|
value INTEGER NOT NULL DEFAULT 0
|
|
1750
1752
|
);
|
|
1751
1753
|
`);
|
|
1754
|
+
db3.exec(`
|
|
1755
|
+
CREATE TABLE IF NOT EXISTS chat_session_log (
|
|
1756
|
+
chat_id TEXT PRIMARY KEY,
|
|
1757
|
+
value INTEGER NOT NULL DEFAULT 0
|
|
1758
|
+
);
|
|
1759
|
+
`);
|
|
1752
1760
|
db3.exec(`
|
|
1753
1761
|
CREATE TABLE IF NOT EXISTS backend_credentials (
|
|
1754
1762
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -2456,6 +2464,7 @@ __export(chat_settings_exports, {
|
|
|
2456
2464
|
getModel: () => getModel,
|
|
2457
2465
|
getPendingEscalation: () => getPendingEscalation,
|
|
2458
2466
|
getRecentBookmarks: () => getRecentBookmarks,
|
|
2467
|
+
getSessionLogEnabled: () => getSessionLogEnabled,
|
|
2459
2468
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
2460
2469
|
getSummarizer: () => getSummarizer,
|
|
2461
2470
|
getThinkingLevel: () => getThinkingLevel,
|
|
@@ -2469,11 +2478,13 @@ __export(chat_settings_exports, {
|
|
|
2469
2478
|
setExecMode: () => setExecMode,
|
|
2470
2479
|
setMode: () => setMode,
|
|
2471
2480
|
setModel: () => setModel,
|
|
2481
|
+
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
2472
2482
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
2473
2483
|
setSummarizer: () => setSummarizer,
|
|
2474
2484
|
setThinkingLevel: () => setThinkingLevel,
|
|
2475
2485
|
setVerboseLevel: () => setVerboseLevel,
|
|
2476
2486
|
storePendingEscalation: () => storePendingEscalation,
|
|
2487
|
+
toggleSessionLogEnabled: () => toggleSessionLogEnabled,
|
|
2477
2488
|
toggleShowThinkingUi: () => toggleShowThinkingUi,
|
|
2478
2489
|
toggleTool: () => toggleTool,
|
|
2479
2490
|
touchBookmark: () => touchBookmark,
|
|
@@ -2744,6 +2755,25 @@ function setExecMode(chatId, mode) {
|
|
|
2744
2755
|
function clearExecMode(chatId) {
|
|
2745
2756
|
getDb().prepare("DELETE FROM chat_exec_mode WHERE chat_id = ?").run(chatId);
|
|
2746
2757
|
}
|
|
2758
|
+
function getSessionLogEnabled(chatId) {
|
|
2759
|
+
const row = getDb().prepare(
|
|
2760
|
+
"SELECT value FROM chat_session_log WHERE chat_id = ?"
|
|
2761
|
+
).get(chatId);
|
|
2762
|
+
return (row?.value ?? 0) === 1;
|
|
2763
|
+
}
|
|
2764
|
+
function setSessionLogEnabled(chatId, enabled) {
|
|
2765
|
+
getDb().prepare(`
|
|
2766
|
+
INSERT INTO chat_session_log (chat_id, value)
|
|
2767
|
+
VALUES (?, ?)
|
|
2768
|
+
ON CONFLICT(chat_id) DO UPDATE SET value = ?
|
|
2769
|
+
`).run(chatId, enabled ? 1 : 0, enabled ? 1 : 0);
|
|
2770
|
+
}
|
|
2771
|
+
function toggleSessionLogEnabled(chatId) {
|
|
2772
|
+
const current = getSessionLogEnabled(chatId);
|
|
2773
|
+
const next = !current;
|
|
2774
|
+
setSessionLogEnabled(chatId, next);
|
|
2775
|
+
return next;
|
|
2776
|
+
}
|
|
2747
2777
|
var pendingEscalations, ESCALATION_TTL_MS, ALL_TOOLS;
|
|
2748
2778
|
var init_chat_settings = __esm({
|
|
2749
2779
|
"src/memory/chat-settings.ts"() {
|
|
@@ -3608,6 +3638,7 @@ __export(store_exports5, {
|
|
|
3608
3638
|
getRecentMessageLog: () => getRecentMessageLog,
|
|
3609
3639
|
getResponseStyle: () => getResponseStyle,
|
|
3610
3640
|
getSessionId: () => getSessionId,
|
|
3641
|
+
getSessionLogEnabled: () => getSessionLogEnabled,
|
|
3611
3642
|
getSessionStartedAt: () => getSessionStartedAt,
|
|
3612
3643
|
getSessionSummaries: () => getSessionSummaries,
|
|
3613
3644
|
getSessionSummariesWithoutEmbeddings: () => getSessionSummariesWithoutEmbeddings,
|
|
@@ -3670,6 +3701,7 @@ __export(store_exports5, {
|
|
|
3670
3701
|
setModelSignature: () => setModelSignature,
|
|
3671
3702
|
setResponseStyle: () => setResponseStyle,
|
|
3672
3703
|
setSessionId: () => setSessionId,
|
|
3704
|
+
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
3673
3705
|
setSessionStartedAt: () => setSessionStartedAt,
|
|
3674
3706
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
3675
3707
|
setSummarizer: () => setSummarizer,
|
|
@@ -3677,6 +3709,7 @@ __export(store_exports5, {
|
|
|
3677
3709
|
setVerboseLevel: () => setVerboseLevel,
|
|
3678
3710
|
storePendingEscalation: () => storePendingEscalation,
|
|
3679
3711
|
toFts5Query: () => toFts5Query,
|
|
3712
|
+
toggleSessionLogEnabled: () => toggleSessionLogEnabled,
|
|
3680
3713
|
toggleShowThinkingUi: () => toggleShowThinkingUi,
|
|
3681
3714
|
toggleTool: () => toggleTool,
|
|
3682
3715
|
touchBookmark: () => touchBookmark,
|
|
@@ -10359,11 +10392,11 @@ var init_evolve = __esm({
|
|
|
10359
10392
|
const body = JSON.parse(await readBody(req));
|
|
10360
10393
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
10361
10394
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
10362
|
-
const { join:
|
|
10395
|
+
const { join: join35 } = await import("path");
|
|
10363
10396
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
10364
10397
|
const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
|
|
10365
|
-
const soulPath =
|
|
10366
|
-
const userPath =
|
|
10398
|
+
const soulPath = join35(home, "identity/SOUL.md");
|
|
10399
|
+
const userPath = join35(home, "identity/USER.md");
|
|
10367
10400
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
10368
10401
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
10369
10402
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -13400,18 +13433,18 @@ function formatToolStart(toolName, input, level) {
|
|
|
13400
13433
|
return `\u{1F527} ${toolName}${cmd ? `: ${cmd}` : path ? `: ${path}` : query ? `: ${query}` : ""}`;
|
|
13401
13434
|
}
|
|
13402
13435
|
}
|
|
13403
|
-
const inputStr = JSON.stringify(input, null, 2).slice(0,
|
|
13436
|
+
const inputStr = JSON.stringify(input, null, 2).slice(0, 300);
|
|
13404
13437
|
return `\u{1F527} ${toolName}:
|
|
13405
13438
|
\`\`\`json
|
|
13406
13439
|
${inputStr}
|
|
13407
13440
|
\`\`\``;
|
|
13408
13441
|
}
|
|
13409
13442
|
function formatToolResult(toolName, result) {
|
|
13410
|
-
const trimmed = result.trim().slice(0,
|
|
13443
|
+
const trimmed = result.trim().slice(0, 250);
|
|
13411
13444
|
if (!trimmed) return "";
|
|
13412
13445
|
const firstLine = trimmed.split("\n")[0] ?? "";
|
|
13413
13446
|
const isError = /error|failed|exception/i.test(firstLine);
|
|
13414
|
-
return isError ? `\u274C ${firstLine.slice(0, 120)}` : `\u{
|
|
13447
|
+
return isError ? `\u274C ${firstLine.slice(0, 120)}` : `\u{1F4EC} Result:
|
|
13415
13448
|
\`\`\`
|
|
13416
13449
|
${trimmed}
|
|
13417
13450
|
\`\`\``;
|
|
@@ -16478,13 +16511,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
16478
16511
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16479
16512
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
16480
16513
|
if (current === "frozen") {
|
|
16481
|
-
const { readFileSync:
|
|
16482
|
-
const { join:
|
|
16514
|
+
const { readFileSync: readFileSync27, existsSync: existsSync56 } = await import("fs");
|
|
16515
|
+
const { join: join35 } = await import("path");
|
|
16483
16516
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
16484
|
-
const soulPath =
|
|
16485
|
-
const userPath =
|
|
16486
|
-
const soul =
|
|
16487
|
-
const user =
|
|
16517
|
+
const soulPath = join35(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16518
|
+
const userPath = join35(CC_CLAW_HOME3, "identity/USER.md");
|
|
16519
|
+
const soul = existsSync56(soulPath) ? readFileSync27(soulPath, "utf-8") : "";
|
|
16520
|
+
const user = existsSync56(userPath) ? readFileSync27(userPath, "utf-8") : "";
|
|
16488
16521
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
16489
16522
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16490
16523
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -18395,8 +18428,8 @@ ${lines.join("\n")}`, { parseMode: "plain" });
|
|
|
18395
18428
|
if (arg.startsWith("/") || arg.startsWith("~")) {
|
|
18396
18429
|
const resolvedPath = arg.startsWith("~") ? arg.replace("~", process.env.HOME ?? "") : arg;
|
|
18397
18430
|
setCwd(chatId, resolvedPath);
|
|
18398
|
-
const
|
|
18399
|
-
if (
|
|
18431
|
+
const basename4 = resolvedPath.split("/").filter(Boolean).pop();
|
|
18432
|
+
if (basename4) upsertBookmark(chatId, basename4, resolvedPath, false);
|
|
18400
18433
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Working directory set to ${resolvedPath}`, detail: { field: "cwd", value: resolvedPath } });
|
|
18401
18434
|
await sendCwdSessionChoice(chatId, resolvedPath, channel);
|
|
18402
18435
|
return;
|
|
@@ -18572,7 +18605,9 @@ Use /model to pick a model with \u26A1 thinking support.`, { parseMode: "plain"
|
|
|
18572
18605
|
chatId,
|
|
18573
18606
|
`\u{1F4AD} Thinking Level \u2014 ${shortModelName(currentModel)}
|
|
18574
18607
|
Current: ${capitalize(currentLevel)}
|
|
18575
|
-
Show thinking tokens: ${showThinkingUi ? "On" : "Off"}${adapter.id
|
|
18608
|
+
Show thinking tokens: ${showThinkingUi ? "On" : "Off"}${adapter.id !== "claude" ? `
|
|
18609
|
+
|
|
18610
|
+
\u26A0\uFE0F ${adapter.displayName} CLI doesn't stream thinking tokens` : ""}`,
|
|
18576
18611
|
buttons
|
|
18577
18612
|
);
|
|
18578
18613
|
} else {
|
|
@@ -18584,6 +18619,37 @@ Set via callback (keyboard required).`, { parseMode: "plain" });
|
|
|
18584
18619
|
}
|
|
18585
18620
|
break;
|
|
18586
18621
|
}
|
|
18622
|
+
case "debug": {
|
|
18623
|
+
const { getSessionLogEnabled: getSessionLogEnabled2, toggleSessionLogEnabled: toggleSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
18624
|
+
const current = getSessionLogEnabled2(chatId);
|
|
18625
|
+
if (commandArgs === "on" || commandArgs === "off") {
|
|
18626
|
+
const { setSessionLogEnabled: setSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
18627
|
+
const value = commandArgs === "on";
|
|
18628
|
+
setSessionLogEnabled2(chatId, value);
|
|
18629
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${value ? "ON" : "OFF"}
|
|
18630
|
+
|
|
18631
|
+
${value ? "Full tool inputs/results will be saved to ~/.cc-claw/logs/sessions/\nUse 'cc-claw logs session list' or 'cc-claw logs session tail' to inspect." : "Session logs disabled."}`, { parseMode: "plain" });
|
|
18632
|
+
} else if (typeof channel.sendKeyboard === "function") {
|
|
18633
|
+
await channel.sendKeyboard(
|
|
18634
|
+
chatId,
|
|
18635
|
+
`\u{1F52C} Session Debug Logging
|
|
18636
|
+
|
|
18637
|
+
Records full, untruncated tool inputs and results to disk for debugging.
|
|
18638
|
+
Logs: ~/.cc-claw/logs/sessions/
|
|
18639
|
+
Retention: ${process.env.SESSION_LOG_RETENTION_DAYS ?? "7"} day(s)
|
|
18640
|
+
|
|
18641
|
+
Currently: ${current ? "ON" : "OFF"}`,
|
|
18642
|
+
[[
|
|
18643
|
+
{ label: current ? "\u2713 ON" : "ON", data: "debug_log:on", ...current ? { style: "primary" } : {} },
|
|
18644
|
+
{ label: !current ? "\u2713 OFF" : "OFF", data: "debug_log:off", ...!current ? { style: "primary" } : {} }
|
|
18645
|
+
]]
|
|
18646
|
+
);
|
|
18647
|
+
} else {
|
|
18648
|
+
const next = toggleSessionLogEnabled2(chatId);
|
|
18649
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${next ? "ON" : "OFF"}`, { parseMode: "plain" });
|
|
18650
|
+
}
|
|
18651
|
+
break;
|
|
18652
|
+
}
|
|
18587
18653
|
case "imagine":
|
|
18588
18654
|
case "image": {
|
|
18589
18655
|
if (!commandArgs) {
|
|
@@ -19494,11 +19560,19 @@ Select thinking/effort level:`,
|
|
|
19494
19560
|
backendId = getAdapterForChat(chatId).id;
|
|
19495
19561
|
} catch {
|
|
19496
19562
|
}
|
|
19497
|
-
msg = backendId
|
|
19563
|
+
msg = backendId && backendId !== "claude" ? `\u{1F4AD} Thinking tokens enabled \u2014 but ${backendId.charAt(0).toUpperCase() + backendId.slice(1)} CLI doesn't stream them.` : "\u{1F4AD} Thinking tokens will now stream live in the status message.";
|
|
19498
19564
|
} else {
|
|
19499
19565
|
msg = "\u{1F4AD} Thinking tokens hidden. Toggle on again via /thinking.";
|
|
19500
19566
|
}
|
|
19501
19567
|
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
19568
|
+
} else if (data.startsWith("debug_log:")) {
|
|
19569
|
+
const value = data.slice(10) === "on";
|
|
19570
|
+
const { setSessionLogEnabled: setSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
19571
|
+
setSessionLogEnabled2(chatId, value);
|
|
19572
|
+
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Session debug log ${value ? "enabled" : "disabled"}`, detail: { field: "session_log", value: String(value) } });
|
|
19573
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${value ? "ON" : "OFF"}
|
|
19574
|
+
|
|
19575
|
+
${value ? "Full tool inputs/results will be saved to ~/.cc-claw/logs/sessions/" : "Session logs disabled."}`, { parseMode: "plain" });
|
|
19502
19576
|
} else if (data.startsWith("summarizer:")) {
|
|
19503
19577
|
const rest = data.slice(11);
|
|
19504
19578
|
if (rest === "auto") {
|
|
@@ -20417,6 +20491,206 @@ var init_callbacks = __esm({
|
|
|
20417
20491
|
}
|
|
20418
20492
|
});
|
|
20419
20493
|
|
|
20494
|
+
// src/router/session-log.ts
|
|
20495
|
+
var session_log_exports2 = {};
|
|
20496
|
+
__export(session_log_exports2, {
|
|
20497
|
+
SessionLogFile: () => SessionLogFile,
|
|
20498
|
+
cleanupSessionLogs: () => cleanupSessionLogs,
|
|
20499
|
+
getRetentionDays: () => getRetentionDays,
|
|
20500
|
+
listSessionLogs: () => listSessionLogs,
|
|
20501
|
+
startSessionLogCleanupTimer: () => startSessionLogCleanupTimer,
|
|
20502
|
+
tailSessionLog: () => tailSessionLog
|
|
20503
|
+
});
|
|
20504
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync9, appendFileSync, readdirSync as readdirSync12, unlinkSync as unlinkSync6, statSync as statSync7, createReadStream } from "fs";
|
|
20505
|
+
import { join as join24, basename as basename3 } from "path";
|
|
20506
|
+
import { createInterface as createInterface6 } from "readline";
|
|
20507
|
+
function getRetentionDays() {
|
|
20508
|
+
const env = process.env.SESSION_LOG_RETENTION_DAYS;
|
|
20509
|
+
if (env) {
|
|
20510
|
+
const n = parseInt(env, 10);
|
|
20511
|
+
if (!isNaN(n) && n > 0) return n;
|
|
20512
|
+
}
|
|
20513
|
+
return DEFAULT_RETENTION_DAYS;
|
|
20514
|
+
}
|
|
20515
|
+
function cleanupSessionLogs(retentionDays) {
|
|
20516
|
+
const days = retentionDays ?? getRetentionDays();
|
|
20517
|
+
if (!existsSync23(SESSION_LOGS_PATH)) return 0;
|
|
20518
|
+
const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
20519
|
+
let cleaned = 0;
|
|
20520
|
+
try {
|
|
20521
|
+
for (const file of readdirSync12(SESSION_LOGS_PATH)) {
|
|
20522
|
+
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
20523
|
+
const filePath = join24(SESSION_LOGS_PATH, file);
|
|
20524
|
+
try {
|
|
20525
|
+
const { mtimeMs } = statSync7(filePath);
|
|
20526
|
+
if (mtimeMs < cutoff) {
|
|
20527
|
+
unlinkSync6(filePath);
|
|
20528
|
+
cleaned++;
|
|
20529
|
+
}
|
|
20530
|
+
} catch {
|
|
20531
|
+
}
|
|
20532
|
+
}
|
|
20533
|
+
} catch (err) {
|
|
20534
|
+
log(`[session-log] Cleanup failed: ${err}`);
|
|
20535
|
+
}
|
|
20536
|
+
if (cleaned > 0) {
|
|
20537
|
+
log(`[session-log] Cleaned ${cleaned} session log(s) older than ${days} day(s)`);
|
|
20538
|
+
}
|
|
20539
|
+
return cleaned;
|
|
20540
|
+
}
|
|
20541
|
+
function startSessionLogCleanupTimer() {
|
|
20542
|
+
const timer = setInterval(() => {
|
|
20543
|
+
cleanupSessionLogs();
|
|
20544
|
+
}, 24 * 60 * 60 * 1e3);
|
|
20545
|
+
timer.unref();
|
|
20546
|
+
return timer;
|
|
20547
|
+
}
|
|
20548
|
+
function listSessionLogs() {
|
|
20549
|
+
if (!existsSync23(SESSION_LOGS_PATH)) return [];
|
|
20550
|
+
const logs = [];
|
|
20551
|
+
for (const file of readdirSync12(SESSION_LOGS_PATH)) {
|
|
20552
|
+
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
20553
|
+
const filePath = join24(SESSION_LOGS_PATH, file);
|
|
20554
|
+
try {
|
|
20555
|
+
const stat4 = statSync7(filePath);
|
|
20556
|
+
const match = file.match(/^session-(.+?)-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})\.log$/);
|
|
20557
|
+
logs.push({
|
|
20558
|
+
filename: file,
|
|
20559
|
+
filePath,
|
|
20560
|
+
chatId: match?.[1] ?? "unknown",
|
|
20561
|
+
timestamp: match?.[2]?.replace(/-/g, (m, i) => i > 9 ? ":" : m) ?? "unknown",
|
|
20562
|
+
sizeBytes: stat4.size,
|
|
20563
|
+
modifiedAt: stat4.mtime
|
|
20564
|
+
});
|
|
20565
|
+
} catch {
|
|
20566
|
+
}
|
|
20567
|
+
}
|
|
20568
|
+
logs.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
20569
|
+
return logs;
|
|
20570
|
+
}
|
|
20571
|
+
async function* tailSessionLog(filePath, lines = 50) {
|
|
20572
|
+
if (!existsSync23(filePath)) {
|
|
20573
|
+
yield `File not found: ${filePath}`;
|
|
20574
|
+
return;
|
|
20575
|
+
}
|
|
20576
|
+
const allLines = [];
|
|
20577
|
+
const rl2 = createInterface6({
|
|
20578
|
+
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
20579
|
+
crlfDelay: Infinity
|
|
20580
|
+
});
|
|
20581
|
+
for await (const line of rl2) {
|
|
20582
|
+
allLines.push(line);
|
|
20583
|
+
}
|
|
20584
|
+
const start = Math.max(0, allLines.length - lines);
|
|
20585
|
+
for (let i = start; i < allLines.length; i++) {
|
|
20586
|
+
yield allLines[i];
|
|
20587
|
+
}
|
|
20588
|
+
}
|
|
20589
|
+
var DEFAULT_RETENTION_DAYS, SessionLogFile;
|
|
20590
|
+
var init_session_log2 = __esm({
|
|
20591
|
+
"src/router/session-log.ts"() {
|
|
20592
|
+
"use strict";
|
|
20593
|
+
init_paths();
|
|
20594
|
+
init_log();
|
|
20595
|
+
DEFAULT_RETENTION_DAYS = 7;
|
|
20596
|
+
SessionLogFile = class {
|
|
20597
|
+
constructor(chatId, backend2, model2) {
|
|
20598
|
+
this.backend = backend2;
|
|
20599
|
+
this.model = model2;
|
|
20600
|
+
if (!existsSync23(SESSION_LOGS_PATH)) {
|
|
20601
|
+
mkdirSync9(SESSION_LOGS_PATH, { recursive: true });
|
|
20602
|
+
}
|
|
20603
|
+
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
20604
|
+
const sanitizedChatId = chatId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
20605
|
+
this.filePath = join24(SESSION_LOGS_PATH, `session-${sanitizedChatId}-${ts2}.log`);
|
|
20606
|
+
const header2 = [
|
|
20607
|
+
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
20608
|
+
`CC-Claw Agent Session \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
20609
|
+
`Chat: ${chatId} | Backend: ${backend2} | Model: ${model2}`,
|
|
20610
|
+
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
20611
|
+
""
|
|
20612
|
+
].join("\n");
|
|
20613
|
+
appendFileSync(this.filePath, header2 + "\n", "utf-8");
|
|
20614
|
+
}
|
|
20615
|
+
filePath;
|
|
20616
|
+
startTime = Date.now();
|
|
20617
|
+
closed = false;
|
|
20618
|
+
/** Log a tool start with full, untruncated input. */
|
|
20619
|
+
logToolStart(toolName, input) {
|
|
20620
|
+
if (this.closed) return;
|
|
20621
|
+
const ts2 = this.timestamp();
|
|
20622
|
+
const inputStr = JSON.stringify(input, null, 2);
|
|
20623
|
+
const entry = `[${ts2}] TOOL_START ${toolName}
|
|
20624
|
+
${inputStr}
|
|
20625
|
+
|
|
20626
|
+
`;
|
|
20627
|
+
this.append(entry);
|
|
20628
|
+
}
|
|
20629
|
+
/** Log a tool end with full, untruncated result. */
|
|
20630
|
+
logToolEnd(toolName, result) {
|
|
20631
|
+
if (this.closed) return;
|
|
20632
|
+
const ts2 = this.timestamp();
|
|
20633
|
+
const preview = result.length > 5e3 ? `(${result.length} chars)
|
|
20634
|
+
${result.slice(0, 5e3)}\u2026[truncated]` : result;
|
|
20635
|
+
const entry = `[${ts2}] TOOL_END ${toolName}
|
|
20636
|
+
${preview}
|
|
20637
|
+
|
|
20638
|
+
`;
|
|
20639
|
+
this.append(entry);
|
|
20640
|
+
}
|
|
20641
|
+
/** Log thinking tokens with full text. */
|
|
20642
|
+
logThinking(text) {
|
|
20643
|
+
if (this.closed) return;
|
|
20644
|
+
const ts2 = this.timestamp();
|
|
20645
|
+
const entry = `[${ts2}] THINKING
|
|
20646
|
+
${text}
|
|
20647
|
+
|
|
20648
|
+
`;
|
|
20649
|
+
this.append(entry);
|
|
20650
|
+
}
|
|
20651
|
+
/** Log informational entry. */
|
|
20652
|
+
logInfo(text) {
|
|
20653
|
+
if (this.closed) return;
|
|
20654
|
+
const ts2 = this.timestamp();
|
|
20655
|
+
const entry = `[${ts2}] INFO ${text}
|
|
20656
|
+
|
|
20657
|
+
`;
|
|
20658
|
+
this.append(entry);
|
|
20659
|
+
}
|
|
20660
|
+
/** Finalize the session log with elapsed time and token counts. */
|
|
20661
|
+
finalize(elapsedMs, usage2) {
|
|
20662
|
+
if (this.closed) return;
|
|
20663
|
+
this.closed = true;
|
|
20664
|
+
const ts2 = this.timestamp();
|
|
20665
|
+
const elapsed = (elapsedMs / 1e3).toFixed(1);
|
|
20666
|
+
const usageStr = usage2 ? ` | input=${usage2.input} output=${usage2.output}${usage2.cacheRead ? ` cacheRead=${usage2.cacheRead}` : ""}` : "";
|
|
20667
|
+
const entry = `[${ts2}] FINALIZED \u2014 ${elapsed}s elapsed${usageStr}
|
|
20668
|
+
`;
|
|
20669
|
+
this.append(entry);
|
|
20670
|
+
}
|
|
20671
|
+
/** Get the file path for display/reference. */
|
|
20672
|
+
getFilePath() {
|
|
20673
|
+
return this.filePath;
|
|
20674
|
+
}
|
|
20675
|
+
/** Get just the filename (for compact display). */
|
|
20676
|
+
getFilename() {
|
|
20677
|
+
return basename3(this.filePath);
|
|
20678
|
+
}
|
|
20679
|
+
// ── Internal ──────────────────────────────────────────────────────
|
|
20680
|
+
timestamp() {
|
|
20681
|
+
return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
|
|
20682
|
+
}
|
|
20683
|
+
append(text) {
|
|
20684
|
+
try {
|
|
20685
|
+
appendFileSync(this.filePath, text, "utf-8");
|
|
20686
|
+
} catch (err) {
|
|
20687
|
+
log(`[session-log] Write failed: ${err}`);
|
|
20688
|
+
}
|
|
20689
|
+
}
|
|
20690
|
+
};
|
|
20691
|
+
}
|
|
20692
|
+
});
|
|
20693
|
+
|
|
20420
20694
|
// src/router/live-status.ts
|
|
20421
20695
|
var live_status_exports = {};
|
|
20422
20696
|
__export(live_status_exports, {
|
|
@@ -20439,22 +20713,20 @@ function renderEntry(e) {
|
|
|
20439
20713
|
}
|
|
20440
20714
|
return e.text;
|
|
20441
20715
|
}
|
|
20442
|
-
function renderEntries(entries, modelLabel, elapsedMs) {
|
|
20716
|
+
function renderEntries(entries, modelLabel, elapsedMs, trimmed) {
|
|
20443
20717
|
const elapsedSec = (elapsedMs / 1e3).toFixed(1);
|
|
20444
|
-
const lines = [`\u23F3 ${modelLabel} \xB7 ${elapsedSec}s
|
|
20445
|
-
|
|
20446
|
-
|
|
20447
|
-
}
|
|
20448
|
-
function renderFinal(entries, modelLabel, elapsedSec) {
|
|
20449
|
-
const lines = [`\u2705 ${modelLabel} \xB7 ${elapsedSec}s`, ""];
|
|
20718
|
+
const lines = [`\u23F3 ${modelLabel} \xB7 ${elapsedSec}s`];
|
|
20719
|
+
if (trimmed) lines[0] += " (\u2026)";
|
|
20720
|
+
lines.push("");
|
|
20450
20721
|
for (const e of entries) lines.push(renderEntry(e));
|
|
20451
|
-
if (lines.length === 2) return `\u2705 ${modelLabel} \xB7 ${elapsedSec}s`;
|
|
20452
20722
|
return lines.join("\n");
|
|
20453
20723
|
}
|
|
20454
|
-
function
|
|
20455
|
-
const lines = [`\
|
|
20724
|
+
function renderFinal(entries, modelLabel, elapsedSec, trimmed) {
|
|
20725
|
+
const lines = [`\u2705 ${modelLabel} \xB7 ${elapsedSec}s`];
|
|
20726
|
+
if (trimmed) lines[0] += " (\u2026)";
|
|
20727
|
+
if (entries.length === 0) return lines[0];
|
|
20728
|
+
lines.push("");
|
|
20456
20729
|
for (const e of entries) lines.push(renderEntry(e));
|
|
20457
|
-
if (lines.length === 2) return `\u{1F4CE} ${modelLabel} \xB7 ${elapsedSec}s`;
|
|
20458
20730
|
return lines.join("\n");
|
|
20459
20731
|
}
|
|
20460
20732
|
function makeLiveStatus(chatId, channel, modelLabel, verboseLevel, showThinking) {
|
|
@@ -20468,16 +20740,16 @@ function makeLiveStatus(chatId, channel, modelLabel, verboseLevel, showThinking)
|
|
|
20468
20740
|
};
|
|
20469
20741
|
return { liveStatus, toolCb };
|
|
20470
20742
|
}
|
|
20471
|
-
var FLUSH_INTERVAL_MS,
|
|
20743
|
+
var FLUSH_INTERVAL_MS, MAX_THINKING_CHARS, TRIM_THRESHOLD, MAX_ENTRIES, LiveStatusMessage;
|
|
20472
20744
|
var init_live_status = __esm({
|
|
20473
20745
|
"src/router/live-status.ts"() {
|
|
20474
20746
|
"use strict";
|
|
20475
20747
|
init_log();
|
|
20476
20748
|
init_helpers();
|
|
20477
20749
|
FLUSH_INTERVAL_MS = 1e3;
|
|
20478
|
-
MAX_ENTRIES = 50;
|
|
20479
20750
|
MAX_THINKING_CHARS = 800;
|
|
20480
|
-
|
|
20751
|
+
TRIM_THRESHOLD = 3500;
|
|
20752
|
+
MAX_ENTRIES = 200;
|
|
20481
20753
|
LiveStatusMessage = class {
|
|
20482
20754
|
constructor(chatId, channel, modelLabel, verboseLevel, showThinking = false) {
|
|
20483
20755
|
this.chatId = chatId;
|
|
@@ -20492,11 +20764,10 @@ var init_live_status = __esm({
|
|
|
20492
20764
|
flushTimer = null;
|
|
20493
20765
|
lastRendered = "";
|
|
20494
20766
|
finalized = false;
|
|
20495
|
-
/**
|
|
20496
|
-
|
|
20497
|
-
|
|
20498
|
-
|
|
20499
|
-
frozenEntryCount = 0;
|
|
20767
|
+
/** Earliest time the next flush is allowed (set after 429 backoff) */
|
|
20768
|
+
nextFlushAllowedAt = 0;
|
|
20769
|
+
/** Tracks whether entries have been trimmed at least once (for display hint). */
|
|
20770
|
+
hasTrimmed = false;
|
|
20500
20771
|
/** Send the initial status message. Must be called before adding entries. */
|
|
20501
20772
|
async init() {
|
|
20502
20773
|
if (!this.channel.sendTextReturningId) return;
|
|
@@ -20555,8 +20826,8 @@ var init_live_status = __esm({
|
|
|
20555
20826
|
}
|
|
20556
20827
|
if (!this.messageId || !this.channel.editText) return;
|
|
20557
20828
|
const elapsedSec = (elapsedMs / 1e3).toFixed(1);
|
|
20558
|
-
const
|
|
20559
|
-
const body = renderFinal(
|
|
20829
|
+
const deduped = dedupThinking(this.entries);
|
|
20830
|
+
const body = renderFinal(deduped, this.modelLabel, elapsedSec, this.hasTrimmed);
|
|
20560
20831
|
try {
|
|
20561
20832
|
await this.channel.editText(this.chatId, this.messageId, body, "plain");
|
|
20562
20833
|
} catch (err) {
|
|
@@ -20570,52 +20841,47 @@ var init_live_status = __esm({
|
|
|
20570
20841
|
// ── Internal ──────────────────────────────────────────────────────────
|
|
20571
20842
|
async flush() {
|
|
20572
20843
|
if (this.finalized || !this.messageId || !this.channel.editText) return;
|
|
20573
|
-
|
|
20574
|
-
const
|
|
20575
|
-
|
|
20576
|
-
await this.spillover();
|
|
20577
|
-
return;
|
|
20578
|
-
}
|
|
20844
|
+
if (Date.now() < this.nextFlushAllowedAt) return;
|
|
20845
|
+
const deduped = dedupThinking(this.entries);
|
|
20846
|
+
const body = renderEntries(deduped, this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
20579
20847
|
if (body === this.lastRendered) return;
|
|
20580
20848
|
this.lastRendered = body;
|
|
20581
20849
|
try {
|
|
20582
20850
|
await this.channel.editText(this.chatId, this.messageId, body, "plain");
|
|
20583
20851
|
} catch (err) {
|
|
20584
|
-
|
|
20852
|
+
this.handleRateLimit(err);
|
|
20585
20853
|
}
|
|
20586
20854
|
}
|
|
20587
20855
|
/**
|
|
20588
|
-
*
|
|
20589
|
-
*
|
|
20856
|
+
* Trim entries from the BEGINNING when the rendered body exceeds the threshold.
|
|
20857
|
+
* This is the core of the single-message pattern: always show the most recent
|
|
20858
|
+
* activity, drop the oldest entries that scroll past the limit.
|
|
20590
20859
|
*/
|
|
20591
|
-
|
|
20592
|
-
if (
|
|
20593
|
-
|
|
20594
|
-
|
|
20595
|
-
const frozenBody = renderFrozen(currentEntries, this.modelLabel, elapsedSec);
|
|
20596
|
-
try {
|
|
20597
|
-
await this.channel.editText(this.chatId, this.messageId, frozenBody, "plain");
|
|
20598
|
-
} catch (err) {
|
|
20599
|
-
log(`[live-status] spillover freeze failed: ${err}`);
|
|
20860
|
+
trimEntries() {
|
|
20861
|
+
if (this.entries.length > MAX_ENTRIES) {
|
|
20862
|
+
this.entries = this.entries.slice(this.entries.length - MAX_ENTRIES);
|
|
20863
|
+
this.hasTrimmed = true;
|
|
20600
20864
|
}
|
|
20601
|
-
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
this.messageId = newId;
|
|
20607
|
-
this.lastRendered = "";
|
|
20608
|
-
}
|
|
20609
|
-
} catch (err) {
|
|
20610
|
-
log(`[live-status] spillover new message failed: ${err}`);
|
|
20865
|
+
let rendered = renderEntries(dedupThinking(this.entries), this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
20866
|
+
while (rendered.length > TRIM_THRESHOLD && this.entries.length > 3) {
|
|
20867
|
+
this.entries.shift();
|
|
20868
|
+
this.hasTrimmed = true;
|
|
20869
|
+
rendered = renderEntries(dedupThinking(this.entries), this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
20611
20870
|
}
|
|
20612
20871
|
}
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
|
|
20872
|
+
/**
|
|
20873
|
+
* Handle Telegram 429 rate-limit errors by backing off.
|
|
20874
|
+
* Parses the "retry after N" hint and sets a cooldown.
|
|
20875
|
+
*/
|
|
20876
|
+
handleRateLimit(err) {
|
|
20877
|
+
const msg = String(err);
|
|
20878
|
+
const match = msg.match(/retry after (\d+)/i);
|
|
20879
|
+
if (match) {
|
|
20880
|
+
const retrySec = parseInt(match[1], 10) || 3;
|
|
20881
|
+
this.nextFlushAllowedAt = Date.now() + retrySec * 1e3;
|
|
20882
|
+
log(`[live-status] 429 rate-limited, backing off ${retrySec}s`);
|
|
20883
|
+
} else {
|
|
20884
|
+
log(`[live-status] edit failed: ${msg}`);
|
|
20619
20885
|
}
|
|
20620
20886
|
}
|
|
20621
20887
|
};
|
|
@@ -20955,16 +21221,40 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
20955
21221
|
const needsLiveStatus = tVerbose !== "off" || showThinkingUi;
|
|
20956
21222
|
let liveStatus = null;
|
|
20957
21223
|
let tToolCb;
|
|
21224
|
+
const { getSessionLogEnabled: getSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
21225
|
+
const { SessionLogFile: SessionLogFile2 } = await Promise.resolve().then(() => (init_session_log2(), session_log_exports2));
|
|
21226
|
+
let sessionLog = null;
|
|
21227
|
+
if (getSessionLogEnabled2(chatId)) {
|
|
21228
|
+
sessionLog = new SessionLogFile2(chatId, adapter.id, model2 ?? adapter.defaultModel);
|
|
21229
|
+
}
|
|
20958
21230
|
if (needsLiveStatus) {
|
|
20959
21231
|
const { makeLiveStatus: makeLiveStatus2 } = await Promise.resolve().then(() => (init_live_status(), live_status_exports));
|
|
20960
21232
|
const effectiveVerbose = tVerbose === "off" ? "normal" : tVerbose;
|
|
20961
21233
|
const ls = makeLiveStatus2(chatId, channel, modelLabel, effectiveVerbose, showThinkingUi);
|
|
20962
21234
|
liveStatus = ls.liveStatus;
|
|
20963
|
-
|
|
21235
|
+
const baseCb = tVerbose !== "off" ? ls.toolCb : void 0;
|
|
21236
|
+
tToolCb = async (toolName, input, result) => {
|
|
21237
|
+
if (baseCb) await baseCb(toolName, input, result);
|
|
21238
|
+
if (sessionLog) {
|
|
21239
|
+
if (result === void 0) {
|
|
21240
|
+
sessionLog.logToolStart(toolName, input);
|
|
21241
|
+
} else {
|
|
21242
|
+
sessionLog.logToolEnd(toolName, result);
|
|
21243
|
+
}
|
|
21244
|
+
}
|
|
21245
|
+
};
|
|
20964
21246
|
await liveStatus.init();
|
|
20965
|
-
if (showThinkingUi && adapter.id
|
|
20966
|
-
liveStatus.addInfo(
|
|
21247
|
+
if (showThinkingUi && adapter.id !== "claude") {
|
|
21248
|
+
liveStatus.addInfo(`\u{1F4AD} Thinking display not available for ${adapter.displayName}`);
|
|
20967
21249
|
}
|
|
21250
|
+
} else if (sessionLog) {
|
|
21251
|
+
tToolCb = async (toolName, input, result) => {
|
|
21252
|
+
if (result === void 0) {
|
|
21253
|
+
sessionLog.logToolStart(toolName, input);
|
|
21254
|
+
} else {
|
|
21255
|
+
sessionLog.logToolEnd(toolName, result);
|
|
21256
|
+
}
|
|
21257
|
+
};
|
|
20968
21258
|
}
|
|
20969
21259
|
const sigT0 = Date.now();
|
|
20970
21260
|
const response = await askAgent(chatId, cleanText || text, {
|
|
@@ -20975,7 +21265,10 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
20975
21265
|
bootstrapTier,
|
|
20976
21266
|
maxTurns,
|
|
20977
21267
|
agentMode: effectiveAgentMode,
|
|
20978
|
-
onThinking: liveStatus ? (chunk) =>
|
|
21268
|
+
onThinking: liveStatus || sessionLog ? (chunk) => {
|
|
21269
|
+
if (liveStatus) liveStatus.addThinking(chunk);
|
|
21270
|
+
if (sessionLog) sessionLog.logThinking(chunk);
|
|
21271
|
+
} : void 0,
|
|
20979
21272
|
onSubagentActivity: (backendId2, info) => {
|
|
20980
21273
|
observedSubagents.add(info.name);
|
|
20981
21274
|
try {
|
|
@@ -21015,6 +21308,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
21015
21308
|
liveStatus.addThinking(response.thinkingText.trim());
|
|
21016
21309
|
}
|
|
21017
21310
|
if (liveStatus) await liveStatus.finalize(elapsedMs);
|
|
21311
|
+
if (sessionLog) sessionLog.finalize(elapsedMs, response.usage);
|
|
21018
21312
|
if (response.usage) addUsage(chatId, response.usage.input, response.usage.output, response.usage.cacheRead, model2, void 0, response.usage.contextSize);
|
|
21019
21313
|
let responseText = response.text;
|
|
21020
21314
|
const sigEnabled = getModelSignature(chatId);
|
|
@@ -21523,7 +21817,7 @@ var init_cron = __esm({
|
|
|
21523
21817
|
});
|
|
21524
21818
|
|
|
21525
21819
|
// src/agents/runners/wrap-backend.ts
|
|
21526
|
-
import { join as
|
|
21820
|
+
import { join as join25 } from "path";
|
|
21527
21821
|
function buildMcpCommands(backendId) {
|
|
21528
21822
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
21529
21823
|
return {
|
|
@@ -21617,7 +21911,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
21617
21911
|
const configPath = writeMcpConfigFile(server);
|
|
21618
21912
|
return ["--mcp-config", configPath];
|
|
21619
21913
|
},
|
|
21620
|
-
getSkillPath: () =>
|
|
21914
|
+
getSkillPath: () => join25(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
21621
21915
|
};
|
|
21622
21916
|
}
|
|
21623
21917
|
var BACKEND_CAPABILITIES;
|
|
@@ -21668,18 +21962,18 @@ var init_wrap_backend = __esm({
|
|
|
21668
21962
|
});
|
|
21669
21963
|
|
|
21670
21964
|
// src/agents/runners/config-loader.ts
|
|
21671
|
-
import { readFileSync as readFileSync14, readdirSync as
|
|
21672
|
-
import { join as
|
|
21965
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync13, existsSync as existsSync24, mkdirSync as mkdirSync10, watchFile, unwatchFile } from "fs";
|
|
21966
|
+
import { join as join26 } from "path";
|
|
21673
21967
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
21674
21968
|
function resolveExecutable(config2) {
|
|
21675
|
-
if (
|
|
21969
|
+
if (existsSync24(config2.executable)) return config2.executable;
|
|
21676
21970
|
try {
|
|
21677
21971
|
return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
21678
21972
|
} catch {
|
|
21679
21973
|
}
|
|
21680
21974
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
21681
21975
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
21682
|
-
if (
|
|
21976
|
+
if (existsSync24(resolved)) return resolved;
|
|
21683
21977
|
}
|
|
21684
21978
|
return config2.executable;
|
|
21685
21979
|
}
|
|
@@ -21805,7 +22099,7 @@ function configToRunner(config2) {
|
|
|
21805
22099
|
prepareMcpInjection() {
|
|
21806
22100
|
return [];
|
|
21807
22101
|
},
|
|
21808
|
-
getSkillPath: () =>
|
|
22102
|
+
getSkillPath: () => join26(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
21809
22103
|
};
|
|
21810
22104
|
}
|
|
21811
22105
|
function loadRunnerConfig(filePath) {
|
|
@@ -21818,14 +22112,14 @@ function loadRunnerConfig(filePath) {
|
|
|
21818
22112
|
}
|
|
21819
22113
|
}
|
|
21820
22114
|
function loadAllRunnerConfigs() {
|
|
21821
|
-
if (!
|
|
21822
|
-
|
|
22115
|
+
if (!existsSync24(RUNNERS_PATH)) {
|
|
22116
|
+
mkdirSync10(RUNNERS_PATH, { recursive: true });
|
|
21823
22117
|
return [];
|
|
21824
22118
|
}
|
|
21825
|
-
const files =
|
|
22119
|
+
const files = readdirSync13(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
21826
22120
|
const configs = [];
|
|
21827
22121
|
for (const file of files) {
|
|
21828
|
-
const config2 = loadRunnerConfig(
|
|
22122
|
+
const config2 = loadRunnerConfig(join26(RUNNERS_PATH, file));
|
|
21829
22123
|
if (config2) configs.push(config2);
|
|
21830
22124
|
}
|
|
21831
22125
|
return configs;
|
|
@@ -21846,16 +22140,16 @@ function registerConfigRunners() {
|
|
|
21846
22140
|
return count;
|
|
21847
22141
|
}
|
|
21848
22142
|
function watchRunnerConfigs(onChange) {
|
|
21849
|
-
if (!
|
|
22143
|
+
if (!existsSync24(RUNNERS_PATH)) return;
|
|
21850
22144
|
for (const prev of watchedFiles) {
|
|
21851
|
-
if (!
|
|
22145
|
+
if (!existsSync24(prev)) {
|
|
21852
22146
|
unwatchFile(prev);
|
|
21853
22147
|
watchedFiles.delete(prev);
|
|
21854
22148
|
}
|
|
21855
22149
|
}
|
|
21856
|
-
const files =
|
|
22150
|
+
const files = readdirSync13(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
21857
22151
|
for (const file of files) {
|
|
21858
|
-
const fullPath =
|
|
22152
|
+
const fullPath = join26(RUNNERS_PATH, file);
|
|
21859
22153
|
if (watchedFiles.has(fullPath)) continue;
|
|
21860
22154
|
watchedFiles.add(fullPath);
|
|
21861
22155
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -22256,6 +22550,7 @@ var init_telegram2 = __esm({
|
|
|
22256
22550
|
{ command: "mode", description: "Execution gate (approved/yolo)" },
|
|
22257
22551
|
{ command: "tools", description: "Configure which tools the agent can use" },
|
|
22258
22552
|
{ command: "verbose", description: "Tool visibility (off/normal/verbose)" },
|
|
22553
|
+
{ command: "debug", description: "Toggle session debug logging (full tool I/O)" },
|
|
22259
22554
|
{ command: "cwd", description: "Set or show working directory" },
|
|
22260
22555
|
// Memory
|
|
22261
22556
|
{ command: "memory", description: "List stored memories" },
|
|
@@ -22702,19 +22997,19 @@ var init_telegram2 = __esm({
|
|
|
22702
22997
|
});
|
|
22703
22998
|
|
|
22704
22999
|
// src/skills/bootstrap.ts
|
|
22705
|
-
import { existsSync as
|
|
23000
|
+
import { existsSync as existsSync25 } from "fs";
|
|
22706
23001
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
22707
|
-
import { join as
|
|
23002
|
+
import { join as join27, dirname as dirname5 } from "path";
|
|
22708
23003
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22709
23004
|
async function copyAgentManifestSkills() {
|
|
22710
|
-
if (!
|
|
23005
|
+
if (!existsSync25(PKG_SKILLS)) return;
|
|
22711
23006
|
try {
|
|
22712
23007
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
22713
23008
|
for (const entry of entries) {
|
|
22714
23009
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
22715
|
-
const src =
|
|
22716
|
-
const dest =
|
|
22717
|
-
if (
|
|
23010
|
+
const src = join27(PKG_SKILLS, entry.name);
|
|
23011
|
+
const dest = join27(SKILLS_PATH, entry.name);
|
|
23012
|
+
if (existsSync25(dest)) continue;
|
|
22718
23013
|
await copyFile(src, dest);
|
|
22719
23014
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
22720
23015
|
}
|
|
@@ -22724,8 +23019,8 @@ async function copyAgentManifestSkills() {
|
|
|
22724
23019
|
}
|
|
22725
23020
|
async function bootstrapSkills() {
|
|
22726
23021
|
await copyAgentManifestSkills();
|
|
22727
|
-
const usmDir =
|
|
22728
|
-
if (
|
|
23022
|
+
const usmDir = join27(SKILLS_PATH, USM_DIR_NAME);
|
|
23023
|
+
if (existsSync25(usmDir)) return;
|
|
22729
23024
|
try {
|
|
22730
23025
|
const entries = await readdir6(SKILLS_PATH);
|
|
22731
23026
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -22747,8 +23042,8 @@ async function bootstrapSkills() {
|
|
|
22747
23042
|
}
|
|
22748
23043
|
}
|
|
22749
23044
|
async function patchUsmForCcClaw(usmDir) {
|
|
22750
|
-
const skillPath =
|
|
22751
|
-
if (!
|
|
23045
|
+
const skillPath = join27(usmDir, "SKILL.md");
|
|
23046
|
+
if (!existsSync25(skillPath)) return;
|
|
22752
23047
|
try {
|
|
22753
23048
|
let content = await readFile8(skillPath, "utf-8");
|
|
22754
23049
|
let patched = false;
|
|
@@ -22793,8 +23088,8 @@ var init_bootstrap = __esm({
|
|
|
22793
23088
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
22794
23089
|
USM_DIR_NAME = "universal-skills-manager";
|
|
22795
23090
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
22796
|
-
PKG_ROOT =
|
|
22797
|
-
PKG_SKILLS =
|
|
23091
|
+
PKG_ROOT = join27(dirname5(fileURLToPath2(import.meta.url)), "..", "..");
|
|
23092
|
+
PKG_SKILLS = join27(PKG_ROOT, "skills");
|
|
22798
23093
|
}
|
|
22799
23094
|
});
|
|
22800
23095
|
|
|
@@ -23016,13 +23311,13 @@ __export(ai_skill_exports, {
|
|
|
23016
23311
|
generateAiSkill: () => generateAiSkill,
|
|
23017
23312
|
installAiSkill: () => installAiSkill
|
|
23018
23313
|
});
|
|
23019
|
-
import { existsSync as
|
|
23020
|
-
import { join as
|
|
23314
|
+
import { existsSync as existsSync26, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
|
|
23315
|
+
import { join as join28 } from "path";
|
|
23021
23316
|
import { homedir as homedir9 } from "os";
|
|
23022
23317
|
function generateAiSkill() {
|
|
23023
23318
|
const version = VERSION;
|
|
23024
23319
|
let systemState = "";
|
|
23025
|
-
if (
|
|
23320
|
+
if (existsSync26(DB_PATH)) {
|
|
23026
23321
|
try {
|
|
23027
23322
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
23028
23323
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -23110,6 +23405,7 @@ Use the CC-Claw CLI when you need to:
|
|
|
23110
23405
|
- \`/model_signature\` \u2014 Show/hide model name on responses
|
|
23111
23406
|
- \`/agents mode\` \u2014 Agent mode (auto/native/claw)
|
|
23112
23407
|
- \`/voice_config\` \u2014 Voice provider settings
|
|
23408
|
+
- \`/debug\` \u2014 Toggle per-chat session debug logging (full tool I/O to disk)
|
|
23113
23409
|
|
|
23114
23410
|
**Memory:**
|
|
23115
23411
|
- \`/remember <text>\` \u2014 Save a memory
|
|
@@ -23152,6 +23448,16 @@ cc-claw logs --error # Show error log
|
|
|
23152
23448
|
cc-claw logs --lines 50 # Show last N lines
|
|
23153
23449
|
\`\`\`
|
|
23154
23450
|
|
|
23451
|
+
### Session Debug Logs
|
|
23452
|
+
\`\`\`bash
|
|
23453
|
+
cc-claw session-logs list # List all session debug logs
|
|
23454
|
+
cc-claw session-logs tail # Tail latest session log
|
|
23455
|
+
cc-claw session-logs tail -f # Follow latest log (like tail -f)
|
|
23456
|
+
cc-claw session-logs tail --file <name> # Tail a specific log file
|
|
23457
|
+
cc-claw session-logs clean # Remove old session logs
|
|
23458
|
+
cc-claw session-logs clean --days 3 # Remove logs older than 3 days
|
|
23459
|
+
\`\`\`
|
|
23460
|
+
|
|
23155
23461
|
### Backend & Model
|
|
23156
23462
|
\`\`\`bash
|
|
23157
23463
|
cc-claw backend list --json # Available backends
|
|
@@ -23426,10 +23732,10 @@ function installAiSkill() {
|
|
|
23426
23732
|
const failed = [];
|
|
23427
23733
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
23428
23734
|
for (const dir of dirs) {
|
|
23429
|
-
const skillDir =
|
|
23430
|
-
const skillPath =
|
|
23735
|
+
const skillDir = join28(dir, "cc-claw-cli");
|
|
23736
|
+
const skillPath = join28(skillDir, "SKILL.md");
|
|
23431
23737
|
try {
|
|
23432
|
-
|
|
23738
|
+
mkdirSync11(skillDir, { recursive: true });
|
|
23433
23739
|
writeFileSync8(skillPath, skill, "utf-8");
|
|
23434
23740
|
installed.push(skillPath);
|
|
23435
23741
|
} catch {
|
|
@@ -23446,11 +23752,11 @@ var init_ai_skill = __esm({
|
|
|
23446
23752
|
init_paths();
|
|
23447
23753
|
init_version();
|
|
23448
23754
|
BACKEND_SKILL_DIRS2 = {
|
|
23449
|
-
"cc-claw": [
|
|
23450
|
-
claude: [
|
|
23451
|
-
gemini: [
|
|
23452
|
-
codex: [
|
|
23453
|
-
cursor: [
|
|
23755
|
+
"cc-claw": [join28(homedir9(), ".cc-claw", "workspace", "skills")],
|
|
23756
|
+
claude: [join28(homedir9(), ".claude", "skills")],
|
|
23757
|
+
gemini: [join28(homedir9(), ".gemini", "skills")],
|
|
23758
|
+
codex: [join28(homedir9(), ".agents", "skills")],
|
|
23759
|
+
cursor: [join28(homedir9(), ".cursor", "skills"), join28(homedir9(), ".cursor", "skills-cursor")]
|
|
23454
23760
|
};
|
|
23455
23761
|
}
|
|
23456
23762
|
});
|
|
@@ -23460,21 +23766,21 @@ var index_exports = {};
|
|
|
23460
23766
|
__export(index_exports, {
|
|
23461
23767
|
main: () => main
|
|
23462
23768
|
});
|
|
23463
|
-
import { mkdirSync as
|
|
23464
|
-
import { join as
|
|
23769
|
+
import { mkdirSync as mkdirSync12, existsSync as existsSync27, renameSync as renameSync2, statSync as statSync8, readFileSync as readFileSync16 } from "fs";
|
|
23770
|
+
import { join as join29 } from "path";
|
|
23465
23771
|
import dotenv from "dotenv";
|
|
23466
23772
|
function migrateLayout() {
|
|
23467
23773
|
const moves = [
|
|
23468
|
-
[
|
|
23469
|
-
[
|
|
23470
|
-
[
|
|
23471
|
-
[
|
|
23472
|
-
[
|
|
23473
|
-
[
|
|
23474
|
-
[
|
|
23774
|
+
[join29(CC_CLAW_HOME, "cc-claw.db"), join29(DATA_PATH, "cc-claw.db")],
|
|
23775
|
+
[join29(CC_CLAW_HOME, "cc-claw.db-shm"), join29(DATA_PATH, "cc-claw.db-shm")],
|
|
23776
|
+
[join29(CC_CLAW_HOME, "cc-claw.db-wal"), join29(DATA_PATH, "cc-claw.db-wal")],
|
|
23777
|
+
[join29(CC_CLAW_HOME, "cc-claw.log"), join29(LOGS_PATH, "cc-claw.log")],
|
|
23778
|
+
[join29(CC_CLAW_HOME, "cc-claw.log.1"), join29(LOGS_PATH, "cc-claw.log.1")],
|
|
23779
|
+
[join29(CC_CLAW_HOME, "cc-claw.error.log"), join29(LOGS_PATH, "cc-claw.error.log")],
|
|
23780
|
+
[join29(CC_CLAW_HOME, "cc-claw.error.log.1"), join29(LOGS_PATH, "cc-claw.error.log.1")]
|
|
23475
23781
|
];
|
|
23476
23782
|
for (const [from, to] of moves) {
|
|
23477
|
-
if (
|
|
23783
|
+
if (existsSync27(from) && !existsSync27(to)) {
|
|
23478
23784
|
try {
|
|
23479
23785
|
renameSync2(from, to);
|
|
23480
23786
|
} catch {
|
|
@@ -23485,7 +23791,7 @@ function migrateLayout() {
|
|
|
23485
23791
|
function rotateLogs() {
|
|
23486
23792
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
23487
23793
|
try {
|
|
23488
|
-
const { size } =
|
|
23794
|
+
const { size } = statSync8(file);
|
|
23489
23795
|
if (size > LOG_MAX_BYTES) {
|
|
23490
23796
|
const archivePath = `${file}.1`;
|
|
23491
23797
|
try {
|
|
@@ -23619,11 +23925,11 @@ async function main() {
|
|
|
23619
23925
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
23620
23926
|
try {
|
|
23621
23927
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
23622
|
-
const { writeFileSync: writeFileSync13, mkdirSync:
|
|
23623
|
-
const { join:
|
|
23624
|
-
const skillDir =
|
|
23625
|
-
|
|
23626
|
-
writeFileSync13(
|
|
23928
|
+
const { writeFileSync: writeFileSync13, mkdirSync: mkdirSync19 } = await import("fs");
|
|
23929
|
+
const { join: join35 } = await import("path");
|
|
23930
|
+
const skillDir = join35(SKILLS_PATH, "cc-claw-cli");
|
|
23931
|
+
mkdirSync19(skillDir, { recursive: true });
|
|
23932
|
+
writeFileSync13(join35(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
23627
23933
|
log("[cc-claw] AI skill updated");
|
|
23628
23934
|
} catch {
|
|
23629
23935
|
}
|
|
@@ -23643,6 +23949,12 @@ async function main() {
|
|
|
23643
23949
|
cleanupOldMedia().catch(() => {
|
|
23644
23950
|
});
|
|
23645
23951
|
pruneImageCache();
|
|
23952
|
+
try {
|
|
23953
|
+
const { cleanupSessionLogs: cleanupSessionLogs2, startSessionLogCleanupTimer: startSessionLogCleanupTimer2 } = await Promise.resolve().then(() => (init_session_log2(), session_log_exports2));
|
|
23954
|
+
cleanupSessionLogs2();
|
|
23955
|
+
startSessionLogCleanupTimer2();
|
|
23956
|
+
} catch {
|
|
23957
|
+
}
|
|
23646
23958
|
log("[cc-claw] Ready!");
|
|
23647
23959
|
const shutdown = async (signal) => {
|
|
23648
23960
|
log(`[cc-claw] Received ${signal}, shutting down...`);
|
|
@@ -23695,11 +24007,11 @@ var init_index = __esm({
|
|
|
23695
24007
|
init_bootstrap2();
|
|
23696
24008
|
init_health3();
|
|
23697
24009
|
init_image_gen();
|
|
23698
|
-
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
23699
|
-
if (!
|
|
24010
|
+
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SESSION_LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
24011
|
+
if (!existsSync27(dir)) mkdirSync12(dir, { recursive: true });
|
|
23700
24012
|
}
|
|
23701
24013
|
migrateLayout();
|
|
23702
|
-
if (
|
|
24014
|
+
if (existsSync27(ENV_PATH)) {
|
|
23703
24015
|
dotenv.config({ path: ENV_PATH });
|
|
23704
24016
|
} else {
|
|
23705
24017
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -23720,12 +24032,12 @@ __export(api_client_exports, {
|
|
|
23720
24032
|
apiPost: () => apiPost,
|
|
23721
24033
|
isDaemonRunning: () => isDaemonRunning
|
|
23722
24034
|
});
|
|
23723
|
-
import { readFileSync as readFileSync17, existsSync as
|
|
24035
|
+
import { readFileSync as readFileSync17, existsSync as existsSync28 } from "fs";
|
|
23724
24036
|
import { request as httpRequest, Agent } from "http";
|
|
23725
24037
|
function getToken() {
|
|
23726
24038
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
23727
24039
|
try {
|
|
23728
|
-
if (
|
|
24040
|
+
if (existsSync28(TOKEN_PATH)) return readFileSync17(TOKEN_PATH, "utf-8").trim();
|
|
23729
24041
|
} catch {
|
|
23730
24042
|
}
|
|
23731
24043
|
return null;
|
|
@@ -23824,10 +24136,10 @@ __export(service_exports, {
|
|
|
23824
24136
|
serviceStatus: () => serviceStatus,
|
|
23825
24137
|
uninstallService: () => uninstallService
|
|
23826
24138
|
});
|
|
23827
|
-
import { existsSync as
|
|
24139
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, unlinkSync as unlinkSync7 } from "fs";
|
|
23828
24140
|
import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
|
|
23829
24141
|
import { homedir as homedir10, platform } from "os";
|
|
23830
|
-
import { join as
|
|
24142
|
+
import { join as join30, dirname as dirname6 } from "path";
|
|
23831
24143
|
function xmlEscape(s) {
|
|
23832
24144
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
23833
24145
|
}
|
|
@@ -23836,7 +24148,7 @@ function resolveExecutable2(name) {
|
|
|
23836
24148
|
return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
|
|
23837
24149
|
} catch {
|
|
23838
24150
|
const fallback = process.argv[1];
|
|
23839
|
-
if (fallback &&
|
|
24151
|
+
if (fallback && existsSync29(fallback)) return fallback;
|
|
23840
24152
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
23841
24153
|
}
|
|
23842
24154
|
}
|
|
@@ -23845,14 +24157,14 @@ function getPathDirs() {
|
|
|
23845
24157
|
const home = homedir10();
|
|
23846
24158
|
const dirs = /* @__PURE__ */ new Set([
|
|
23847
24159
|
nodeBin,
|
|
23848
|
-
|
|
24160
|
+
join30(home, ".local", "bin"),
|
|
23849
24161
|
"/usr/local/bin",
|
|
23850
24162
|
"/usr/bin",
|
|
23851
24163
|
"/bin"
|
|
23852
24164
|
]);
|
|
23853
24165
|
try {
|
|
23854
24166
|
const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
23855
|
-
if (prefix) dirs.add(
|
|
24167
|
+
if (prefix) dirs.add(join30(prefix, "bin"));
|
|
23856
24168
|
} catch {
|
|
23857
24169
|
}
|
|
23858
24170
|
return [...dirs].join(":");
|
|
@@ -23911,9 +24223,9 @@ function generatePlist() {
|
|
|
23911
24223
|
}
|
|
23912
24224
|
function installMacOS() {
|
|
23913
24225
|
const agentsDir = dirname6(PLIST_PATH);
|
|
23914
|
-
if (!
|
|
23915
|
-
if (!
|
|
23916
|
-
if (
|
|
24226
|
+
if (!existsSync29(agentsDir)) mkdirSync13(agentsDir, { recursive: true });
|
|
24227
|
+
if (!existsSync29(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
24228
|
+
if (existsSync29(PLIST_PATH)) {
|
|
23917
24229
|
try {
|
|
23918
24230
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
23919
24231
|
} catch {
|
|
@@ -23925,7 +24237,7 @@ function installMacOS() {
|
|
|
23925
24237
|
console.log(" Service loaded and starting.");
|
|
23926
24238
|
}
|
|
23927
24239
|
function uninstallMacOS() {
|
|
23928
|
-
if (!
|
|
24240
|
+
if (!existsSync29(PLIST_PATH)) {
|
|
23929
24241
|
console.log(" No service found to uninstall.");
|
|
23930
24242
|
return;
|
|
23931
24243
|
}
|
|
@@ -23933,7 +24245,7 @@ function uninstallMacOS() {
|
|
|
23933
24245
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
23934
24246
|
} catch {
|
|
23935
24247
|
}
|
|
23936
|
-
|
|
24248
|
+
unlinkSync7(PLIST_PATH);
|
|
23937
24249
|
console.log(" Service uninstalled.");
|
|
23938
24250
|
}
|
|
23939
24251
|
function formatUptime(seconds) {
|
|
@@ -24000,8 +24312,8 @@ WantedBy=default.target
|
|
|
24000
24312
|
`;
|
|
24001
24313
|
}
|
|
24002
24314
|
function installLinux() {
|
|
24003
|
-
if (!
|
|
24004
|
-
if (!
|
|
24315
|
+
if (!existsSync29(SYSTEMD_DIR)) mkdirSync13(SYSTEMD_DIR, { recursive: true });
|
|
24316
|
+
if (!existsSync29(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
24005
24317
|
writeFileSync9(UNIT_PATH, generateUnit());
|
|
24006
24318
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
24007
24319
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -24010,7 +24322,7 @@ function installLinux() {
|
|
|
24010
24322
|
console.log(" Service enabled and started.");
|
|
24011
24323
|
}
|
|
24012
24324
|
function uninstallLinux() {
|
|
24013
|
-
if (!
|
|
24325
|
+
if (!existsSync29(UNIT_PATH)) {
|
|
24014
24326
|
console.log(" No service found to uninstall.");
|
|
24015
24327
|
return;
|
|
24016
24328
|
}
|
|
@@ -24022,7 +24334,7 @@ function uninstallLinux() {
|
|
|
24022
24334
|
execFileSync3("systemctl", ["--user", "disable", "cc-claw"]);
|
|
24023
24335
|
} catch {
|
|
24024
24336
|
}
|
|
24025
|
-
|
|
24337
|
+
unlinkSync7(UNIT_PATH);
|
|
24026
24338
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
24027
24339
|
console.log(" Service uninstalled.");
|
|
24028
24340
|
}
|
|
@@ -24035,7 +24347,7 @@ function statusLinux() {
|
|
|
24035
24347
|
}
|
|
24036
24348
|
}
|
|
24037
24349
|
function installService() {
|
|
24038
|
-
if (!
|
|
24350
|
+
if (!existsSync29(join30(CC_CLAW_HOME, ".env"))) {
|
|
24039
24351
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
24040
24352
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
24041
24353
|
process.exitCode = 1;
|
|
@@ -24064,9 +24376,9 @@ var init_service = __esm({
|
|
|
24064
24376
|
"use strict";
|
|
24065
24377
|
init_paths();
|
|
24066
24378
|
PLIST_LABEL = "com.cc-claw";
|
|
24067
|
-
PLIST_PATH =
|
|
24068
|
-
SYSTEMD_DIR =
|
|
24069
|
-
UNIT_PATH =
|
|
24379
|
+
PLIST_PATH = join30(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
24380
|
+
SYSTEMD_DIR = join30(homedir10(), ".config", "systemd", "user");
|
|
24381
|
+
UNIT_PATH = join30(SYSTEMD_DIR, "cc-claw.service");
|
|
24070
24382
|
}
|
|
24071
24383
|
});
|
|
24072
24384
|
|
|
@@ -24263,7 +24575,7 @@ var status_exports = {};
|
|
|
24263
24575
|
__export(status_exports, {
|
|
24264
24576
|
statusCommand: () => statusCommand
|
|
24265
24577
|
});
|
|
24266
|
-
import { existsSync as
|
|
24578
|
+
import { existsSync as existsSync30, statSync as statSync9 } from "fs";
|
|
24267
24579
|
async function statusCommand(globalOpts, localOpts) {
|
|
24268
24580
|
try {
|
|
24269
24581
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -24303,7 +24615,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
24303
24615
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
24304
24616
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
24305
24617
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
24306
|
-
const dbStat =
|
|
24618
|
+
const dbStat = existsSync30(DB_PATH) ? statSync9(DB_PATH) : null;
|
|
24307
24619
|
let daemonRunning = false;
|
|
24308
24620
|
let daemonInfo = {};
|
|
24309
24621
|
try {
|
|
@@ -24392,12 +24704,12 @@ var doctor_exports = {};
|
|
|
24392
24704
|
__export(doctor_exports, {
|
|
24393
24705
|
doctorCommand: () => doctorCommand
|
|
24394
24706
|
});
|
|
24395
|
-
import { existsSync as
|
|
24707
|
+
import { existsSync as existsSync31, statSync as statSync10, accessSync, constants } from "fs";
|
|
24396
24708
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
24397
24709
|
async function doctorCommand(globalOpts, localOpts) {
|
|
24398
24710
|
const checks = [];
|
|
24399
|
-
if (
|
|
24400
|
-
const size =
|
|
24711
|
+
if (existsSync31(DB_PATH)) {
|
|
24712
|
+
const size = statSync10(DB_PATH).size;
|
|
24401
24713
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
24402
24714
|
try {
|
|
24403
24715
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -24426,7 +24738,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24426
24738
|
} else {
|
|
24427
24739
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
24428
24740
|
}
|
|
24429
|
-
if (
|
|
24741
|
+
if (existsSync31(ENV_PATH)) {
|
|
24430
24742
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
24431
24743
|
} else {
|
|
24432
24744
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -24481,7 +24793,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24481
24793
|
} catch {
|
|
24482
24794
|
}
|
|
24483
24795
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
24484
|
-
if (
|
|
24796
|
+
if (existsSync31(tokenPath)) {
|
|
24485
24797
|
try {
|
|
24486
24798
|
accessSync(tokenPath, constants.R_OK);
|
|
24487
24799
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -24506,10 +24818,10 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24506
24818
|
}
|
|
24507
24819
|
} catch {
|
|
24508
24820
|
}
|
|
24509
|
-
if (
|
|
24821
|
+
if (existsSync31(ERROR_LOG_PATH)) {
|
|
24510
24822
|
try {
|
|
24511
|
-
const { readFileSync:
|
|
24512
|
-
const logContent =
|
|
24823
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
24824
|
+
const logContent = readFileSync27(ERROR_LOG_PATH, "utf-8");
|
|
24513
24825
|
const recentLines = logContent.split("\n").filter(Boolean).slice(-100);
|
|
24514
24826
|
const last24h = Date.now() - 864e5;
|
|
24515
24827
|
const recentErrors = recentLines.filter((line) => {
|
|
@@ -24632,10 +24944,10 @@ var logs_exports = {};
|
|
|
24632
24944
|
__export(logs_exports, {
|
|
24633
24945
|
logsCommand: () => logsCommand
|
|
24634
24946
|
});
|
|
24635
|
-
import { existsSync as
|
|
24947
|
+
import { existsSync as existsSync32, readFileSync as readFileSync20, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
24636
24948
|
async function logsCommand(opts) {
|
|
24637
24949
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
24638
|
-
if (!
|
|
24950
|
+
if (!existsSync32(logFile)) {
|
|
24639
24951
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
24640
24952
|
process.exit(1);
|
|
24641
24953
|
}
|
|
@@ -24675,6 +24987,105 @@ var init_logs = __esm({
|
|
|
24675
24987
|
}
|
|
24676
24988
|
});
|
|
24677
24989
|
|
|
24990
|
+
// src/cli/commands/session-logs.ts
|
|
24991
|
+
var session_logs_exports = {};
|
|
24992
|
+
__export(session_logs_exports, {
|
|
24993
|
+
sessionLogsClean: () => sessionLogsClean,
|
|
24994
|
+
sessionLogsList: () => sessionLogsList,
|
|
24995
|
+
sessionLogsTail: () => sessionLogsTail
|
|
24996
|
+
});
|
|
24997
|
+
import { readFileSync as readFileSync21, watchFile as watchFile3, unwatchFile as unwatchFile3 } from "fs";
|
|
24998
|
+
async function sessionLogsList(opts) {
|
|
24999
|
+
const logs = listSessionLogs();
|
|
25000
|
+
if (logs.length === 0) {
|
|
25001
|
+
console.log(muted(" No session debug logs found."));
|
|
25002
|
+
console.log(muted(` Enable via /debug in Telegram, then logs will appear in ${SESSION_LOGS_PATH}`));
|
|
25003
|
+
return;
|
|
25004
|
+
}
|
|
25005
|
+
if (opts.json) {
|
|
25006
|
+
console.log(JSON.stringify(logs.map((l) => ({
|
|
25007
|
+
filename: l.filename,
|
|
25008
|
+
chatId: l.chatId,
|
|
25009
|
+
timestamp: l.timestamp,
|
|
25010
|
+
sizeBytes: l.sizeBytes,
|
|
25011
|
+
modifiedAt: l.modifiedAt.toISOString()
|
|
25012
|
+
})), null, 2));
|
|
25013
|
+
return;
|
|
25014
|
+
}
|
|
25015
|
+
console.log(muted(` \u2500\u2500 Session Debug Logs (${logs.length}) \u2500\u2500
|
|
25016
|
+
`));
|
|
25017
|
+
console.log(` ${"Filename".padEnd(55)} ${"Size".padStart(8)} Chat ID`);
|
|
25018
|
+
console.log(` ${"\u2500".repeat(55)} ${"\u2500".repeat(8)} ${"\u2500".repeat(15)}`);
|
|
25019
|
+
for (const log5 of logs) {
|
|
25020
|
+
const size = log5.sizeBytes < 1024 ? `${log5.sizeBytes}B` : log5.sizeBytes < 1024 * 1024 ? `${(log5.sizeBytes / 1024).toFixed(1)}K` : `${(log5.sizeBytes / 1024 / 1024).toFixed(1)}M`;
|
|
25021
|
+
console.log(` ${log5.filename.padEnd(55)} ${size.padStart(8)} ${log5.chatId}`);
|
|
25022
|
+
}
|
|
25023
|
+
console.log(muted(`
|
|
25024
|
+
Path: ${SESSION_LOGS_PATH}`));
|
|
25025
|
+
console.log(muted(` Retention: ${getRetentionDays()} day(s) (set SESSION_LOG_RETENTION_DAYS to change)`));
|
|
25026
|
+
}
|
|
25027
|
+
async function sessionLogsTail(opts) {
|
|
25028
|
+
const logs = listSessionLogs();
|
|
25029
|
+
if (logs.length === 0) {
|
|
25030
|
+
outputError("NO_LOGS", "No session debug logs found. Enable via /debug in Telegram.");
|
|
25031
|
+
return;
|
|
25032
|
+
}
|
|
25033
|
+
let targetPath;
|
|
25034
|
+
if (opts.file) {
|
|
25035
|
+
const match = logs.find((l) => l.filename.includes(opts.file));
|
|
25036
|
+
if (!match) {
|
|
25037
|
+
outputError("NOT_FOUND", `No session log matching "${opts.file}". Use 'cc-claw logs session list' to see available logs.`);
|
|
25038
|
+
return;
|
|
25039
|
+
}
|
|
25040
|
+
targetPath = match.filePath;
|
|
25041
|
+
} else {
|
|
25042
|
+
targetPath = logs[0].filePath;
|
|
25043
|
+
}
|
|
25044
|
+
const lineCount = parseInt(opts.lines ?? "50", 10);
|
|
25045
|
+
console.log(muted(` \u2500\u2500 ${targetPath} (last ${lineCount} lines) \u2500\u2500
|
|
25046
|
+
`));
|
|
25047
|
+
for await (const line of tailSessionLog(targetPath, lineCount)) {
|
|
25048
|
+
console.log(line);
|
|
25049
|
+
}
|
|
25050
|
+
if (opts.follow) {
|
|
25051
|
+
console.log(muted("\n Following... (Ctrl+C to stop)\n"));
|
|
25052
|
+
let lastLength = 0;
|
|
25053
|
+
try {
|
|
25054
|
+
lastLength = readFileSync21(targetPath, "utf-8").length;
|
|
25055
|
+
} catch {
|
|
25056
|
+
}
|
|
25057
|
+
watchFile3(targetPath, { interval: 500 }, () => {
|
|
25058
|
+
try {
|
|
25059
|
+
const content = readFileSync21(targetPath, "utf-8");
|
|
25060
|
+
if (content.length > lastLength) {
|
|
25061
|
+
process.stdout.write(content.slice(lastLength));
|
|
25062
|
+
lastLength = content.length;
|
|
25063
|
+
}
|
|
25064
|
+
} catch {
|
|
25065
|
+
}
|
|
25066
|
+
});
|
|
25067
|
+
process.on("SIGINT", () => {
|
|
25068
|
+
unwatchFile3(targetPath);
|
|
25069
|
+
process.exit(0);
|
|
25070
|
+
});
|
|
25071
|
+
await new Promise(() => {
|
|
25072
|
+
});
|
|
25073
|
+
}
|
|
25074
|
+
}
|
|
25075
|
+
async function sessionLogsClean(opts) {
|
|
25076
|
+
const days = opts.days ? parseInt(opts.days, 10) : void 0;
|
|
25077
|
+
const cleaned = cleanupSessionLogs(days);
|
|
25078
|
+
console.log(success(`Cleaned ${cleaned} session log(s) older than ${days ?? getRetentionDays()} day(s).`));
|
|
25079
|
+
}
|
|
25080
|
+
var init_session_logs = __esm({
|
|
25081
|
+
"src/cli/commands/session-logs.ts"() {
|
|
25082
|
+
"use strict";
|
|
25083
|
+
init_session_log2();
|
|
25084
|
+
init_paths();
|
|
25085
|
+
init_format2();
|
|
25086
|
+
}
|
|
25087
|
+
});
|
|
25088
|
+
|
|
24678
25089
|
// src/cli/commands/gemini.ts
|
|
24679
25090
|
var gemini_exports = {};
|
|
24680
25091
|
__export(gemini_exports, {
|
|
@@ -24687,11 +25098,11 @@ __export(gemini_exports, {
|
|
|
24687
25098
|
geminiReorder: () => geminiReorder,
|
|
24688
25099
|
geminiRotation: () => geminiRotation
|
|
24689
25100
|
});
|
|
24690
|
-
import { existsSync as
|
|
24691
|
-
import { join as
|
|
24692
|
-
import { createInterface as
|
|
25101
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync14, writeFileSync as writeFileSync10, readFileSync as readFileSync22, chmodSync } from "fs";
|
|
25102
|
+
import { join as join31 } from "path";
|
|
25103
|
+
import { createInterface as createInterface7 } from "readline";
|
|
24693
25104
|
function requireDb() {
|
|
24694
|
-
if (!
|
|
25105
|
+
if (!existsSync34(DB_PATH)) {
|
|
24695
25106
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
24696
25107
|
process.exit(1);
|
|
24697
25108
|
}
|
|
@@ -24716,9 +25127,9 @@ async function resolveSlotId(idOrLabel) {
|
|
|
24716
25127
|
function resolveOAuthEmail(configHome) {
|
|
24717
25128
|
if (!configHome) return null;
|
|
24718
25129
|
try {
|
|
24719
|
-
const accountsPath =
|
|
24720
|
-
if (!
|
|
24721
|
-
const accounts = JSON.parse(
|
|
25130
|
+
const accountsPath = join31(configHome, ".gemini", "google_accounts.json");
|
|
25131
|
+
if (!existsSync34(accountsPath)) return null;
|
|
25132
|
+
const accounts = JSON.parse(readFileSync22(accountsPath, "utf-8"));
|
|
24722
25133
|
return accounts.active || null;
|
|
24723
25134
|
} catch {
|
|
24724
25135
|
return null;
|
|
@@ -24762,7 +25173,7 @@ async function geminiList(globalOpts) {
|
|
|
24762
25173
|
}
|
|
24763
25174
|
async function geminiAddKey(globalOpts, opts) {
|
|
24764
25175
|
await requireWriteDb();
|
|
24765
|
-
const rl2 =
|
|
25176
|
+
const rl2 = createInterface7({ input: process.stdin, output: process.stdout });
|
|
24766
25177
|
const ask2 = (q) => new Promise((r) => rl2.question(q, r));
|
|
24767
25178
|
const key = await ask2("Paste your Gemini API key: ");
|
|
24768
25179
|
rl2.close();
|
|
@@ -24800,14 +25211,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
24800
25211
|
}
|
|
24801
25212
|
async function geminiAddAccount(globalOpts, opts) {
|
|
24802
25213
|
await requireWriteDb();
|
|
24803
|
-
const slotsDir =
|
|
24804
|
-
if (!
|
|
25214
|
+
const slotsDir = join31(CC_CLAW_HOME, "gemini-slots");
|
|
25215
|
+
if (!existsSync34(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
24805
25216
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
24806
25217
|
const tempId = Date.now();
|
|
24807
|
-
const slotDir =
|
|
24808
|
-
|
|
24809
|
-
|
|
24810
|
-
writeFileSync10(
|
|
25218
|
+
const slotDir = join31(slotsDir, `slot-${tempId}`);
|
|
25219
|
+
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
25220
|
+
mkdirSync14(join31(slotDir, ".gemini"), { recursive: true });
|
|
25221
|
+
writeFileSync10(join31(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
24811
25222
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
24812
25223
|
}, null, 2));
|
|
24813
25224
|
console.log("");
|
|
@@ -24824,8 +25235,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
24824
25235
|
});
|
|
24825
25236
|
} catch {
|
|
24826
25237
|
}
|
|
24827
|
-
const oauthPath =
|
|
24828
|
-
if (!
|
|
25238
|
+
const oauthPath = join31(slotDir, ".gemini", "oauth_creds.json");
|
|
25239
|
+
if (!existsSync34(oauthPath)) {
|
|
24829
25240
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
24830
25241
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
24831
25242
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -24833,7 +25244,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
24833
25244
|
}
|
|
24834
25245
|
let accountEmail = "unknown";
|
|
24835
25246
|
try {
|
|
24836
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
25247
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join31(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
24837
25248
|
accountEmail = accounts.active || accountEmail;
|
|
24838
25249
|
} catch {
|
|
24839
25250
|
}
|
|
@@ -24952,11 +25363,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
24952
25363
|
makeReorder: () => makeReorder,
|
|
24953
25364
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
24954
25365
|
});
|
|
24955
|
-
import { existsSync as
|
|
24956
|
-
import { join as
|
|
24957
|
-
import { createInterface as
|
|
25366
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync15, readFileSync as readFileSync23 } from "fs";
|
|
25367
|
+
import { join as join32 } from "path";
|
|
25368
|
+
import { createInterface as createInterface8 } from "readline";
|
|
24958
25369
|
function requireDb2() {
|
|
24959
|
-
if (!
|
|
25370
|
+
if (!existsSync35(DB_PATH)) {
|
|
24960
25371
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
24961
25372
|
process.exit(1);
|
|
24962
25373
|
}
|
|
@@ -25015,7 +25426,7 @@ Add one with: cc-claw ${backend2} add-account or cc-claw ${backend2} add-key`)
|
|
|
25015
25426
|
function makeAddKey(backend2, displayName) {
|
|
25016
25427
|
return async function addKey(_globalOpts, opts) {
|
|
25017
25428
|
await requireWriteDb2();
|
|
25018
|
-
const rl2 =
|
|
25429
|
+
const rl2 = createInterface8({ input: process.stdin, output: process.stdout });
|
|
25019
25430
|
const ask2 = (q) => new Promise((r) => rl2.question(q, r));
|
|
25020
25431
|
const key = await ask2(`Paste your ${displayName} API key: `);
|
|
25021
25432
|
rl2.close();
|
|
@@ -25045,11 +25456,11 @@ function makeAddAccount(backend2, displayName) {
|
|
|
25045
25456
|
process.exit(1);
|
|
25046
25457
|
}
|
|
25047
25458
|
await requireWriteDb2();
|
|
25048
|
-
const slotsDir =
|
|
25049
|
-
if (!
|
|
25459
|
+
const slotsDir = join32(CC_CLAW_HOME, config2.slotsSubdir);
|
|
25460
|
+
if (!existsSync35(slotsDir)) mkdirSync15(slotsDir, { recursive: true });
|
|
25050
25461
|
const tempId = Date.now();
|
|
25051
|
-
const slotDir =
|
|
25052
|
-
|
|
25462
|
+
const slotDir = join32(slotsDir, `slot-${tempId}`);
|
|
25463
|
+
mkdirSync15(slotDir, { recursive: true, mode: 448 });
|
|
25053
25464
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
25054
25465
|
console.log("");
|
|
25055
25466
|
console.log(` Opening ${displayName} CLI for sign-in...`);
|
|
@@ -25217,22 +25628,22 @@ var init_backend_cmd_factory = __esm({
|
|
|
25217
25628
|
envValue: (slotDir) => slotDir,
|
|
25218
25629
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
25219
25630
|
preSetup: (slotDir) => {
|
|
25220
|
-
|
|
25631
|
+
mkdirSync15(join32(slotDir, ".claude"), { recursive: true });
|
|
25221
25632
|
},
|
|
25222
25633
|
verifyCredentials: (slotDir) => {
|
|
25223
|
-
const claudeJson =
|
|
25224
|
-
const claudeJsonNested =
|
|
25225
|
-
if (
|
|
25634
|
+
const claudeJson = join32(slotDir, ".claude.json");
|
|
25635
|
+
const claudeJsonNested = join32(slotDir, ".claude", ".claude.json");
|
|
25636
|
+
if (existsSync35(claudeJson)) {
|
|
25226
25637
|
try {
|
|
25227
|
-
const data = JSON.parse(
|
|
25638
|
+
const data = JSON.parse(readFileSync23(claudeJson, "utf-8"));
|
|
25228
25639
|
return Boolean(data.oauthAccount);
|
|
25229
25640
|
} catch {
|
|
25230
25641
|
return false;
|
|
25231
25642
|
}
|
|
25232
25643
|
}
|
|
25233
|
-
if (
|
|
25644
|
+
if (existsSync35(claudeJsonNested)) {
|
|
25234
25645
|
try {
|
|
25235
|
-
const data = JSON.parse(
|
|
25646
|
+
const data = JSON.parse(readFileSync23(claudeJsonNested, "utf-8"));
|
|
25236
25647
|
return Boolean(data.oauthAccount);
|
|
25237
25648
|
} catch {
|
|
25238
25649
|
return false;
|
|
@@ -25253,9 +25664,9 @@ var init_backend_cmd_factory = __esm({
|
|
|
25253
25664
|
} catch {
|
|
25254
25665
|
}
|
|
25255
25666
|
try {
|
|
25256
|
-
const claudeJson =
|
|
25257
|
-
if (
|
|
25258
|
-
const data = JSON.parse(
|
|
25667
|
+
const claudeJson = join32(slotDir, ".claude.json");
|
|
25668
|
+
if (existsSync35(claudeJson)) {
|
|
25669
|
+
const data = JSON.parse(readFileSync23(claudeJson, "utf-8"));
|
|
25259
25670
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
25260
25671
|
}
|
|
25261
25672
|
} catch {
|
|
@@ -25270,11 +25681,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
25270
25681
|
envValue: (slotDir) => slotDir,
|
|
25271
25682
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
25272
25683
|
verifyCredentials: (slotDir) => {
|
|
25273
|
-
return
|
|
25684
|
+
return existsSync35(join32(slotDir, "auth.json"));
|
|
25274
25685
|
},
|
|
25275
25686
|
extractLabel: (slotDir) => {
|
|
25276
25687
|
try {
|
|
25277
|
-
const authData = JSON.parse(
|
|
25688
|
+
const authData = JSON.parse(readFileSync23(join32(slotDir, "auth.json"), "utf-8"));
|
|
25278
25689
|
if (authData.email) return authData.email;
|
|
25279
25690
|
if (authData.account_name) return authData.account_name;
|
|
25280
25691
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -25294,12 +25705,12 @@ __export(backend_exports, {
|
|
|
25294
25705
|
backendList: () => backendList,
|
|
25295
25706
|
backendSet: () => backendSet
|
|
25296
25707
|
});
|
|
25297
|
-
import { existsSync as
|
|
25708
|
+
import { existsSync as existsSync36 } from "fs";
|
|
25298
25709
|
async function backendList(globalOpts) {
|
|
25299
25710
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
25300
25711
|
const chatId = resolveChatId(globalOpts);
|
|
25301
25712
|
let activeBackend = null;
|
|
25302
|
-
if (
|
|
25713
|
+
if (existsSync36(DB_PATH)) {
|
|
25303
25714
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25304
25715
|
const readDb = openDatabaseReadOnly2();
|
|
25305
25716
|
try {
|
|
@@ -25330,7 +25741,7 @@ async function backendList(globalOpts) {
|
|
|
25330
25741
|
}
|
|
25331
25742
|
async function backendGet(globalOpts) {
|
|
25332
25743
|
const chatId = resolveChatId(globalOpts);
|
|
25333
|
-
if (!
|
|
25744
|
+
if (!existsSync36(DB_PATH)) {
|
|
25334
25745
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25335
25746
|
process.exit(1);
|
|
25336
25747
|
}
|
|
@@ -25374,13 +25785,13 @@ __export(model_exports, {
|
|
|
25374
25785
|
modelList: () => modelList,
|
|
25375
25786
|
modelSet: () => modelSet
|
|
25376
25787
|
});
|
|
25377
|
-
import { existsSync as
|
|
25788
|
+
import { existsSync as existsSync37 } from "fs";
|
|
25378
25789
|
async function modelList(globalOpts) {
|
|
25379
25790
|
const chatId = resolveChatId(globalOpts);
|
|
25380
25791
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25381
25792
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
25382
25793
|
let backendId = "claude";
|
|
25383
|
-
if (
|
|
25794
|
+
if (existsSync37(DB_PATH)) {
|
|
25384
25795
|
const readDb = openDatabaseReadOnly2();
|
|
25385
25796
|
try {
|
|
25386
25797
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -25413,7 +25824,7 @@ async function modelList(globalOpts) {
|
|
|
25413
25824
|
}
|
|
25414
25825
|
async function modelGet(globalOpts) {
|
|
25415
25826
|
const chatId = resolveChatId(globalOpts);
|
|
25416
|
-
if (!
|
|
25827
|
+
if (!existsSync37(DB_PATH)) {
|
|
25417
25828
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25418
25829
|
process.exit(1);
|
|
25419
25830
|
}
|
|
@@ -25457,9 +25868,9 @@ __export(memory_exports2, {
|
|
|
25457
25868
|
memoryList: () => memoryList,
|
|
25458
25869
|
memorySearch: () => memorySearch
|
|
25459
25870
|
});
|
|
25460
|
-
import { existsSync as
|
|
25871
|
+
import { existsSync as existsSync38 } from "fs";
|
|
25461
25872
|
async function memoryList(globalOpts) {
|
|
25462
|
-
if (!
|
|
25873
|
+
if (!existsSync38(DB_PATH)) {
|
|
25463
25874
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25464
25875
|
process.exit(1);
|
|
25465
25876
|
}
|
|
@@ -25483,7 +25894,7 @@ async function memoryList(globalOpts) {
|
|
|
25483
25894
|
});
|
|
25484
25895
|
}
|
|
25485
25896
|
async function memorySearch(globalOpts, query) {
|
|
25486
|
-
if (!
|
|
25897
|
+
if (!existsSync38(DB_PATH)) {
|
|
25487
25898
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25488
25899
|
process.exit(1);
|
|
25489
25900
|
}
|
|
@@ -25505,7 +25916,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
25505
25916
|
});
|
|
25506
25917
|
}
|
|
25507
25918
|
async function memoryHistory(globalOpts, opts) {
|
|
25508
|
-
if (!
|
|
25919
|
+
if (!existsSync38(DB_PATH)) {
|
|
25509
25920
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25510
25921
|
process.exit(1);
|
|
25511
25922
|
}
|
|
@@ -25553,7 +25964,7 @@ __export(cron_exports2, {
|
|
|
25553
25964
|
cronList: () => cronList,
|
|
25554
25965
|
cronRuns: () => cronRuns
|
|
25555
25966
|
});
|
|
25556
|
-
import { existsSync as
|
|
25967
|
+
import { existsSync as existsSync39 } from "fs";
|
|
25557
25968
|
function parseFallbacks(raw) {
|
|
25558
25969
|
return raw.slice(0, 3).map((f) => {
|
|
25559
25970
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -25574,7 +25985,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
25574
25985
|
return val;
|
|
25575
25986
|
}
|
|
25576
25987
|
async function cronList(globalOpts) {
|
|
25577
|
-
if (!
|
|
25988
|
+
if (!existsSync39(DB_PATH)) {
|
|
25578
25989
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25579
25990
|
process.exit(1);
|
|
25580
25991
|
}
|
|
@@ -25612,7 +26023,7 @@ async function cronList(globalOpts) {
|
|
|
25612
26023
|
});
|
|
25613
26024
|
}
|
|
25614
26025
|
async function cronHealth(globalOpts) {
|
|
25615
|
-
if (!
|
|
26026
|
+
if (!existsSync39(DB_PATH)) {
|
|
25616
26027
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25617
26028
|
process.exit(1);
|
|
25618
26029
|
}
|
|
@@ -25771,7 +26182,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
25771
26182
|
}
|
|
25772
26183
|
}
|
|
25773
26184
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
25774
|
-
if (!
|
|
26185
|
+
if (!existsSync39(DB_PATH)) {
|
|
25775
26186
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25776
26187
|
process.exit(1);
|
|
25777
26188
|
}
|
|
@@ -25818,9 +26229,9 @@ __export(agents_exports, {
|
|
|
25818
26229
|
runnersList: () => runnersList,
|
|
25819
26230
|
tasksList: () => tasksList
|
|
25820
26231
|
});
|
|
25821
|
-
import { existsSync as
|
|
26232
|
+
import { existsSync as existsSync40 } from "fs";
|
|
25822
26233
|
async function agentsList(globalOpts) {
|
|
25823
|
-
if (!
|
|
26234
|
+
if (!existsSync40(DB_PATH)) {
|
|
25824
26235
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25825
26236
|
process.exit(1);
|
|
25826
26237
|
}
|
|
@@ -25851,7 +26262,7 @@ async function agentsList(globalOpts) {
|
|
|
25851
26262
|
});
|
|
25852
26263
|
}
|
|
25853
26264
|
async function tasksList(globalOpts) {
|
|
25854
|
-
if (!
|
|
26265
|
+
if (!existsSync40(DB_PATH)) {
|
|
25855
26266
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25856
26267
|
process.exit(1);
|
|
25857
26268
|
}
|
|
@@ -25979,18 +26390,18 @@ __export(db_exports, {
|
|
|
25979
26390
|
dbPath: () => dbPath,
|
|
25980
26391
|
dbStats: () => dbStats
|
|
25981
26392
|
});
|
|
25982
|
-
import { existsSync as
|
|
26393
|
+
import { existsSync as existsSync41, statSync as statSync11, copyFileSync as copyFileSync3, mkdirSync as mkdirSync16 } from "fs";
|
|
25983
26394
|
import { dirname as dirname7 } from "path";
|
|
25984
26395
|
async function dbStats(globalOpts) {
|
|
25985
|
-
if (!
|
|
26396
|
+
if (!existsSync41(DB_PATH)) {
|
|
25986
26397
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
25987
26398
|
process.exit(1);
|
|
25988
26399
|
}
|
|
25989
26400
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25990
26401
|
const readDb = openDatabaseReadOnly2();
|
|
25991
|
-
const mainSize =
|
|
26402
|
+
const mainSize = statSync11(DB_PATH).size;
|
|
25992
26403
|
const walPath = DB_PATH + "-wal";
|
|
25993
|
-
const walSize =
|
|
26404
|
+
const walSize = existsSync41(walPath) ? statSync11(walPath).size : 0;
|
|
25994
26405
|
const tableNames = readDb.prepare(
|
|
25995
26406
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
25996
26407
|
).all();
|
|
@@ -26024,17 +26435,17 @@ async function dbPath(globalOpts) {
|
|
|
26024
26435
|
output({ path: DB_PATH }, (d) => d.path);
|
|
26025
26436
|
}
|
|
26026
26437
|
async function dbBackup(globalOpts, destPath) {
|
|
26027
|
-
if (!
|
|
26438
|
+
if (!existsSync41(DB_PATH)) {
|
|
26028
26439
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
26029
26440
|
process.exit(1);
|
|
26030
26441
|
}
|
|
26031
26442
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
26032
26443
|
try {
|
|
26033
|
-
|
|
26444
|
+
mkdirSync16(dirname7(dest), { recursive: true });
|
|
26034
26445
|
copyFileSync3(DB_PATH, dest);
|
|
26035
26446
|
const walPath = DB_PATH + "-wal";
|
|
26036
|
-
if (
|
|
26037
|
-
output({ path: dest, sizeBytes:
|
|
26447
|
+
if (existsSync41(walPath)) copyFileSync3(walPath, dest + "-wal");
|
|
26448
|
+
output({ path: dest, sizeBytes: statSync11(dest).size }, (d) => {
|
|
26038
26449
|
const b = d;
|
|
26039
26450
|
return `
|
|
26040
26451
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -26062,9 +26473,9 @@ __export(usage_exports, {
|
|
|
26062
26473
|
usageCost: () => usageCost,
|
|
26063
26474
|
usageTokens: () => usageTokens
|
|
26064
26475
|
});
|
|
26065
|
-
import { existsSync as
|
|
26476
|
+
import { existsSync as existsSync42 } from "fs";
|
|
26066
26477
|
function ensureDb() {
|
|
26067
|
-
if (!
|
|
26478
|
+
if (!existsSync42(DB_PATH)) {
|
|
26068
26479
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
26069
26480
|
process.exit(1);
|
|
26070
26481
|
}
|
|
@@ -26254,9 +26665,9 @@ __export(config_exports2, {
|
|
|
26254
26665
|
configList: () => configList,
|
|
26255
26666
|
configSet: () => configSet
|
|
26256
26667
|
});
|
|
26257
|
-
import { existsSync as
|
|
26668
|
+
import { existsSync as existsSync43, readFileSync as readFileSync24 } from "fs";
|
|
26258
26669
|
async function configList(globalOpts) {
|
|
26259
|
-
if (!
|
|
26670
|
+
if (!existsSync43(DB_PATH)) {
|
|
26260
26671
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26261
26672
|
process.exit(1);
|
|
26262
26673
|
}
|
|
@@ -26290,7 +26701,7 @@ async function configGet(globalOpts, key) {
|
|
|
26290
26701
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
26291
26702
|
process.exit(1);
|
|
26292
26703
|
}
|
|
26293
|
-
if (!
|
|
26704
|
+
if (!existsSync43(DB_PATH)) {
|
|
26294
26705
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26295
26706
|
process.exit(1);
|
|
26296
26707
|
}
|
|
@@ -26336,11 +26747,11 @@ async function configSet(globalOpts, key, value) {
|
|
|
26336
26747
|
}
|
|
26337
26748
|
}
|
|
26338
26749
|
async function configEnv(_globalOpts) {
|
|
26339
|
-
if (!
|
|
26750
|
+
if (!existsSync43(ENV_PATH)) {
|
|
26340
26751
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
26341
26752
|
process.exit(1);
|
|
26342
26753
|
}
|
|
26343
|
-
const content =
|
|
26754
|
+
const content = readFileSync24(ENV_PATH, "utf-8");
|
|
26344
26755
|
const entries = {};
|
|
26345
26756
|
const secretPatterns = /TOKEN|KEY|SECRET|PASSWORD|CREDENTIALS/i;
|
|
26346
26757
|
for (const line of content.split("\n")) {
|
|
@@ -26390,9 +26801,9 @@ __export(session_exports, {
|
|
|
26390
26801
|
sessionGet: () => sessionGet,
|
|
26391
26802
|
sessionNew: () => sessionNew
|
|
26392
26803
|
});
|
|
26393
|
-
import { existsSync as
|
|
26804
|
+
import { existsSync as existsSync44 } from "fs";
|
|
26394
26805
|
async function sessionGet(globalOpts) {
|
|
26395
|
-
if (!
|
|
26806
|
+
if (!existsSync44(DB_PATH)) {
|
|
26396
26807
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26397
26808
|
process.exit(1);
|
|
26398
26809
|
}
|
|
@@ -26453,9 +26864,9 @@ __export(permissions_exports, {
|
|
|
26453
26864
|
verboseGet: () => verboseGet,
|
|
26454
26865
|
verboseSet: () => verboseSet
|
|
26455
26866
|
});
|
|
26456
|
-
import { existsSync as
|
|
26867
|
+
import { existsSync as existsSync45 } from "fs";
|
|
26457
26868
|
function ensureDb2() {
|
|
26458
|
-
if (!
|
|
26869
|
+
if (!existsSync45(DB_PATH)) {
|
|
26459
26870
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26460
26871
|
process.exit(1);
|
|
26461
26872
|
}
|
|
@@ -26602,9 +27013,9 @@ __export(cwd_exports, {
|
|
|
26602
27013
|
cwdGet: () => cwdGet,
|
|
26603
27014
|
cwdSet: () => cwdSet
|
|
26604
27015
|
});
|
|
26605
|
-
import { existsSync as
|
|
27016
|
+
import { existsSync as existsSync46 } from "fs";
|
|
26606
27017
|
async function cwdGet(globalOpts) {
|
|
26607
|
-
if (!
|
|
27018
|
+
if (!existsSync46(DB_PATH)) {
|
|
26608
27019
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26609
27020
|
process.exit(1);
|
|
26610
27021
|
}
|
|
@@ -26666,9 +27077,9 @@ __export(voice_exports, {
|
|
|
26666
27077
|
voiceGet: () => voiceGet,
|
|
26667
27078
|
voiceSet: () => voiceSet
|
|
26668
27079
|
});
|
|
26669
|
-
import { existsSync as
|
|
27080
|
+
import { existsSync as existsSync47 } from "fs";
|
|
26670
27081
|
async function voiceGet(globalOpts) {
|
|
26671
|
-
if (!
|
|
27082
|
+
if (!existsSync47(DB_PATH)) {
|
|
26672
27083
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26673
27084
|
process.exit(1);
|
|
26674
27085
|
}
|
|
@@ -26717,9 +27128,9 @@ __export(heartbeat_exports, {
|
|
|
26717
27128
|
heartbeatGet: () => heartbeatGet,
|
|
26718
27129
|
heartbeatSet: () => heartbeatSet
|
|
26719
27130
|
});
|
|
26720
|
-
import { existsSync as
|
|
27131
|
+
import { existsSync as existsSync48 } from "fs";
|
|
26721
27132
|
async function heartbeatGet(globalOpts) {
|
|
26722
|
-
if (!
|
|
27133
|
+
if (!existsSync48(DB_PATH)) {
|
|
26723
27134
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26724
27135
|
process.exit(1);
|
|
26725
27136
|
}
|
|
@@ -26828,9 +27239,9 @@ __export(summarizer_exports, {
|
|
|
26828
27239
|
summarizerGet: () => summarizerGet,
|
|
26829
27240
|
summarizerSet: () => summarizerSet
|
|
26830
27241
|
});
|
|
26831
|
-
import { existsSync as
|
|
27242
|
+
import { existsSync as existsSync49 } from "fs";
|
|
26832
27243
|
async function summarizerGet(globalOpts) {
|
|
26833
|
-
if (!
|
|
27244
|
+
if (!existsSync49(DB_PATH)) {
|
|
26834
27245
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26835
27246
|
process.exit(1);
|
|
26836
27247
|
}
|
|
@@ -26874,9 +27285,9 @@ __export(thinking_exports, {
|
|
|
26874
27285
|
thinkingGet: () => thinkingGet,
|
|
26875
27286
|
thinkingSet: () => thinkingSet
|
|
26876
27287
|
});
|
|
26877
|
-
import { existsSync as
|
|
27288
|
+
import { existsSync as existsSync50 } from "fs";
|
|
26878
27289
|
async function thinkingGet(globalOpts) {
|
|
26879
|
-
if (!
|
|
27290
|
+
if (!existsSync50(DB_PATH)) {
|
|
26880
27291
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26881
27292
|
process.exit(1);
|
|
26882
27293
|
}
|
|
@@ -26920,9 +27331,9 @@ __export(chats_exports, {
|
|
|
26920
27331
|
chatsList: () => chatsList,
|
|
26921
27332
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
26922
27333
|
});
|
|
26923
|
-
import { existsSync as
|
|
27334
|
+
import { existsSync as existsSync51 } from "fs";
|
|
26924
27335
|
async function chatsList(_globalOpts) {
|
|
26925
|
-
if (!
|
|
27336
|
+
if (!existsSync51(DB_PATH)) {
|
|
26926
27337
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26927
27338
|
process.exit(1);
|
|
26928
27339
|
}
|
|
@@ -27050,9 +27461,9 @@ var mcps_exports2 = {};
|
|
|
27050
27461
|
__export(mcps_exports2, {
|
|
27051
27462
|
mcpsList: () => mcpsList
|
|
27052
27463
|
});
|
|
27053
|
-
import { existsSync as
|
|
27464
|
+
import { existsSync as existsSync52 } from "fs";
|
|
27054
27465
|
async function mcpsList(_globalOpts) {
|
|
27055
|
-
if (!
|
|
27466
|
+
if (!existsSync52(DB_PATH)) {
|
|
27056
27467
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
27057
27468
|
process.exit(1);
|
|
27058
27469
|
}
|
|
@@ -27089,11 +27500,11 @@ __export(chat_exports2, {
|
|
|
27089
27500
|
chatSend: () => chatSend
|
|
27090
27501
|
});
|
|
27091
27502
|
import { request as httpRequest2 } from "http";
|
|
27092
|
-
import { readFileSync as
|
|
27503
|
+
import { readFileSync as readFileSync25, existsSync as existsSync53 } from "fs";
|
|
27093
27504
|
function getToken2() {
|
|
27094
27505
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
27095
27506
|
try {
|
|
27096
|
-
if (
|
|
27507
|
+
if (existsSync53(TOKEN_PATH2)) return readFileSync25(TOKEN_PATH2, "utf-8").trim();
|
|
27097
27508
|
} catch {
|
|
27098
27509
|
}
|
|
27099
27510
|
return null;
|
|
@@ -27230,7 +27641,7 @@ var tui_exports = {};
|
|
|
27230
27641
|
__export(tui_exports, {
|
|
27231
27642
|
tuiCommand: () => tuiCommand
|
|
27232
27643
|
});
|
|
27233
|
-
import { createInterface as
|
|
27644
|
+
import { createInterface as createInterface9 } from "readline";
|
|
27234
27645
|
import pc2 from "picocolors";
|
|
27235
27646
|
async function tuiCommand(globalOpts, cmdOpts) {
|
|
27236
27647
|
const { isDaemonRunning: isDaemonRunning2, apiPost: apiPost2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
@@ -27240,7 +27651,7 @@ async function tuiCommand(globalOpts, cmdOpts) {
|
|
|
27240
27651
|
}
|
|
27241
27652
|
const chatId = resolveChatId(globalOpts);
|
|
27242
27653
|
const { chatSend: chatSend2 } = await Promise.resolve().then(() => (init_chat2(), chat_exports2));
|
|
27243
|
-
const rl2 =
|
|
27654
|
+
const rl2 = createInterface9({
|
|
27244
27655
|
input: process.stdin,
|
|
27245
27656
|
output: process.stdout,
|
|
27246
27657
|
prompt: pc2.cyan("you > "),
|
|
@@ -27372,8 +27783,8 @@ var completion_exports = {};
|
|
|
27372
27783
|
__export(completion_exports, {
|
|
27373
27784
|
completionCommand: () => completionCommand
|
|
27374
27785
|
});
|
|
27375
|
-
import { writeFileSync as writeFileSync11, mkdirSync as
|
|
27376
|
-
import { join as
|
|
27786
|
+
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync17 } from "fs";
|
|
27787
|
+
import { join as join33 } from "path";
|
|
27377
27788
|
import { homedir as homedir11 } from "os";
|
|
27378
27789
|
async function completionCommand(opts) {
|
|
27379
27790
|
const shell = opts.shell ?? detectShell();
|
|
@@ -27389,10 +27800,10 @@ async function completionCommand(opts) {
|
|
|
27389
27800
|
process.exit(1);
|
|
27390
27801
|
}
|
|
27391
27802
|
if (opts.install) {
|
|
27392
|
-
const dir =
|
|
27393
|
-
|
|
27803
|
+
const dir = join33(homedir11(), ".config", "cc-claw", "completions");
|
|
27804
|
+
mkdirSync17(dir, { recursive: true });
|
|
27394
27805
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
27395
|
-
const filepath =
|
|
27806
|
+
const filepath = join33(dir, filename);
|
|
27396
27807
|
writeFileSync11(filepath, script, "utf-8");
|
|
27397
27808
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
27398
27809
|
`);
|
|
@@ -27563,9 +27974,9 @@ __export(evolve_exports2, {
|
|
|
27563
27974
|
evolveStatus: () => evolveStatus,
|
|
27564
27975
|
evolveUndo: () => evolveUndo
|
|
27565
27976
|
});
|
|
27566
|
-
import { existsSync as
|
|
27977
|
+
import { existsSync as existsSync54 } from "fs";
|
|
27567
27978
|
function ensureDb3() {
|
|
27568
|
-
if (!
|
|
27979
|
+
if (!existsSync54(DB_PATH)) {
|
|
27569
27980
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
27570
27981
|
process.exit(1);
|
|
27571
27982
|
}
|
|
@@ -28039,10 +28450,10 @@ var init_optimize2 = __esm({
|
|
|
28039
28450
|
|
|
28040
28451
|
// src/setup.ts
|
|
28041
28452
|
var setup_exports = {};
|
|
28042
|
-
import { existsSync as
|
|
28453
|
+
import { existsSync as existsSync55, writeFileSync as writeFileSync12, readFileSync as readFileSync26, copyFileSync as copyFileSync4, mkdirSync as mkdirSync18, statSync as statSync12 } from "fs";
|
|
28043
28454
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
28044
|
-
import { createInterface as
|
|
28045
|
-
import { join as
|
|
28455
|
+
import { createInterface as createInterface10 } from "readline";
|
|
28456
|
+
import { join as join34 } from "path";
|
|
28046
28457
|
function divider2() {
|
|
28047
28458
|
console.log(dim("\u2500".repeat(55)));
|
|
28048
28459
|
}
|
|
@@ -28117,22 +28528,22 @@ async function setup() {
|
|
|
28117
28528
|
}
|
|
28118
28529
|
console.log("");
|
|
28119
28530
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
28120
|
-
if (!
|
|
28531
|
+
if (!existsSync55(dir)) mkdirSync18(dir, { recursive: true });
|
|
28121
28532
|
}
|
|
28122
28533
|
const env = {};
|
|
28123
|
-
const envSource =
|
|
28534
|
+
const envSource = existsSync55(ENV_PATH) ? ENV_PATH : existsSync55(".env") ? ".env" : null;
|
|
28124
28535
|
if (envSource) {
|
|
28125
28536
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
28126
28537
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
28127
|
-
const existing =
|
|
28538
|
+
const existing = readFileSync26(envSource, "utf-8");
|
|
28128
28539
|
for (const line of existing.split("\n")) {
|
|
28129
28540
|
const match = line.match(/^([^#=]+)=(.*)$/);
|
|
28130
28541
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
28131
28542
|
}
|
|
28132
28543
|
}
|
|
28133
|
-
const cwdDb =
|
|
28134
|
-
if (
|
|
28135
|
-
const { size } =
|
|
28544
|
+
const cwdDb = join34(process.cwd(), "cc-claw.db");
|
|
28545
|
+
if (existsSync55(cwdDb) && !existsSync55(DB_PATH)) {
|
|
28546
|
+
const { size } = statSync12(cwdDb);
|
|
28136
28547
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
28137
28548
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
28138
28549
|
if (migrate) {
|
|
@@ -28404,7 +28815,7 @@ var init_setup = __esm({
|
|
|
28404
28815
|
"src/setup.ts"() {
|
|
28405
28816
|
"use strict";
|
|
28406
28817
|
init_paths();
|
|
28407
|
-
rl =
|
|
28818
|
+
rl = createInterface10({ input: process.stdin, output: process.stdout });
|
|
28408
28819
|
ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
28409
28820
|
bold = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
28410
28821
|
green = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
@@ -28473,6 +28884,19 @@ program.command("logs").description("Tail daemon logs").option("-f, --follow", "
|
|
|
28473
28884
|
const { logsCommand: logsCommand2 } = await Promise.resolve().then(() => (init_logs(), logs_exports));
|
|
28474
28885
|
await logsCommand2(opts);
|
|
28475
28886
|
});
|
|
28887
|
+
var sessionLogs = program.command("session-logs").description("Manage session debug logs (enable via /debug in Telegram)");
|
|
28888
|
+
sessionLogs.command("list").description("List all session debug logs").action(async () => {
|
|
28889
|
+
const { sessionLogsList: sessionLogsList2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
28890
|
+
await sessionLogsList2(program.opts());
|
|
28891
|
+
});
|
|
28892
|
+
sessionLogs.command("tail").description("Tail latest (or specific) session log").option("-f, --follow", "Follow mode (like tail -f)").option("--file <name>", "Specific log file (partial match)").option("--lines <n>", "Number of lines", "50").action(async (opts) => {
|
|
28893
|
+
const { sessionLogsTail: sessionLogsTail2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
28894
|
+
await sessionLogsTail2(opts);
|
|
28895
|
+
});
|
|
28896
|
+
sessionLogs.command("clean").description("Remove old session logs").option("--days <n>", "Remove logs older than N days").action(async (opts) => {
|
|
28897
|
+
const { sessionLogsClean: sessionLogsClean2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
28898
|
+
await sessionLogsClean2(opts);
|
|
28899
|
+
});
|
|
28476
28900
|
var gemini = program.command("gemini").description("Manage Gemini credential slots for rotation");
|
|
28477
28901
|
gemini.command("list").description("Show all configured Gemini credential slots").action(async () => {
|
|
28478
28902
|
const { geminiList: geminiList2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|