cc-claw 0.18.0 → 0.18.2
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 +924 -303
- 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.2" : (() => {
|
|
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
|
});
|
|
@@ -1340,7 +1342,8 @@ function initSchema(db3) {
|
|
|
1340
1342
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1341
1343
|
last_run_at TEXT,
|
|
1342
1344
|
next_run_at TEXT,
|
|
1343
|
-
consecutive_failures INTEGER NOT NULL DEFAULT 0
|
|
1345
|
+
consecutive_failures INTEGER NOT NULL DEFAULT 0,
|
|
1346
|
+
allow_paid_slots INTEGER NOT NULL DEFAULT 0
|
|
1344
1347
|
);
|
|
1345
1348
|
`);
|
|
1346
1349
|
try {
|
|
@@ -1496,6 +1499,10 @@ function initSchema(db3) {
|
|
|
1496
1499
|
db3.exec("ALTER TABLE jobs ADD COLUMN job_type TEXT DEFAULT 'normal'");
|
|
1497
1500
|
} catch {
|
|
1498
1501
|
}
|
|
1502
|
+
try {
|
|
1503
|
+
db3.exec("ALTER TABLE jobs ADD COLUMN allow_paid_slots INTEGER NOT NULL DEFAULT 0");
|
|
1504
|
+
} catch {
|
|
1505
|
+
}
|
|
1499
1506
|
try {
|
|
1500
1507
|
db3.exec("UPDATE jobs SET job_type = 'reflection' WHERE description LIKE '%reflection analysis%' AND job_type = 'normal'");
|
|
1501
1508
|
} catch {
|
|
@@ -1749,6 +1756,12 @@ function initSchema(db3) {
|
|
|
1749
1756
|
value INTEGER NOT NULL DEFAULT 0
|
|
1750
1757
|
);
|
|
1751
1758
|
`);
|
|
1759
|
+
db3.exec(`
|
|
1760
|
+
CREATE TABLE IF NOT EXISTS chat_session_log (
|
|
1761
|
+
chat_id TEXT PRIMARY KEY,
|
|
1762
|
+
value INTEGER NOT NULL DEFAULT 0
|
|
1763
|
+
);
|
|
1764
|
+
`);
|
|
1752
1765
|
db3.exec(`
|
|
1753
1766
|
CREATE TABLE IF NOT EXISTS backend_credentials (
|
|
1754
1767
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -1773,6 +1786,13 @@ function initSchema(db3) {
|
|
|
1773
1786
|
PRIMARY KEY (chat_id, backend)
|
|
1774
1787
|
);
|
|
1775
1788
|
`);
|
|
1789
|
+
db3.exec(`
|
|
1790
|
+
CREATE TABLE IF NOT EXISTS chat_allow_paid_slots (
|
|
1791
|
+
chat_id TEXT NOT NULL,
|
|
1792
|
+
backend TEXT NOT NULL,
|
|
1793
|
+
PRIMARY KEY (chat_id, backend)
|
|
1794
|
+
);
|
|
1795
|
+
`);
|
|
1776
1796
|
try {
|
|
1777
1797
|
const deleted = db3.prepare(
|
|
1778
1798
|
"DELETE FROM usage_log WHERE created_at < datetime('now', '-90 days')"
|
|
@@ -2437,6 +2457,8 @@ var chat_settings_exports = {};
|
|
|
2437
2457
|
__export(chat_settings_exports, {
|
|
2438
2458
|
ALL_TOOLS: () => ALL_TOOLS,
|
|
2439
2459
|
clearAgentMode: () => clearAgentMode,
|
|
2460
|
+
clearAllPaidSlots: () => clearAllPaidSlots,
|
|
2461
|
+
clearChatPaidSlots: () => clearChatPaidSlots,
|
|
2440
2462
|
clearCwd: () => clearCwd,
|
|
2441
2463
|
clearExecMode: () => clearExecMode,
|
|
2442
2464
|
clearModel: () => clearModel,
|
|
@@ -2447,6 +2469,7 @@ __export(chat_settings_exports, {
|
|
|
2447
2469
|
findBookmarksByPrefix: () => findBookmarksByPrefix,
|
|
2448
2470
|
getAgentMode: () => getAgentMode,
|
|
2449
2471
|
getAllBookmarks: () => getAllBookmarks,
|
|
2472
|
+
getAllowPaidSlots: () => getAllowPaidSlots,
|
|
2450
2473
|
getBackend: () => getBackend,
|
|
2451
2474
|
getBookmark: () => getBookmark,
|
|
2452
2475
|
getCwd: () => getCwd,
|
|
@@ -2456,6 +2479,7 @@ __export(chat_settings_exports, {
|
|
|
2456
2479
|
getModel: () => getModel,
|
|
2457
2480
|
getPendingEscalation: () => getPendingEscalation,
|
|
2458
2481
|
getRecentBookmarks: () => getRecentBookmarks,
|
|
2482
|
+
getSessionLogEnabled: () => getSessionLogEnabled,
|
|
2459
2483
|
getShowThinkingUi: () => getShowThinkingUi,
|
|
2460
2484
|
getSummarizer: () => getSummarizer,
|
|
2461
2485
|
getThinkingLevel: () => getThinkingLevel,
|
|
@@ -2464,16 +2488,19 @@ __export(chat_settings_exports, {
|
|
|
2464
2488
|
removePendingEscalation: () => removePendingEscalation,
|
|
2465
2489
|
resetTools: () => resetTools,
|
|
2466
2490
|
setAgentMode: () => setAgentMode,
|
|
2491
|
+
setAllowPaidSlots: () => setAllowPaidSlots,
|
|
2467
2492
|
setBackend: () => setBackend,
|
|
2468
2493
|
setCwd: () => setCwd,
|
|
2469
2494
|
setExecMode: () => setExecMode,
|
|
2470
2495
|
setMode: () => setMode,
|
|
2471
2496
|
setModel: () => setModel,
|
|
2497
|
+
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
2472
2498
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
2473
2499
|
setSummarizer: () => setSummarizer,
|
|
2474
2500
|
setThinkingLevel: () => setThinkingLevel,
|
|
2475
2501
|
setVerboseLevel: () => setVerboseLevel,
|
|
2476
2502
|
storePendingEscalation: () => storePendingEscalation,
|
|
2503
|
+
toggleSessionLogEnabled: () => toggleSessionLogEnabled,
|
|
2477
2504
|
toggleShowThinkingUi: () => toggleShowThinkingUi,
|
|
2478
2505
|
toggleTool: () => toggleTool,
|
|
2479
2506
|
touchBookmark: () => touchBookmark,
|
|
@@ -2744,6 +2771,42 @@ function setExecMode(chatId, mode) {
|
|
|
2744
2771
|
function clearExecMode(chatId) {
|
|
2745
2772
|
getDb().prepare("DELETE FROM chat_exec_mode WHERE chat_id = ?").run(chatId);
|
|
2746
2773
|
}
|
|
2774
|
+
function getSessionLogEnabled(chatId) {
|
|
2775
|
+
const row = getDb().prepare(
|
|
2776
|
+
"SELECT value FROM chat_session_log WHERE chat_id = ?"
|
|
2777
|
+
).get(chatId);
|
|
2778
|
+
return (row?.value ?? 0) === 1;
|
|
2779
|
+
}
|
|
2780
|
+
function setSessionLogEnabled(chatId, enabled) {
|
|
2781
|
+
getDb().prepare(`
|
|
2782
|
+
INSERT INTO chat_session_log (chat_id, value)
|
|
2783
|
+
VALUES (?, ?)
|
|
2784
|
+
ON CONFLICT(chat_id) DO UPDATE SET value = ?
|
|
2785
|
+
`).run(chatId, enabled ? 1 : 0, enabled ? 1 : 0);
|
|
2786
|
+
}
|
|
2787
|
+
function toggleSessionLogEnabled(chatId) {
|
|
2788
|
+
const current = getSessionLogEnabled(chatId);
|
|
2789
|
+
const next = !current;
|
|
2790
|
+
setSessionLogEnabled(chatId, next);
|
|
2791
|
+
return next;
|
|
2792
|
+
}
|
|
2793
|
+
function getAllowPaidSlots(chatId, backend2) {
|
|
2794
|
+
const row = getDb().prepare(
|
|
2795
|
+
"SELECT 1 FROM chat_allow_paid_slots WHERE chat_id = ? AND backend = ?"
|
|
2796
|
+
).get(chatId, backend2);
|
|
2797
|
+
return !!row;
|
|
2798
|
+
}
|
|
2799
|
+
function setAllowPaidSlots(chatId, backend2) {
|
|
2800
|
+
getDb().prepare(`
|
|
2801
|
+
INSERT OR IGNORE INTO chat_allow_paid_slots (chat_id, backend) VALUES (?, ?)
|
|
2802
|
+
`).run(chatId, backend2);
|
|
2803
|
+
}
|
|
2804
|
+
function clearChatPaidSlots(chatId) {
|
|
2805
|
+
getDb().prepare("DELETE FROM chat_allow_paid_slots WHERE chat_id = ?").run(chatId);
|
|
2806
|
+
}
|
|
2807
|
+
function clearAllPaidSlots() {
|
|
2808
|
+
getDb().prepare("DELETE FROM chat_allow_paid_slots").run();
|
|
2809
|
+
}
|
|
2747
2810
|
var pendingEscalations, ESCALATION_TTL_MS, ALL_TOOLS;
|
|
2748
2811
|
var init_chat_settings = __esm({
|
|
2749
2812
|
"src/memory/chat-settings.ts"() {
|
|
@@ -3008,8 +3071,8 @@ function insertJob(params) {
|
|
|
3008
3071
|
const db3 = getDb();
|
|
3009
3072
|
const result = db3.prepare(`
|
|
3010
3073
|
INSERT INTO jobs (schedule_type, cron, at_time, every_ms, title, description, chat_id,
|
|
3011
|
-
backend, model, thinking, timeout, fallbacks, session_type, channel, target, delivery_mode, timezone, job_type)
|
|
3012
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3074
|
+
backend, model, thinking, timeout, fallbacks, session_type, channel, target, delivery_mode, timezone, job_type, allow_paid_slots)
|
|
3075
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3013
3076
|
`).run(
|
|
3014
3077
|
params.scheduleType,
|
|
3015
3078
|
params.cron ?? null,
|
|
@@ -3028,13 +3091,15 @@ function insertJob(params) {
|
|
|
3028
3091
|
params.target ?? null,
|
|
3029
3092
|
params.deliveryMode ?? "announce",
|
|
3030
3093
|
params.timezone ?? "UTC",
|
|
3031
|
-
params.jobType ?? "normal"
|
|
3094
|
+
params.jobType ?? "normal",
|
|
3095
|
+
params.allowPaidSlots ? 1 : 0
|
|
3032
3096
|
);
|
|
3033
3097
|
return getJobById(Number(result.lastInsertRowid));
|
|
3034
3098
|
}
|
|
3035
3099
|
function mapJobRow(row) {
|
|
3036
3100
|
if (!row) return void 0;
|
|
3037
3101
|
row.fallbacks = row.fallbacks ? JSON.parse(row.fallbacks) : [];
|
|
3102
|
+
row.allowPaidSlots = !!row.allowPaidSlots;
|
|
3038
3103
|
return row;
|
|
3039
3104
|
}
|
|
3040
3105
|
function getJobById(id) {
|
|
@@ -3088,7 +3153,8 @@ function updateJob(id, fields) {
|
|
|
3088
3153
|
target: "target",
|
|
3089
3154
|
deliveryMode: "delivery_mode",
|
|
3090
3155
|
timezone: "timezone",
|
|
3091
|
-
jobType: "job_type"
|
|
3156
|
+
jobType: "job_type",
|
|
3157
|
+
allowPaidSlots: "allow_paid_slots"
|
|
3092
3158
|
};
|
|
3093
3159
|
for (const [key, val] of Object.entries(fields)) {
|
|
3094
3160
|
const col = fieldMap[key];
|
|
@@ -3160,7 +3226,8 @@ var init_jobs = __esm({
|
|
|
3160
3226
|
title, description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3161
3227
|
session_type as sessionType, channel, target, delivery_mode as deliveryMode,
|
|
3162
3228
|
timezone, job_type as jobType, enabled, active, created_at as createdAt, last_run_at as lastRunAt,
|
|
3163
|
-
next_run_at as nextRunAt, consecutive_failures as consecutiveFailures
|
|
3229
|
+
next_run_at as nextRunAt, consecutive_failures as consecutiveFailures,
|
|
3230
|
+
allow_paid_slots as allowPaidSlots
|
|
3164
3231
|
FROM jobs
|
|
3165
3232
|
`;
|
|
3166
3233
|
}
|
|
@@ -3340,9 +3407,13 @@ function getGeminiSlots() {
|
|
|
3340
3407
|
FROM gemini_credentials ORDER BY priority ASC, id ASC
|
|
3341
3408
|
`).all();
|
|
3342
3409
|
}
|
|
3343
|
-
function getEligibleGeminiSlots(mode) {
|
|
3410
|
+
function getEligibleGeminiSlots(mode, allowPaid) {
|
|
3344
3411
|
if (mode === "off") return [];
|
|
3345
|
-
const
|
|
3412
|
+
const effectiveAllowPaid = mode === "keys" ? true : allowPaid ?? false;
|
|
3413
|
+
const slotTypeFilter = mode === "accounts" ? "AND slot_type = 'oauth'" : mode === "keys" ? "AND slot_type = 'api_key'" : (
|
|
3414
|
+
// "all" or undefined: exclude paid slots unless allowed
|
|
3415
|
+
!effectiveAllowPaid ? "AND slot_type != 'api_key'" : ""
|
|
3416
|
+
);
|
|
3346
3417
|
return getDb().prepare(`
|
|
3347
3418
|
SELECT id, slot_type AS slotType, label, api_key AS apiKey, config_home AS configHome,
|
|
3348
3419
|
priority, enabled, cooldown_until AS cooldownUntil, last_used AS lastUsed,
|
|
@@ -3350,7 +3421,8 @@ function getEligibleGeminiSlots(mode) {
|
|
|
3350
3421
|
FROM gemini_credentials
|
|
3351
3422
|
WHERE enabled = 1 AND (cooldown_until IS NULL OR cooldown_until <= datetime('now'))
|
|
3352
3423
|
${slotTypeFilter}
|
|
3353
|
-
ORDER BY
|
|
3424
|
+
ORDER BY CASE WHEN slot_type = 'api_key' THEN 1 ELSE 0 END ASC,
|
|
3425
|
+
priority ASC, last_used ASC NULLS FIRST
|
|
3354
3426
|
`).all();
|
|
3355
3427
|
}
|
|
3356
3428
|
function getChatGeminiSlotId(chatId) {
|
|
@@ -3443,13 +3515,20 @@ function getBackendSlots(backend2) {
|
|
|
3443
3515
|
FROM backend_credentials bc WHERE bc.backend = ? ORDER BY bc.priority ASC, bc.id ASC
|
|
3444
3516
|
`).all(backend2);
|
|
3445
3517
|
}
|
|
3446
|
-
function getEligibleBackendSlots(backend2) {
|
|
3518
|
+
function getEligibleBackendSlots(backend2, mode, allowPaid) {
|
|
3519
|
+
if (mode === "off") return [];
|
|
3520
|
+
const slotTypeFilter = mode === "accounts" ? "AND bc.slot_type = 'oauth'" : mode === "keys" ? "AND bc.slot_type = 'api_key'" : (
|
|
3521
|
+
// "all" or undefined: exclude paid slots unless allowed
|
|
3522
|
+
!allowPaid ? "AND bc.slot_type != 'api_key'" : ""
|
|
3523
|
+
);
|
|
3447
3524
|
return getDb().prepare(`
|
|
3448
3525
|
SELECT ${SLOT_COLUMNS}
|
|
3449
3526
|
FROM backend_credentials bc
|
|
3450
3527
|
WHERE bc.backend = ? AND bc.enabled = 1
|
|
3451
3528
|
AND (bc.cooldown_until IS NULL OR bc.cooldown_until <= datetime('now'))
|
|
3452
|
-
|
|
3529
|
+
${slotTypeFilter}
|
|
3530
|
+
ORDER BY CASE WHEN bc.slot_type = 'api_key' THEN 1 ELSE 0 END ASC,
|
|
3531
|
+
bc.priority ASC, bc.last_used ASC NULLS FIRST
|
|
3453
3532
|
`).all(backend2);
|
|
3454
3533
|
}
|
|
3455
3534
|
function getChatBackendSlotId(chatId, backend2) {
|
|
@@ -3520,6 +3599,13 @@ function reenableBackendSlot(slotId) {
|
|
|
3520
3599
|
WHERE id = ?
|
|
3521
3600
|
`).run(slotId);
|
|
3522
3601
|
}
|
|
3602
|
+
function getBackendRotationMode(backend2) {
|
|
3603
|
+
const row = getDb().prepare("SELECT value FROM meta WHERE key = ?").get(`${backend2}_rotation_mode`);
|
|
3604
|
+
return row?.value ?? "all";
|
|
3605
|
+
}
|
|
3606
|
+
function setBackendRotationMode(backend2, mode) {
|
|
3607
|
+
getDb().prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run(`${backend2}_rotation_mode`, mode);
|
|
3608
|
+
}
|
|
3523
3609
|
var SLOT_COLUMNS;
|
|
3524
3610
|
var init_backend_slots = __esm({
|
|
3525
3611
|
"src/memory/backend-slots.ts"() {
|
|
@@ -3546,10 +3632,12 @@ __export(store_exports5, {
|
|
|
3546
3632
|
checkBackendLimits: () => checkBackendLimits,
|
|
3547
3633
|
cleanExpiredWatches: () => cleanExpiredWatches,
|
|
3548
3634
|
clearAgentMode: () => clearAgentMode,
|
|
3635
|
+
clearAllPaidSlots: () => clearAllPaidSlots,
|
|
3549
3636
|
clearAllSessions: () => clearAllSessions,
|
|
3550
3637
|
clearBackendLimit: () => clearBackendLimit,
|
|
3551
3638
|
clearChatBackendSlot: () => clearChatBackendSlot,
|
|
3552
3639
|
clearChatGeminiSlot: () => clearChatGeminiSlot,
|
|
3640
|
+
clearChatPaidSlots: () => clearChatPaidSlots,
|
|
3553
3641
|
clearCwd: () => clearCwd,
|
|
3554
3642
|
clearExecMode: () => clearExecMode,
|
|
3555
3643
|
clearMessageLog: () => clearMessageLog,
|
|
@@ -3575,8 +3663,10 @@ __export(store_exports5, {
|
|
|
3575
3663
|
getAllMemoriesWithEmbeddings: () => getAllMemoriesWithEmbeddings,
|
|
3576
3664
|
getAllSessionSummariesWithEmbeddings: () => getAllSessionSummariesWithEmbeddings,
|
|
3577
3665
|
getAllTimeUsage: () => getAllTimeUsage,
|
|
3666
|
+
getAllowPaidSlots: () => getAllowPaidSlots,
|
|
3578
3667
|
getBackend: () => getBackend,
|
|
3579
3668
|
getBackendLimit: () => getBackendLimit,
|
|
3669
|
+
getBackendRotationMode: () => getBackendRotationMode,
|
|
3580
3670
|
getBackendSlots: () => getBackendSlots,
|
|
3581
3671
|
getBackendUsageInWindow: () => getBackendUsageInWindow,
|
|
3582
3672
|
getBookmark: () => getBookmark,
|
|
@@ -3608,6 +3698,7 @@ __export(store_exports5, {
|
|
|
3608
3698
|
getRecentMessageLog: () => getRecentMessageLog,
|
|
3609
3699
|
getResponseStyle: () => getResponseStyle,
|
|
3610
3700
|
getSessionId: () => getSessionId,
|
|
3701
|
+
getSessionLogEnabled: () => getSessionLogEnabled,
|
|
3611
3702
|
getSessionStartedAt: () => getSessionStartedAt,
|
|
3612
3703
|
getSessionSummaries: () => getSessionSummaries,
|
|
3613
3704
|
getSessionSummariesWithoutEmbeddings: () => getSessionSummariesWithoutEmbeddings,
|
|
@@ -3655,8 +3746,10 @@ __export(store_exports5, {
|
|
|
3655
3746
|
searchMessageLog: () => searchMessageLog,
|
|
3656
3747
|
searchSessionSummaries: () => searchSessionSummaries,
|
|
3657
3748
|
setAgentMode: () => setAgentMode,
|
|
3749
|
+
setAllowPaidSlots: () => setAllowPaidSlots,
|
|
3658
3750
|
setBackend: () => setBackend,
|
|
3659
3751
|
setBackendLimit: () => setBackendLimit,
|
|
3752
|
+
setBackendRotationMode: () => setBackendRotationMode,
|
|
3660
3753
|
setBackendSlotEnabled: () => setBackendSlotEnabled,
|
|
3661
3754
|
setBootTime: () => setBootTime,
|
|
3662
3755
|
setChatAlias: () => setChatAlias,
|
|
@@ -3670,6 +3763,7 @@ __export(store_exports5, {
|
|
|
3670
3763
|
setModelSignature: () => setModelSignature,
|
|
3671
3764
|
setResponseStyle: () => setResponseStyle,
|
|
3672
3765
|
setSessionId: () => setSessionId,
|
|
3766
|
+
setSessionLogEnabled: () => setSessionLogEnabled,
|
|
3673
3767
|
setSessionStartedAt: () => setSessionStartedAt,
|
|
3674
3768
|
setShowThinkingUi: () => setShowThinkingUi,
|
|
3675
3769
|
setSummarizer: () => setSummarizer,
|
|
@@ -3677,6 +3771,7 @@ __export(store_exports5, {
|
|
|
3677
3771
|
setVerboseLevel: () => setVerboseLevel,
|
|
3678
3772
|
storePendingEscalation: () => storePendingEscalation,
|
|
3679
3773
|
toFts5Query: () => toFts5Query,
|
|
3774
|
+
toggleSessionLogEnabled: () => toggleSessionLogEnabled,
|
|
3680
3775
|
toggleShowThinkingUi: () => toggleShowThinkingUi,
|
|
3681
3776
|
toggleTool: () => toggleTool,
|
|
3682
3777
|
touchBookmark: () => touchBookmark,
|
|
@@ -10359,11 +10454,11 @@ var init_evolve = __esm({
|
|
|
10359
10454
|
const body = JSON.parse(await readBody(req));
|
|
10360
10455
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
10361
10456
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
10362
|
-
const { join:
|
|
10457
|
+
const { join: join35 } = await import("path");
|
|
10363
10458
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
10364
10459
|
const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
|
|
10365
|
-
const soulPath =
|
|
10366
|
-
const userPath =
|
|
10460
|
+
const soulPath = join35(home, "identity/SOUL.md");
|
|
10461
|
+
const userPath = join35(home, "identity/USER.md");
|
|
10367
10462
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
10368
10463
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
10369
10464
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -10853,6 +10948,7 @@ var init_detect = __esm({
|
|
|
10853
10948
|
var agent_exports = {};
|
|
10854
10949
|
__export(agent_exports, {
|
|
10855
10950
|
FIRST_RESPONSE_TIMEOUT_ERROR: () => FIRST_RESPONSE_TIMEOUT_ERROR,
|
|
10951
|
+
FREE_SLOTS_EXHAUSTED: () => FREE_SLOTS_EXHAUSTED,
|
|
10856
10952
|
askAgent: () => askAgent,
|
|
10857
10953
|
getInFlightMessage: () => getInFlightMessage,
|
|
10858
10954
|
isChatBusy: () => isChatBusy,
|
|
@@ -11167,9 +11263,15 @@ Partial output: ${accumulatedText.slice(-500)}`;
|
|
|
11167
11263
|
});
|
|
11168
11264
|
});
|
|
11169
11265
|
}
|
|
11170
|
-
async function spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts, onSlotRotation) {
|
|
11171
|
-
const
|
|
11266
|
+
async function spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, allowPaid, opts, onSlotRotation) {
|
|
11267
|
+
const effectiveAllowPaid = rotationMode === "keys" ? true : allowPaid;
|
|
11268
|
+
const slots = getEligibleBackendSlots(adapter.id, rotationMode, effectiveAllowPaid);
|
|
11172
11269
|
if (slots.length === 0) {
|
|
11270
|
+
const allSlots = getBackendSlots(adapter.id).filter((s) => s.enabled);
|
|
11271
|
+
const paidSlots = allSlots.filter((s) => s.slotType === "api_key");
|
|
11272
|
+
if (!effectiveAllowPaid && paidSlots.length > 0) {
|
|
11273
|
+
throw new Error(`${FREE_SLOTS_EXHAUSTED}|${adapter.id}|${paidSlots.length}`);
|
|
11274
|
+
}
|
|
11173
11275
|
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
11174
11276
|
}
|
|
11175
11277
|
const maxAttempts = slots.length;
|
|
@@ -11201,7 +11303,7 @@ async function spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSess
|
|
|
11201
11303
|
clearSession(chatId);
|
|
11202
11304
|
} catch {
|
|
11203
11305
|
}
|
|
11204
|
-
const nextSlot = getEligibleBackendSlots(adapter.id)[0];
|
|
11306
|
+
const nextSlot = getEligibleBackendSlots(adapter.id, rotationMode, effectiveAllowPaid)[0];
|
|
11205
11307
|
if (nextSlot && onSlotRotation) {
|
|
11206
11308
|
const nextLabel = nextSlot.label || `slot-${nextSlot.id}`;
|
|
11207
11309
|
onSlotRotation(slotLabel, nextLabel);
|
|
@@ -11212,11 +11314,18 @@ async function spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSess
|
|
|
11212
11314
|
throw err;
|
|
11213
11315
|
}
|
|
11214
11316
|
}
|
|
11317
|
+
if (!effectiveAllowPaid) {
|
|
11318
|
+
const paidSlots = getBackendSlots(adapter.id).filter((s) => s.enabled && s.slotType === "api_key");
|
|
11319
|
+
if (paidSlots.length > 0) {
|
|
11320
|
+
throw new Error(`${FREE_SLOTS_EXHAUSTED}|${adapter.id}|${paidSlots.length}`);
|
|
11321
|
+
}
|
|
11322
|
+
}
|
|
11215
11323
|
throw lastError ?? new Error(`All ${adapter.id} credential slots exhausted`);
|
|
11216
11324
|
}
|
|
11217
11325
|
async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, rotationMode, opts, onSlotRotation, parentChatId, onModelDowngrade) {
|
|
11218
11326
|
const geminiAdapter = adapter;
|
|
11219
|
-
const
|
|
11327
|
+
const effectiveAllowPaid = rotationMode === "keys" ? true : getAllowPaidSlots(chatId, "gemini");
|
|
11328
|
+
const slots = getEligibleGeminiSlots(rotationMode, effectiveAllowPaid);
|
|
11220
11329
|
if (slots.length === 0) {
|
|
11221
11330
|
return spawnQuery(adapter, configWithSession, model2, cancelState, thinkingLevel, timeoutMs, maxTurns, opts);
|
|
11222
11331
|
}
|
|
@@ -11295,7 +11404,7 @@ async function spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSe
|
|
|
11295
11404
|
clearSession(chatId);
|
|
11296
11405
|
} catch {
|
|
11297
11406
|
}
|
|
11298
|
-
const nextSlot = getEligibleGeminiSlots(rotationMode)[0];
|
|
11407
|
+
const nextSlot = getEligibleGeminiSlots(rotationMode, effectiveAllowPaid)[0];
|
|
11299
11408
|
if (nextSlot && onSlotRotation) {
|
|
11300
11409
|
const nextLabel = nextSlot.label || `slot-${nextSlot.id}`;
|
|
11301
11410
|
onSlotRotation(slotLabel, nextLabel);
|
|
@@ -11380,17 +11489,19 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
11380
11489
|
};
|
|
11381
11490
|
const resolvedModel = model2 ?? adapter.defaultModel;
|
|
11382
11491
|
let result = { resultText: "", sessionId: void 0, input: 0, output: 0, cacheRead: 0, sawToolEvents: false, sawResultEvent: false };
|
|
11383
|
-
const
|
|
11384
|
-
const
|
|
11385
|
-
const
|
|
11492
|
+
const geminiRotationMode = adapter.id === "gemini" ? getGeminiRotationMode() : "off";
|
|
11493
|
+
const backendRotationMode = adapter.id !== "gemini" ? getBackendRotationMode(adapter.id) : "off";
|
|
11494
|
+
const allowPaid = getAllowPaidSlots(chatId, adapter.id);
|
|
11495
|
+
const useGeminiRotation = geminiRotationMode !== "off" && getEligibleGeminiSlots(geminiRotationMode, allowPaid).length > 0;
|
|
11496
|
+
const useBackendRotation = adapter.id !== "gemini" && (backendRotationMode !== "off" || getBackendSlots(adapter.id).filter((s) => s.enabled).length > 0);
|
|
11386
11497
|
try {
|
|
11387
11498
|
if (useGeminiRotation) {
|
|
11388
11499
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11389
11500
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
11390
|
-
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns,
|
|
11501
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, geminiRotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
11391
11502
|
} else if (useBackendRotation) {
|
|
11392
11503
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11393
|
-
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
11504
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, configWithSession, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, backendRotationMode, allowPaid, spawnOpts, rotationCb);
|
|
11394
11505
|
} else {
|
|
11395
11506
|
const slotSpawnOpts = (() => {
|
|
11396
11507
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
@@ -11441,10 +11552,10 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
11441
11552
|
if (useGeminiRotation) {
|
|
11442
11553
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11443
11554
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
11444
|
-
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns,
|
|
11555
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, geminiRotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
11445
11556
|
} else if (useBackendRotation) {
|
|
11446
11557
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11447
|
-
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
11558
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, backendRotationMode, allowPaid, spawnOpts, rotationCb);
|
|
11448
11559
|
} else {
|
|
11449
11560
|
const retryOpts = (() => {
|
|
11450
11561
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
@@ -11464,10 +11575,10 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
11464
11575
|
if (useGeminiRotation) {
|
|
11465
11576
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11466
11577
|
const downgradeCb = onModelDowngrade ? (from, to, reason) => onModelDowngrade(chatId, from, to, reason) : void 0;
|
|
11467
|
-
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns,
|
|
11578
|
+
result = await spawnGeminiWithRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, geminiRotationMode, spawnOpts, rotationCb, settingsSourceChatId, downgradeCb);
|
|
11468
11579
|
} else if (useBackendRotation) {
|
|
11469
11580
|
const rotationCb = onSlotRotation ? (from, to) => onSlotRotation(chatId, from, to) : void 0;
|
|
11470
|
-
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, spawnOpts, rotationCb);
|
|
11581
|
+
result = await spawnWithSlotRotation(chatId, adapter, baseConfig, baseConfig, resolvedModel, cancelState, thinkingLevel, timeoutMs, maxTurns, backendRotationMode, allowPaid, spawnOpts, rotationCb);
|
|
11471
11582
|
} else {
|
|
11472
11583
|
const retryOpts = (() => {
|
|
11473
11584
|
if (adapter.id !== "gemini") return spawnOpts;
|
|
@@ -11582,7 +11693,7 @@ function injectMcpConfig(adapterId, args, mcpConfigPath) {
|
|
|
11582
11693
|
if (!flag) return args;
|
|
11583
11694
|
return [...args, ...flag, mcpConfigPath];
|
|
11584
11695
|
}
|
|
11585
|
-
var activeChats, chatLocks, SPAWN_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_ERROR, GEMINI_FALLBACK_CHAIN, GEMINI_DOWNGRADE_MODELS, MCP_CONFIG_FLAG;
|
|
11696
|
+
var activeChats, chatLocks, SPAWN_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_MS, FIRST_RESPONSE_TIMEOUT_ERROR, FREE_SLOTS_EXHAUSTED, GEMINI_FALLBACK_CHAIN, GEMINI_DOWNGRADE_MODELS, MCP_CONFIG_FLAG;
|
|
11586
11697
|
var init_agent = __esm({
|
|
11587
11698
|
"src/agent.ts"() {
|
|
11588
11699
|
"use strict";
|
|
@@ -11608,6 +11719,7 @@ var init_agent = __esm({
|
|
|
11608
11719
|
SPAWN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
11609
11720
|
FIRST_RESPONSE_TIMEOUT_MS = parseInt(process.env.GEMINI_FIRST_RESPONSE_TIMEOUT_MS ?? "30000", 10);
|
|
11610
11721
|
FIRST_RESPONSE_TIMEOUT_ERROR = "FIRST_RESPONSE_TIMEOUT";
|
|
11722
|
+
FREE_SLOTS_EXHAUSTED = "FREE_SLOTS_EXHAUSTED";
|
|
11611
11723
|
GEMINI_FALLBACK_CHAIN = {
|
|
11612
11724
|
"gemini-3.1-pro-preview": "gemini-2.5-pro",
|
|
11613
11725
|
"gemini-2.5-pro": "gemini-3.1-flash-preview"
|
|
@@ -13400,18 +13512,18 @@ function formatToolStart(toolName, input, level) {
|
|
|
13400
13512
|
return `\u{1F527} ${toolName}${cmd ? `: ${cmd}` : path ? `: ${path}` : query ? `: ${query}` : ""}`;
|
|
13401
13513
|
}
|
|
13402
13514
|
}
|
|
13403
|
-
const inputStr = JSON.stringify(input, null, 2).slice(0,
|
|
13515
|
+
const inputStr = JSON.stringify(input, null, 2).slice(0, 300);
|
|
13404
13516
|
return `\u{1F527} ${toolName}:
|
|
13405
13517
|
\`\`\`json
|
|
13406
13518
|
${inputStr}
|
|
13407
13519
|
\`\`\``;
|
|
13408
13520
|
}
|
|
13409
13521
|
function formatToolResult(toolName, result) {
|
|
13410
|
-
const trimmed = result.trim().slice(0,
|
|
13522
|
+
const trimmed = result.trim().slice(0, 250);
|
|
13411
13523
|
if (!trimmed) return "";
|
|
13412
13524
|
const firstLine = trimmed.split("\n")[0] ?? "";
|
|
13413
13525
|
const isError = /error|failed|exception/i.test(firstLine);
|
|
13414
|
-
return isError ? `\u274C ${firstLine.slice(0, 120)}` : `\u{
|
|
13526
|
+
return isError ? `\u274C ${firstLine.slice(0, 120)}` : `\u{1F4EC} Result:
|
|
13415
13527
|
\`\`\`
|
|
13416
13528
|
${trimmed}
|
|
13417
13529
|
\`\`\``;
|
|
@@ -13971,6 +14083,17 @@ var init_image_gen = __esm({
|
|
|
13971
14083
|
});
|
|
13972
14084
|
|
|
13973
14085
|
// src/router/response.ts
|
|
14086
|
+
var response_exports = {};
|
|
14087
|
+
__export(response_exports, {
|
|
14088
|
+
ensureReaction: () => ensureReaction,
|
|
14089
|
+
handleResponseExhaustion: () => handleResponseExhaustion,
|
|
14090
|
+
makeToolActionCallback: () => makeToolActionCallback,
|
|
14091
|
+
pendingFallbackMessages: () => pendingFallbackMessages,
|
|
14092
|
+
processFileSends: () => processFileSends2,
|
|
14093
|
+
processImageGenerations: () => processImageGenerations,
|
|
14094
|
+
processReaction: () => processReaction,
|
|
14095
|
+
sendResponse: () => sendResponse
|
|
14096
|
+
});
|
|
13974
14097
|
import { readFile as readFile3 } from "fs/promises";
|
|
13975
14098
|
function makeToolActionCallback(chatId, channel, level) {
|
|
13976
14099
|
return async (toolName, input, result) => {
|
|
@@ -16478,13 +16601,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
16478
16601
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16479
16602
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
16480
16603
|
if (current === "frozen") {
|
|
16481
|
-
const { readFileSync:
|
|
16482
|
-
const { join:
|
|
16604
|
+
const { readFileSync: readFileSync27, existsSync: existsSync56 } = await import("fs");
|
|
16605
|
+
const { join: join35 } = await import("path");
|
|
16483
16606
|
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 =
|
|
16607
|
+
const soulPath = join35(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16608
|
+
const userPath = join35(CC_CLAW_HOME3, "identity/USER.md");
|
|
16609
|
+
const soul = existsSync56(soulPath) ? readFileSync27(soulPath, "utf-8") : "";
|
|
16610
|
+
const user = existsSync56(userPath) ? readFileSync27(userPath, "utf-8") : "";
|
|
16488
16611
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
16489
16612
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16490
16613
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -17888,6 +18011,7 @@ Tap to toggle:`,
|
|
|
17888
18011
|
const exchangeCount = getMessagePairCount(chatId);
|
|
17889
18012
|
const summarized = await summarizeSession(chatId);
|
|
17890
18013
|
clearSession(chatId);
|
|
18014
|
+
clearChatPaidSlots(chatId);
|
|
17891
18015
|
setSessionStartedAt(chatId);
|
|
17892
18016
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "New session started", detail: { field: "session", action: "reset", summarized } });
|
|
17893
18017
|
if (typeof channel.sendKeyboard === "function" && oldSessionId) {
|
|
@@ -18208,6 +18332,7 @@ Add with: <code>cc-claw ${slotBackend} add-key</code>`, { parseMode: "html" });
|
|
|
18208
18332
|
break;
|
|
18209
18333
|
}
|
|
18210
18334
|
if (typeof channel.sendKeyboard === "function") {
|
|
18335
|
+
const currentMode = getBackendRotationMode(slotBackend);
|
|
18211
18336
|
const pinnedSlotId = getChatBackendSlotId(chatId, slotBackend);
|
|
18212
18337
|
const slotButtons = slots.filter((s) => s.enabled).map((s) => {
|
|
18213
18338
|
const label2 = s.label || `slot-${s.id}`;
|
|
@@ -18220,8 +18345,15 @@ Add with: <code>cc-claw ${slotBackend} add-key</code>`, { parseMode: "html" });
|
|
|
18220
18345
|
rows.push(slotButtons.slice(i, i + 2));
|
|
18221
18346
|
}
|
|
18222
18347
|
rows.push([{ label: "\u{1F504} Auto (rotation)", data: `bslot:${slotBackend}:auto` }]);
|
|
18223
|
-
|
|
18348
|
+
const modeLabels = { off: "Off", all: "All", accounts: "\u{1F468}\u{1F3FD}\u200D\u{1F4BB} Only", keys: "\u{1F511} Only" };
|
|
18349
|
+
const modeButtons = ["off", "all", "accounts", "keys"].map((m) => ({
|
|
18350
|
+
label: `${m === currentMode ? "\u2713 " : ""}${modeLabels[m]}`,
|
|
18351
|
+
data: `brotation:${slotBackend}:${m}`
|
|
18352
|
+
}));
|
|
18353
|
+
rows.push(modeButtons);
|
|
18354
|
+
await channel.sendKeyboard(chatId, `${slotDisplayName} Accounts & Rotation:`, rows);
|
|
18224
18355
|
} else {
|
|
18356
|
+
const currentMode = getBackendRotationMode(slotBackend);
|
|
18225
18357
|
const list = slots.filter((s) => s.enabled).map((s) => {
|
|
18226
18358
|
const icon = s.slotType === "oauth" ? "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" : "\u{1F511}";
|
|
18227
18359
|
return `${icon} ${s.label || `slot-${s.id}`} (#${s.id})`;
|
|
@@ -18229,6 +18361,7 @@ Add with: <code>cc-claw ${slotBackend} add-key</code>`, { parseMode: "html" });
|
|
|
18229
18361
|
await channel.sendText(chatId, `${slotDisplayName} Slots:
|
|
18230
18362
|
${list}
|
|
18231
18363
|
|
|
18364
|
+
Rotation mode: ${currentMode}
|
|
18232
18365
|
Use: /${command} <name> to pin`, { parseMode: "plain" });
|
|
18233
18366
|
}
|
|
18234
18367
|
break;
|
|
@@ -18395,8 +18528,8 @@ ${lines.join("\n")}`, { parseMode: "plain" });
|
|
|
18395
18528
|
if (arg.startsWith("/") || arg.startsWith("~")) {
|
|
18396
18529
|
const resolvedPath = arg.startsWith("~") ? arg.replace("~", process.env.HOME ?? "") : arg;
|
|
18397
18530
|
setCwd(chatId, resolvedPath);
|
|
18398
|
-
const
|
|
18399
|
-
if (
|
|
18531
|
+
const basename4 = resolvedPath.split("/").filter(Boolean).pop();
|
|
18532
|
+
if (basename4) upsertBookmark(chatId, basename4, resolvedPath, false);
|
|
18400
18533
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Working directory set to ${resolvedPath}`, detail: { field: "cwd", value: resolvedPath } });
|
|
18401
18534
|
await sendCwdSessionChoice(chatId, resolvedPath, channel);
|
|
18402
18535
|
return;
|
|
@@ -18572,7 +18705,9 @@ Use /model to pick a model with \u26A1 thinking support.`, { parseMode: "plain"
|
|
|
18572
18705
|
chatId,
|
|
18573
18706
|
`\u{1F4AD} Thinking Level \u2014 ${shortModelName(currentModel)}
|
|
18574
18707
|
Current: ${capitalize(currentLevel)}
|
|
18575
|
-
Show thinking tokens: ${showThinkingUi ? "On" : "Off"}${adapter.id
|
|
18708
|
+
Show thinking tokens: ${showThinkingUi ? "On" : "Off"}${adapter.id !== "claude" ? `
|
|
18709
|
+
|
|
18710
|
+
\u26A0\uFE0F ${adapter.displayName} CLI doesn't stream thinking tokens` : ""}`,
|
|
18576
18711
|
buttons
|
|
18577
18712
|
);
|
|
18578
18713
|
} else {
|
|
@@ -18584,6 +18719,37 @@ Set via callback (keyboard required).`, { parseMode: "plain" });
|
|
|
18584
18719
|
}
|
|
18585
18720
|
break;
|
|
18586
18721
|
}
|
|
18722
|
+
case "debug": {
|
|
18723
|
+
const { getSessionLogEnabled: getSessionLogEnabled2, toggleSessionLogEnabled: toggleSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
18724
|
+
const current = getSessionLogEnabled2(chatId);
|
|
18725
|
+
if (commandArgs === "on" || commandArgs === "off") {
|
|
18726
|
+
const { setSessionLogEnabled: setSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
18727
|
+
const value = commandArgs === "on";
|
|
18728
|
+
setSessionLogEnabled2(chatId, value);
|
|
18729
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${value ? "ON" : "OFF"}
|
|
18730
|
+
|
|
18731
|
+
${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" });
|
|
18732
|
+
} else if (typeof channel.sendKeyboard === "function") {
|
|
18733
|
+
await channel.sendKeyboard(
|
|
18734
|
+
chatId,
|
|
18735
|
+
`\u{1F52C} Session Debug Logging
|
|
18736
|
+
|
|
18737
|
+
Records full, untruncated tool inputs and results to disk for debugging.
|
|
18738
|
+
Logs: ~/.cc-claw/logs/sessions/
|
|
18739
|
+
Retention: ${process.env.SESSION_LOG_RETENTION_DAYS ?? "7"} day(s)
|
|
18740
|
+
|
|
18741
|
+
Currently: ${current ? "ON" : "OFF"}`,
|
|
18742
|
+
[[
|
|
18743
|
+
{ label: current ? "\u2713 ON" : "ON", data: "debug_log:on", ...current ? { style: "primary" } : {} },
|
|
18744
|
+
{ label: !current ? "\u2713 OFF" : "OFF", data: "debug_log:off", ...!current ? { style: "primary" } : {} }
|
|
18745
|
+
]]
|
|
18746
|
+
);
|
|
18747
|
+
} else {
|
|
18748
|
+
const next = toggleSessionLogEnabled2(chatId);
|
|
18749
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${next ? "ON" : "OFF"}`, { parseMode: "plain" });
|
|
18750
|
+
}
|
|
18751
|
+
break;
|
|
18752
|
+
}
|
|
18587
18753
|
case "imagine":
|
|
18588
18754
|
case "image": {
|
|
18589
18755
|
if (!commandArgs) {
|
|
@@ -19494,11 +19660,19 @@ Select thinking/effort level:`,
|
|
|
19494
19660
|
backendId = getAdapterForChat(chatId).id;
|
|
19495
19661
|
} catch {
|
|
19496
19662
|
}
|
|
19497
|
-
msg = backendId
|
|
19663
|
+
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
19664
|
} else {
|
|
19499
19665
|
msg = "\u{1F4AD} Thinking tokens hidden. Toggle on again via /thinking.";
|
|
19500
19666
|
}
|
|
19501
19667
|
await channel.sendText(chatId, msg, { parseMode: "plain" });
|
|
19668
|
+
} else if (data.startsWith("debug_log:")) {
|
|
19669
|
+
const value = data.slice(10) === "on";
|
|
19670
|
+
const { setSessionLogEnabled: setSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
19671
|
+
setSessionLogEnabled2(chatId, value);
|
|
19672
|
+
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: `Session debug log ${value ? "enabled" : "disabled"}`, detail: { field: "session_log", value: String(value) } });
|
|
19673
|
+
await channel.sendText(chatId, `\u{1F52C} Session debug logging: ${value ? "ON" : "OFF"}
|
|
19674
|
+
|
|
19675
|
+
${value ? "Full tool inputs/results will be saved to ~/.cc-claw/logs/sessions/" : "Session logs disabled."}`, { parseMode: "plain" });
|
|
19502
19676
|
} else if (data.startsWith("summarizer:")) {
|
|
19503
19677
|
const rest = data.slice(11);
|
|
19504
19678
|
if (rest === "auto") {
|
|
@@ -19878,6 +20052,32 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
19878
20052
|
const modeLabels = { off: "Off", all: "All", accounts: "\u{1F468}\u{1F3FD}\u200D\u{1F4BB} Accounts only", keys: "\u{1F511} Keys only" };
|
|
19879
20053
|
await channel.sendText(chatId, `Rotation mode set to <b>${modeLabels[mode]}</b>.`, { parseMode: "html" });
|
|
19880
20054
|
return;
|
|
20055
|
+
} else if (data.startsWith("brotation:")) {
|
|
20056
|
+
const parts = data.split(":");
|
|
20057
|
+
const backend2 = parts[1];
|
|
20058
|
+
const mode = parts[2];
|
|
20059
|
+
const validModes = ["off", "all", "accounts", "keys"];
|
|
20060
|
+
if (!validModes.includes(mode)) return;
|
|
20061
|
+
const displayName = backend2.charAt(0).toUpperCase() + backend2.slice(1);
|
|
20062
|
+
const slots = getBackendSlots(backend2);
|
|
20063
|
+
if (mode === "accounts") {
|
|
20064
|
+
const oauthSlots = slots.filter((s) => s.enabled && s.slotType === "oauth");
|
|
20065
|
+
if (oauthSlots.length === 0) {
|
|
20066
|
+
await channel.sendText(chatId, `\u26A0\uFE0F No ${displayName} OAuth accounts configured. Add one with <code>cc-claw ${backend2} add-account</code> or choose a different mode.`, { parseMode: "html" });
|
|
20067
|
+
return;
|
|
20068
|
+
}
|
|
20069
|
+
} else if (mode === "keys") {
|
|
20070
|
+
const keySlots = slots.filter((s) => s.enabled && s.slotType === "api_key");
|
|
20071
|
+
if (keySlots.length === 0) {
|
|
20072
|
+
await channel.sendText(chatId, `\u26A0\uFE0F No ${displayName} API keys configured. Add one with <code>cc-claw ${backend2} add-key</code> or choose a different mode.`, { parseMode: "html" });
|
|
20073
|
+
return;
|
|
20074
|
+
}
|
|
20075
|
+
}
|
|
20076
|
+
setBackendRotationMode(backend2, mode);
|
|
20077
|
+
clearSession(chatId);
|
|
20078
|
+
const modeLabelMap = { off: "Off", all: "All", accounts: "\u{1F468}\u{1F3FD}\u200D\u{1F4BB} Accounts only", keys: "\u{1F511} Keys only" };
|
|
20079
|
+
await channel.sendText(chatId, `${displayName} rotation mode set to <b>${modeLabelMap[mode]}</b>.`, { parseMode: "html" });
|
|
20080
|
+
return;
|
|
19881
20081
|
} else if (data.startsWith("gslot:")) {
|
|
19882
20082
|
const val = data.split(":")[1];
|
|
19883
20083
|
if (val === "auto") {
|
|
@@ -19952,6 +20152,37 @@ ${rotationNote}`, { parseMode: "html" });
|
|
|
19952
20152
|
}
|
|
19953
20153
|
}
|
|
19954
20154
|
return;
|
|
20155
|
+
} else if (data.startsWith("paidslot:")) {
|
|
20156
|
+
const parts = data.split(":");
|
|
20157
|
+
const action = parts[1];
|
|
20158
|
+
const backend2 = parts[2];
|
|
20159
|
+
const displayName = backend2.charAt(0).toUpperCase() + backend2.slice(1);
|
|
20160
|
+
if (action === "approve") {
|
|
20161
|
+
setAllowPaidSlots(chatId, backend2);
|
|
20162
|
+
await channel.sendText(chatId, `\u2705 Paid API key usage approved for ${displayName} (this session). Retrying\u2026`, { parseMode: "html" });
|
|
20163
|
+
const { pendingFallbackMessages: pendingFallbackMessages3 } = await Promise.resolve().then(() => (init_response(), response_exports));
|
|
20164
|
+
const pending = pendingFallbackMessages3.get(chatId);
|
|
20165
|
+
if (pending) {
|
|
20166
|
+
pendingFallbackMessages3.delete(chatId);
|
|
20167
|
+
const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
|
|
20168
|
+
await handleMessage2(pending.msg, pending.channel);
|
|
20169
|
+
}
|
|
20170
|
+
} else if (action === "deny") {
|
|
20171
|
+
const { pendingFallbackMessages: pendingFallbackMessages3 } = await Promise.resolve().then(() => (init_response(), response_exports));
|
|
20172
|
+
pendingFallbackMessages3.delete(chatId);
|
|
20173
|
+
const otherBackends = (await Promise.resolve().then(() => (init_backends(), backends_exports))).getAvailableAdapters().filter((a) => a.id !== backend2);
|
|
20174
|
+
if (typeof channel.sendKeyboard === "function" && otherBackends.length > 0) {
|
|
20175
|
+
const buttons = otherBackends.map((a) => ({
|
|
20176
|
+
label: `\u{1F504} ${a.displayName}`,
|
|
20177
|
+
data: `backend:${a.id}`,
|
|
20178
|
+
style: "primary"
|
|
20179
|
+
}));
|
|
20180
|
+
await channel.sendKeyboard(chatId, `Switch to another backend?`, [buttons]);
|
|
20181
|
+
} else {
|
|
20182
|
+
await channel.sendText(chatId, `Paid usage denied. Try again later or switch backend manually.`, { parseMode: "plain" });
|
|
20183
|
+
}
|
|
20184
|
+
}
|
|
20185
|
+
return;
|
|
19955
20186
|
} else if (data.startsWith("shell:")) {
|
|
19956
20187
|
const parts = data.split(":");
|
|
19957
20188
|
const action = parts[1];
|
|
@@ -20417,6 +20648,206 @@ var init_callbacks = __esm({
|
|
|
20417
20648
|
}
|
|
20418
20649
|
});
|
|
20419
20650
|
|
|
20651
|
+
// src/router/session-log.ts
|
|
20652
|
+
var session_log_exports2 = {};
|
|
20653
|
+
__export(session_log_exports2, {
|
|
20654
|
+
SessionLogFile: () => SessionLogFile,
|
|
20655
|
+
cleanupSessionLogs: () => cleanupSessionLogs,
|
|
20656
|
+
getRetentionDays: () => getRetentionDays,
|
|
20657
|
+
listSessionLogs: () => listSessionLogs,
|
|
20658
|
+
startSessionLogCleanupTimer: () => startSessionLogCleanupTimer,
|
|
20659
|
+
tailSessionLog: () => tailSessionLog
|
|
20660
|
+
});
|
|
20661
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync9, appendFileSync, readdirSync as readdirSync12, unlinkSync as unlinkSync6, statSync as statSync7, createReadStream } from "fs";
|
|
20662
|
+
import { join as join24, basename as basename3 } from "path";
|
|
20663
|
+
import { createInterface as createInterface6 } from "readline";
|
|
20664
|
+
function getRetentionDays() {
|
|
20665
|
+
const env = process.env.SESSION_LOG_RETENTION_DAYS;
|
|
20666
|
+
if (env) {
|
|
20667
|
+
const n = parseInt(env, 10);
|
|
20668
|
+
if (!isNaN(n) && n > 0) return n;
|
|
20669
|
+
}
|
|
20670
|
+
return DEFAULT_RETENTION_DAYS;
|
|
20671
|
+
}
|
|
20672
|
+
function cleanupSessionLogs(retentionDays) {
|
|
20673
|
+
const days = retentionDays ?? getRetentionDays();
|
|
20674
|
+
if (!existsSync23(SESSION_LOGS_PATH)) return 0;
|
|
20675
|
+
const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
20676
|
+
let cleaned = 0;
|
|
20677
|
+
try {
|
|
20678
|
+
for (const file of readdirSync12(SESSION_LOGS_PATH)) {
|
|
20679
|
+
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
20680
|
+
const filePath = join24(SESSION_LOGS_PATH, file);
|
|
20681
|
+
try {
|
|
20682
|
+
const { mtimeMs } = statSync7(filePath);
|
|
20683
|
+
if (mtimeMs < cutoff) {
|
|
20684
|
+
unlinkSync6(filePath);
|
|
20685
|
+
cleaned++;
|
|
20686
|
+
}
|
|
20687
|
+
} catch {
|
|
20688
|
+
}
|
|
20689
|
+
}
|
|
20690
|
+
} catch (err) {
|
|
20691
|
+
log(`[session-log] Cleanup failed: ${err}`);
|
|
20692
|
+
}
|
|
20693
|
+
if (cleaned > 0) {
|
|
20694
|
+
log(`[session-log] Cleaned ${cleaned} session log(s) older than ${days} day(s)`);
|
|
20695
|
+
}
|
|
20696
|
+
return cleaned;
|
|
20697
|
+
}
|
|
20698
|
+
function startSessionLogCleanupTimer() {
|
|
20699
|
+
const timer = setInterval(() => {
|
|
20700
|
+
cleanupSessionLogs();
|
|
20701
|
+
}, 24 * 60 * 60 * 1e3);
|
|
20702
|
+
timer.unref();
|
|
20703
|
+
return timer;
|
|
20704
|
+
}
|
|
20705
|
+
function listSessionLogs() {
|
|
20706
|
+
if (!existsSync23(SESSION_LOGS_PATH)) return [];
|
|
20707
|
+
const logs = [];
|
|
20708
|
+
for (const file of readdirSync12(SESSION_LOGS_PATH)) {
|
|
20709
|
+
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
20710
|
+
const filePath = join24(SESSION_LOGS_PATH, file);
|
|
20711
|
+
try {
|
|
20712
|
+
const stat4 = statSync7(filePath);
|
|
20713
|
+
const match = file.match(/^session-(.+?)-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})\.log$/);
|
|
20714
|
+
logs.push({
|
|
20715
|
+
filename: file,
|
|
20716
|
+
filePath,
|
|
20717
|
+
chatId: match?.[1] ?? "unknown",
|
|
20718
|
+
timestamp: match?.[2]?.replace(/-/g, (m, i) => i > 9 ? ":" : m) ?? "unknown",
|
|
20719
|
+
sizeBytes: stat4.size,
|
|
20720
|
+
modifiedAt: stat4.mtime
|
|
20721
|
+
});
|
|
20722
|
+
} catch {
|
|
20723
|
+
}
|
|
20724
|
+
}
|
|
20725
|
+
logs.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());
|
|
20726
|
+
return logs;
|
|
20727
|
+
}
|
|
20728
|
+
async function* tailSessionLog(filePath, lines = 50) {
|
|
20729
|
+
if (!existsSync23(filePath)) {
|
|
20730
|
+
yield `File not found: ${filePath}`;
|
|
20731
|
+
return;
|
|
20732
|
+
}
|
|
20733
|
+
const allLines = [];
|
|
20734
|
+
const rl2 = createInterface6({
|
|
20735
|
+
input: createReadStream(filePath, { encoding: "utf-8" }),
|
|
20736
|
+
crlfDelay: Infinity
|
|
20737
|
+
});
|
|
20738
|
+
for await (const line of rl2) {
|
|
20739
|
+
allLines.push(line);
|
|
20740
|
+
}
|
|
20741
|
+
const start = Math.max(0, allLines.length - lines);
|
|
20742
|
+
for (let i = start; i < allLines.length; i++) {
|
|
20743
|
+
yield allLines[i];
|
|
20744
|
+
}
|
|
20745
|
+
}
|
|
20746
|
+
var DEFAULT_RETENTION_DAYS, SessionLogFile;
|
|
20747
|
+
var init_session_log2 = __esm({
|
|
20748
|
+
"src/router/session-log.ts"() {
|
|
20749
|
+
"use strict";
|
|
20750
|
+
init_paths();
|
|
20751
|
+
init_log();
|
|
20752
|
+
DEFAULT_RETENTION_DAYS = 7;
|
|
20753
|
+
SessionLogFile = class {
|
|
20754
|
+
constructor(chatId, backend2, model2) {
|
|
20755
|
+
this.backend = backend2;
|
|
20756
|
+
this.model = model2;
|
|
20757
|
+
if (!existsSync23(SESSION_LOGS_PATH)) {
|
|
20758
|
+
mkdirSync9(SESSION_LOGS_PATH, { recursive: true });
|
|
20759
|
+
}
|
|
20760
|
+
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
20761
|
+
const sanitizedChatId = chatId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
20762
|
+
this.filePath = join24(SESSION_LOGS_PATH, `session-${sanitizedChatId}-${ts2}.log`);
|
|
20763
|
+
const header2 = [
|
|
20764
|
+
"\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",
|
|
20765
|
+
`CC-Claw Agent Session \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
20766
|
+
`Chat: ${chatId} | Backend: ${backend2} | Model: ${model2}`,
|
|
20767
|
+
"\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",
|
|
20768
|
+
""
|
|
20769
|
+
].join("\n");
|
|
20770
|
+
appendFileSync(this.filePath, header2 + "\n", "utf-8");
|
|
20771
|
+
}
|
|
20772
|
+
filePath;
|
|
20773
|
+
startTime = Date.now();
|
|
20774
|
+
closed = false;
|
|
20775
|
+
/** Log a tool start with full, untruncated input. */
|
|
20776
|
+
logToolStart(toolName, input) {
|
|
20777
|
+
if (this.closed) return;
|
|
20778
|
+
const ts2 = this.timestamp();
|
|
20779
|
+
const inputStr = JSON.stringify(input, null, 2);
|
|
20780
|
+
const entry = `[${ts2}] TOOL_START ${toolName}
|
|
20781
|
+
${inputStr}
|
|
20782
|
+
|
|
20783
|
+
`;
|
|
20784
|
+
this.append(entry);
|
|
20785
|
+
}
|
|
20786
|
+
/** Log a tool end with full, untruncated result. */
|
|
20787
|
+
logToolEnd(toolName, result) {
|
|
20788
|
+
if (this.closed) return;
|
|
20789
|
+
const ts2 = this.timestamp();
|
|
20790
|
+
const preview = result.length > 5e3 ? `(${result.length} chars)
|
|
20791
|
+
${result.slice(0, 5e3)}\u2026[truncated]` : result;
|
|
20792
|
+
const entry = `[${ts2}] TOOL_END ${toolName}
|
|
20793
|
+
${preview}
|
|
20794
|
+
|
|
20795
|
+
`;
|
|
20796
|
+
this.append(entry);
|
|
20797
|
+
}
|
|
20798
|
+
/** Log thinking tokens with full text. */
|
|
20799
|
+
logThinking(text) {
|
|
20800
|
+
if (this.closed) return;
|
|
20801
|
+
const ts2 = this.timestamp();
|
|
20802
|
+
const entry = `[${ts2}] THINKING
|
|
20803
|
+
${text}
|
|
20804
|
+
|
|
20805
|
+
`;
|
|
20806
|
+
this.append(entry);
|
|
20807
|
+
}
|
|
20808
|
+
/** Log informational entry. */
|
|
20809
|
+
logInfo(text) {
|
|
20810
|
+
if (this.closed) return;
|
|
20811
|
+
const ts2 = this.timestamp();
|
|
20812
|
+
const entry = `[${ts2}] INFO ${text}
|
|
20813
|
+
|
|
20814
|
+
`;
|
|
20815
|
+
this.append(entry);
|
|
20816
|
+
}
|
|
20817
|
+
/** Finalize the session log with elapsed time and token counts. */
|
|
20818
|
+
finalize(elapsedMs, usage2) {
|
|
20819
|
+
if (this.closed) return;
|
|
20820
|
+
this.closed = true;
|
|
20821
|
+
const ts2 = this.timestamp();
|
|
20822
|
+
const elapsed = (elapsedMs / 1e3).toFixed(1);
|
|
20823
|
+
const usageStr = usage2 ? ` | input=${usage2.input} output=${usage2.output}${usage2.cacheRead ? ` cacheRead=${usage2.cacheRead}` : ""}` : "";
|
|
20824
|
+
const entry = `[${ts2}] FINALIZED \u2014 ${elapsed}s elapsed${usageStr}
|
|
20825
|
+
`;
|
|
20826
|
+
this.append(entry);
|
|
20827
|
+
}
|
|
20828
|
+
/** Get the file path for display/reference. */
|
|
20829
|
+
getFilePath() {
|
|
20830
|
+
return this.filePath;
|
|
20831
|
+
}
|
|
20832
|
+
/** Get just the filename (for compact display). */
|
|
20833
|
+
getFilename() {
|
|
20834
|
+
return basename3(this.filePath);
|
|
20835
|
+
}
|
|
20836
|
+
// ── Internal ──────────────────────────────────────────────────────
|
|
20837
|
+
timestamp() {
|
|
20838
|
+
return (/* @__PURE__ */ new Date()).toLocaleTimeString("en-GB", { hour12: false });
|
|
20839
|
+
}
|
|
20840
|
+
append(text) {
|
|
20841
|
+
try {
|
|
20842
|
+
appendFileSync(this.filePath, text, "utf-8");
|
|
20843
|
+
} catch (err) {
|
|
20844
|
+
log(`[session-log] Write failed: ${err}`);
|
|
20845
|
+
}
|
|
20846
|
+
}
|
|
20847
|
+
};
|
|
20848
|
+
}
|
|
20849
|
+
});
|
|
20850
|
+
|
|
20420
20851
|
// src/router/live-status.ts
|
|
20421
20852
|
var live_status_exports = {};
|
|
20422
20853
|
__export(live_status_exports, {
|
|
@@ -20439,22 +20870,20 @@ function renderEntry(e) {
|
|
|
20439
20870
|
}
|
|
20440
20871
|
return e.text;
|
|
20441
20872
|
}
|
|
20442
|
-
function renderEntries(entries, modelLabel, elapsedMs) {
|
|
20873
|
+
function renderEntries(entries, modelLabel, elapsedMs, trimmed) {
|
|
20443
20874
|
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`, ""];
|
|
20875
|
+
const lines = [`\u23F3 ${modelLabel} \xB7 ${elapsedSec}s`];
|
|
20876
|
+
if (trimmed) lines[0] += " (\u2026)";
|
|
20877
|
+
lines.push("");
|
|
20450
20878
|
for (const e of entries) lines.push(renderEntry(e));
|
|
20451
|
-
if (lines.length === 2) return `\u2705 ${modelLabel} \xB7 ${elapsedSec}s`;
|
|
20452
20879
|
return lines.join("\n");
|
|
20453
20880
|
}
|
|
20454
|
-
function
|
|
20455
|
-
const lines = [`\
|
|
20881
|
+
function renderFinal(entries, modelLabel, elapsedSec, trimmed) {
|
|
20882
|
+
const lines = [`\u2705 ${modelLabel} \xB7 ${elapsedSec}s`];
|
|
20883
|
+
if (trimmed) lines[0] += " (\u2026)";
|
|
20884
|
+
if (entries.length === 0) return lines[0];
|
|
20885
|
+
lines.push("");
|
|
20456
20886
|
for (const e of entries) lines.push(renderEntry(e));
|
|
20457
|
-
if (lines.length === 2) return `\u{1F4CE} ${modelLabel} \xB7 ${elapsedSec}s`;
|
|
20458
20887
|
return lines.join("\n");
|
|
20459
20888
|
}
|
|
20460
20889
|
function makeLiveStatus(chatId, channel, modelLabel, verboseLevel, showThinking) {
|
|
@@ -20468,16 +20897,16 @@ function makeLiveStatus(chatId, channel, modelLabel, verboseLevel, showThinking)
|
|
|
20468
20897
|
};
|
|
20469
20898
|
return { liveStatus, toolCb };
|
|
20470
20899
|
}
|
|
20471
|
-
var FLUSH_INTERVAL_MS,
|
|
20900
|
+
var FLUSH_INTERVAL_MS, MAX_THINKING_CHARS, TRIM_THRESHOLD, MAX_ENTRIES, LiveStatusMessage;
|
|
20472
20901
|
var init_live_status = __esm({
|
|
20473
20902
|
"src/router/live-status.ts"() {
|
|
20474
20903
|
"use strict";
|
|
20475
20904
|
init_log();
|
|
20476
20905
|
init_helpers();
|
|
20477
20906
|
FLUSH_INTERVAL_MS = 1e3;
|
|
20478
|
-
MAX_ENTRIES = 50;
|
|
20479
20907
|
MAX_THINKING_CHARS = 800;
|
|
20480
|
-
|
|
20908
|
+
TRIM_THRESHOLD = 3500;
|
|
20909
|
+
MAX_ENTRIES = 200;
|
|
20481
20910
|
LiveStatusMessage = class {
|
|
20482
20911
|
constructor(chatId, channel, modelLabel, verboseLevel, showThinking = false) {
|
|
20483
20912
|
this.chatId = chatId;
|
|
@@ -20492,11 +20921,10 @@ var init_live_status = __esm({
|
|
|
20492
20921
|
flushTimer = null;
|
|
20493
20922
|
lastRendered = "";
|
|
20494
20923
|
finalized = false;
|
|
20495
|
-
/**
|
|
20496
|
-
|
|
20497
|
-
|
|
20498
|
-
|
|
20499
|
-
frozenEntryCount = 0;
|
|
20924
|
+
/** Earliest time the next flush is allowed (set after 429 backoff) */
|
|
20925
|
+
nextFlushAllowedAt = 0;
|
|
20926
|
+
/** Tracks whether entries have been trimmed at least once (for display hint). */
|
|
20927
|
+
hasTrimmed = false;
|
|
20500
20928
|
/** Send the initial status message. Must be called before adding entries. */
|
|
20501
20929
|
async init() {
|
|
20502
20930
|
if (!this.channel.sendTextReturningId) return;
|
|
@@ -20555,8 +20983,8 @@ var init_live_status = __esm({
|
|
|
20555
20983
|
}
|
|
20556
20984
|
if (!this.messageId || !this.channel.editText) return;
|
|
20557
20985
|
const elapsedSec = (elapsedMs / 1e3).toFixed(1);
|
|
20558
|
-
const
|
|
20559
|
-
const body = renderFinal(
|
|
20986
|
+
const deduped = dedupThinking(this.entries);
|
|
20987
|
+
const body = renderFinal(deduped, this.modelLabel, elapsedSec, this.hasTrimmed);
|
|
20560
20988
|
try {
|
|
20561
20989
|
await this.channel.editText(this.chatId, this.messageId, body, "plain");
|
|
20562
20990
|
} catch (err) {
|
|
@@ -20570,52 +20998,47 @@ var init_live_status = __esm({
|
|
|
20570
20998
|
// ── Internal ──────────────────────────────────────────────────────────
|
|
20571
20999
|
async flush() {
|
|
20572
21000
|
if (this.finalized || !this.messageId || !this.channel.editText) return;
|
|
20573
|
-
|
|
20574
|
-
const
|
|
20575
|
-
|
|
20576
|
-
await this.spillover();
|
|
20577
|
-
return;
|
|
20578
|
-
}
|
|
21001
|
+
if (Date.now() < this.nextFlushAllowedAt) return;
|
|
21002
|
+
const deduped = dedupThinking(this.entries);
|
|
21003
|
+
const body = renderEntries(deduped, this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
20579
21004
|
if (body === this.lastRendered) return;
|
|
20580
21005
|
this.lastRendered = body;
|
|
20581
21006
|
try {
|
|
20582
21007
|
await this.channel.editText(this.chatId, this.messageId, body, "plain");
|
|
20583
21008
|
} catch (err) {
|
|
20584
|
-
|
|
21009
|
+
this.handleRateLimit(err);
|
|
20585
21010
|
}
|
|
20586
21011
|
}
|
|
20587
21012
|
/**
|
|
20588
|
-
*
|
|
20589
|
-
*
|
|
21013
|
+
* Trim entries from the BEGINNING when the rendered body exceeds the threshold.
|
|
21014
|
+
* This is the core of the single-message pattern: always show the most recent
|
|
21015
|
+
* activity, drop the oldest entries that scroll past the limit.
|
|
20590
21016
|
*/
|
|
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}`);
|
|
21017
|
+
trimEntries() {
|
|
21018
|
+
if (this.entries.length > MAX_ENTRIES) {
|
|
21019
|
+
this.entries = this.entries.slice(this.entries.length - MAX_ENTRIES);
|
|
21020
|
+
this.hasTrimmed = true;
|
|
20600
21021
|
}
|
|
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}`);
|
|
21022
|
+
let rendered = renderEntries(dedupThinking(this.entries), this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
21023
|
+
while (rendered.length > TRIM_THRESHOLD && this.entries.length > 3) {
|
|
21024
|
+
this.entries.shift();
|
|
21025
|
+
this.hasTrimmed = true;
|
|
21026
|
+
rendered = renderEntries(dedupThinking(this.entries), this.modelLabel, Date.now() - this.startTime, this.hasTrimmed);
|
|
20611
21027
|
}
|
|
20612
21028
|
}
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
|
|
21029
|
+
/**
|
|
21030
|
+
* Handle Telegram 429 rate-limit errors by backing off.
|
|
21031
|
+
* Parses the "retry after N" hint and sets a cooldown.
|
|
21032
|
+
*/
|
|
21033
|
+
handleRateLimit(err) {
|
|
21034
|
+
const msg = String(err);
|
|
21035
|
+
const match = msg.match(/retry after (\d+)/i);
|
|
21036
|
+
if (match) {
|
|
21037
|
+
const retrySec = parseInt(match[1], 10) || 3;
|
|
21038
|
+
this.nextFlushAllowedAt = Date.now() + retrySec * 1e3;
|
|
21039
|
+
log(`[live-status] 429 rate-limited, backing off ${retrySec}s`);
|
|
21040
|
+
} else {
|
|
21041
|
+
log(`[live-status] edit failed: ${msg}`);
|
|
20619
21042
|
}
|
|
20620
21043
|
}
|
|
20621
21044
|
};
|
|
@@ -20955,16 +21378,40 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
20955
21378
|
const needsLiveStatus = tVerbose !== "off" || showThinkingUi;
|
|
20956
21379
|
let liveStatus = null;
|
|
20957
21380
|
let tToolCb;
|
|
21381
|
+
const { getSessionLogEnabled: getSessionLogEnabled2 } = await Promise.resolve().then(() => (init_chat_settings(), chat_settings_exports));
|
|
21382
|
+
const { SessionLogFile: SessionLogFile2 } = await Promise.resolve().then(() => (init_session_log2(), session_log_exports2));
|
|
21383
|
+
let sessionLog = null;
|
|
21384
|
+
if (getSessionLogEnabled2(chatId)) {
|
|
21385
|
+
sessionLog = new SessionLogFile2(chatId, adapter.id, model2 ?? adapter.defaultModel);
|
|
21386
|
+
}
|
|
20958
21387
|
if (needsLiveStatus) {
|
|
20959
21388
|
const { makeLiveStatus: makeLiveStatus2 } = await Promise.resolve().then(() => (init_live_status(), live_status_exports));
|
|
20960
21389
|
const effectiveVerbose = tVerbose === "off" ? "normal" : tVerbose;
|
|
20961
21390
|
const ls = makeLiveStatus2(chatId, channel, modelLabel, effectiveVerbose, showThinkingUi);
|
|
20962
21391
|
liveStatus = ls.liveStatus;
|
|
20963
|
-
|
|
21392
|
+
const baseCb = tVerbose !== "off" ? ls.toolCb : void 0;
|
|
21393
|
+
tToolCb = async (toolName, input, result) => {
|
|
21394
|
+
if (baseCb) await baseCb(toolName, input, result);
|
|
21395
|
+
if (sessionLog) {
|
|
21396
|
+
if (result === void 0) {
|
|
21397
|
+
sessionLog.logToolStart(toolName, input);
|
|
21398
|
+
} else {
|
|
21399
|
+
sessionLog.logToolEnd(toolName, result);
|
|
21400
|
+
}
|
|
21401
|
+
}
|
|
21402
|
+
};
|
|
20964
21403
|
await liveStatus.init();
|
|
20965
|
-
if (showThinkingUi && adapter.id
|
|
20966
|
-
liveStatus.addInfo(
|
|
21404
|
+
if (showThinkingUi && adapter.id !== "claude") {
|
|
21405
|
+
liveStatus.addInfo(`\u{1F4AD} Thinking display not available for ${adapter.displayName}`);
|
|
20967
21406
|
}
|
|
21407
|
+
} else if (sessionLog) {
|
|
21408
|
+
tToolCb = async (toolName, input, result) => {
|
|
21409
|
+
if (result === void 0) {
|
|
21410
|
+
sessionLog.logToolStart(toolName, input);
|
|
21411
|
+
} else {
|
|
21412
|
+
sessionLog.logToolEnd(toolName, result);
|
|
21413
|
+
}
|
|
21414
|
+
};
|
|
20968
21415
|
}
|
|
20969
21416
|
const sigT0 = Date.now();
|
|
20970
21417
|
const response = await askAgent(chatId, cleanText || text, {
|
|
@@ -20975,7 +21422,10 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
20975
21422
|
bootstrapTier,
|
|
20976
21423
|
maxTurns,
|
|
20977
21424
|
agentMode: effectiveAgentMode,
|
|
20978
|
-
onThinking: liveStatus ? (chunk) =>
|
|
21425
|
+
onThinking: liveStatus || sessionLog ? (chunk) => {
|
|
21426
|
+
if (liveStatus) liveStatus.addThinking(chunk);
|
|
21427
|
+
if (sessionLog) sessionLog.logThinking(chunk);
|
|
21428
|
+
} : void 0,
|
|
20979
21429
|
onSubagentActivity: (backendId2, info) => {
|
|
20980
21430
|
observedSubagents.add(info.name);
|
|
20981
21431
|
try {
|
|
@@ -21015,6 +21465,7 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
21015
21465
|
liveStatus.addThinking(response.thinkingText.trim());
|
|
21016
21466
|
}
|
|
21017
21467
|
if (liveStatus) await liveStatus.finalize(elapsedMs);
|
|
21468
|
+
if (sessionLog) sessionLog.finalize(elapsedMs, response.usage);
|
|
21018
21469
|
if (response.usage) addUsage(chatId, response.usage.input, response.usage.output, response.usage.cacheRead, model2, void 0, response.usage.contextSize);
|
|
21019
21470
|
let responseText = response.text;
|
|
21020
21471
|
const sigEnabled = getModelSignature(chatId);
|
|
@@ -21105,6 +21556,33 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
21105
21556
|
}
|
|
21106
21557
|
return;
|
|
21107
21558
|
}
|
|
21559
|
+
if (errMsg.startsWith(FREE_SLOTS_EXHAUSTED)) {
|
|
21560
|
+
const parts = errMsg.split("|");
|
|
21561
|
+
const backend2 = parts[1] ?? "unknown";
|
|
21562
|
+
const paidCount = parts[2] ?? "?";
|
|
21563
|
+
const displayName = backend2.charAt(0).toUpperCase() + backend2.slice(1);
|
|
21564
|
+
const { pendingFallbackMessages: pendingFallbackMessages3 } = await Promise.resolve().then(() => (init_response(), response_exports));
|
|
21565
|
+
pendingFallbackMessages3.set(chatId, { msg, channel, agentMode: effectiveAgentMode });
|
|
21566
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
21567
|
+
await channel.sendKeyboard(
|
|
21568
|
+
chatId,
|
|
21569
|
+
`\u26A0\uFE0F All free ${displayName} accounts are exhausted.
|
|
21570
|
+
|
|
21571
|
+
${paidCount} paid API key slot(s) available. Using them will incur API costs.
|
|
21572
|
+
|
|
21573
|
+
Approve paid usage for this session?`,
|
|
21574
|
+
[
|
|
21575
|
+
[
|
|
21576
|
+
{ label: "\u2705 Approve (this session)", data: `paidslot:approve:${backend2}`, style: "success" },
|
|
21577
|
+
{ label: "\u274C No, switch backend", data: `paidslot:deny:${backend2}`, style: "danger" }
|
|
21578
|
+
]
|
|
21579
|
+
]
|
|
21580
|
+
);
|
|
21581
|
+
} else {
|
|
21582
|
+
await channel.sendText(chatId, `\u26A0\uFE0F All free ${displayName} accounts exhausted. ${paidCount} paid API key slot(s) available but not approved. Switch backend or approve paid usage.`, { parseMode: "plain" });
|
|
21583
|
+
}
|
|
21584
|
+
return;
|
|
21585
|
+
}
|
|
21108
21586
|
const errorClass = classifyError(err);
|
|
21109
21587
|
if (errorClass === "exhausted") {
|
|
21110
21588
|
if (await handleResponseExhaustion(errMsg, chatId, msg, channel)) return;
|
|
@@ -21448,6 +21926,10 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
21448
21926
|
onToolAction = makeToolActionCallback2(chatId, channel, vLevel);
|
|
21449
21927
|
}
|
|
21450
21928
|
}
|
|
21929
|
+
if (job.allowPaidSlots) {
|
|
21930
|
+
const cronBackend = currentBackend;
|
|
21931
|
+
setAllowPaidSlots(chatId, cronBackend);
|
|
21932
|
+
}
|
|
21451
21933
|
const response = await askAgent(chatId, job.description, {
|
|
21452
21934
|
model: currentModel,
|
|
21453
21935
|
backend: currentBackend,
|
|
@@ -21456,6 +21938,9 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
21456
21938
|
permMode: job.sessionType === "main" ? getMode(job.chatId) : "yolo",
|
|
21457
21939
|
onToolAction
|
|
21458
21940
|
});
|
|
21941
|
+
if (job.allowPaidSlots) {
|
|
21942
|
+
clearChatPaidSlots(chatId);
|
|
21943
|
+
}
|
|
21459
21944
|
if (isFallback) {
|
|
21460
21945
|
response.text = `[Fallback: ran on ${currentBackend}:${currentModel}]
|
|
21461
21946
|
|
|
@@ -21465,8 +21950,13 @@ ${response.text}`;
|
|
|
21465
21950
|
} catch (err) {
|
|
21466
21951
|
lastError = err;
|
|
21467
21952
|
const errorClass = classifyError(err);
|
|
21953
|
+
const errMsg = errorMessage(err);
|
|
21954
|
+
if (typeof errMsg === "string" && errMsg.startsWith(FREE_SLOTS_EXHAUSTED)) {
|
|
21955
|
+
log(`[scheduler] Job #${job.id} backend ${currentBackend} free slots exhausted (paid not approved): ${errMsg}`);
|
|
21956
|
+
break;
|
|
21957
|
+
}
|
|
21468
21958
|
if (errorClass === "exhausted") {
|
|
21469
|
-
log(`[scheduler] Job #${job.id} backend ${currentBackend} exhausted: ${
|
|
21959
|
+
log(`[scheduler] Job #${job.id} backend ${currentBackend} exhausted: ${errMsg}`);
|
|
21470
21960
|
break;
|
|
21471
21961
|
}
|
|
21472
21962
|
if (errorClass === "permanent" || attempt >= MAX_RETRIES) {
|
|
@@ -21523,7 +22013,7 @@ var init_cron = __esm({
|
|
|
21523
22013
|
});
|
|
21524
22014
|
|
|
21525
22015
|
// src/agents/runners/wrap-backend.ts
|
|
21526
|
-
import { join as
|
|
22016
|
+
import { join as join25 } from "path";
|
|
21527
22017
|
function buildMcpCommands(backendId) {
|
|
21528
22018
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
21529
22019
|
return {
|
|
@@ -21617,7 +22107,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
21617
22107
|
const configPath = writeMcpConfigFile(server);
|
|
21618
22108
|
return ["--mcp-config", configPath];
|
|
21619
22109
|
},
|
|
21620
|
-
getSkillPath: () =>
|
|
22110
|
+
getSkillPath: () => join25(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
21621
22111
|
};
|
|
21622
22112
|
}
|
|
21623
22113
|
var BACKEND_CAPABILITIES;
|
|
@@ -21668,18 +22158,18 @@ var init_wrap_backend = __esm({
|
|
|
21668
22158
|
});
|
|
21669
22159
|
|
|
21670
22160
|
// src/agents/runners/config-loader.ts
|
|
21671
|
-
import { readFileSync as readFileSync14, readdirSync as
|
|
21672
|
-
import { join as
|
|
22161
|
+
import { readFileSync as readFileSync14, readdirSync as readdirSync13, existsSync as existsSync24, mkdirSync as mkdirSync10, watchFile, unwatchFile } from "fs";
|
|
22162
|
+
import { join as join26 } from "path";
|
|
21673
22163
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
21674
22164
|
function resolveExecutable(config2) {
|
|
21675
|
-
if (
|
|
22165
|
+
if (existsSync24(config2.executable)) return config2.executable;
|
|
21676
22166
|
try {
|
|
21677
22167
|
return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
21678
22168
|
} catch {
|
|
21679
22169
|
}
|
|
21680
22170
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
21681
22171
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
21682
|
-
if (
|
|
22172
|
+
if (existsSync24(resolved)) return resolved;
|
|
21683
22173
|
}
|
|
21684
22174
|
return config2.executable;
|
|
21685
22175
|
}
|
|
@@ -21805,7 +22295,7 @@ function configToRunner(config2) {
|
|
|
21805
22295
|
prepareMcpInjection() {
|
|
21806
22296
|
return [];
|
|
21807
22297
|
},
|
|
21808
|
-
getSkillPath: () =>
|
|
22298
|
+
getSkillPath: () => join26(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
21809
22299
|
};
|
|
21810
22300
|
}
|
|
21811
22301
|
function loadRunnerConfig(filePath) {
|
|
@@ -21818,14 +22308,14 @@ function loadRunnerConfig(filePath) {
|
|
|
21818
22308
|
}
|
|
21819
22309
|
}
|
|
21820
22310
|
function loadAllRunnerConfigs() {
|
|
21821
|
-
if (!
|
|
21822
|
-
|
|
22311
|
+
if (!existsSync24(RUNNERS_PATH)) {
|
|
22312
|
+
mkdirSync10(RUNNERS_PATH, { recursive: true });
|
|
21823
22313
|
return [];
|
|
21824
22314
|
}
|
|
21825
|
-
const files =
|
|
22315
|
+
const files = readdirSync13(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
21826
22316
|
const configs = [];
|
|
21827
22317
|
for (const file of files) {
|
|
21828
|
-
const config2 = loadRunnerConfig(
|
|
22318
|
+
const config2 = loadRunnerConfig(join26(RUNNERS_PATH, file));
|
|
21829
22319
|
if (config2) configs.push(config2);
|
|
21830
22320
|
}
|
|
21831
22321
|
return configs;
|
|
@@ -21846,16 +22336,16 @@ function registerConfigRunners() {
|
|
|
21846
22336
|
return count;
|
|
21847
22337
|
}
|
|
21848
22338
|
function watchRunnerConfigs(onChange) {
|
|
21849
|
-
if (!
|
|
22339
|
+
if (!existsSync24(RUNNERS_PATH)) return;
|
|
21850
22340
|
for (const prev of watchedFiles) {
|
|
21851
|
-
if (!
|
|
22341
|
+
if (!existsSync24(prev)) {
|
|
21852
22342
|
unwatchFile(prev);
|
|
21853
22343
|
watchedFiles.delete(prev);
|
|
21854
22344
|
}
|
|
21855
22345
|
}
|
|
21856
|
-
const files =
|
|
22346
|
+
const files = readdirSync13(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
21857
22347
|
for (const file of files) {
|
|
21858
|
-
const fullPath =
|
|
22348
|
+
const fullPath = join26(RUNNERS_PATH, file);
|
|
21859
22349
|
if (watchedFiles.has(fullPath)) continue;
|
|
21860
22350
|
watchedFiles.add(fullPath);
|
|
21861
22351
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -22256,6 +22746,7 @@ var init_telegram2 = __esm({
|
|
|
22256
22746
|
{ command: "mode", description: "Execution gate (approved/yolo)" },
|
|
22257
22747
|
{ command: "tools", description: "Configure which tools the agent can use" },
|
|
22258
22748
|
{ command: "verbose", description: "Tool visibility (off/normal/verbose)" },
|
|
22749
|
+
{ command: "debug", description: "Toggle session debug logging (full tool I/O)" },
|
|
22259
22750
|
{ command: "cwd", description: "Set or show working directory" },
|
|
22260
22751
|
// Memory
|
|
22261
22752
|
{ command: "memory", description: "List stored memories" },
|
|
@@ -22702,19 +23193,19 @@ var init_telegram2 = __esm({
|
|
|
22702
23193
|
});
|
|
22703
23194
|
|
|
22704
23195
|
// src/skills/bootstrap.ts
|
|
22705
|
-
import { existsSync as
|
|
23196
|
+
import { existsSync as existsSync25 } from "fs";
|
|
22706
23197
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
22707
|
-
import { join as
|
|
23198
|
+
import { join as join27, dirname as dirname5 } from "path";
|
|
22708
23199
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
22709
23200
|
async function copyAgentManifestSkills() {
|
|
22710
|
-
if (!
|
|
23201
|
+
if (!existsSync25(PKG_SKILLS)) return;
|
|
22711
23202
|
try {
|
|
22712
23203
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
22713
23204
|
for (const entry of entries) {
|
|
22714
23205
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
22715
|
-
const src =
|
|
22716
|
-
const dest =
|
|
22717
|
-
if (
|
|
23206
|
+
const src = join27(PKG_SKILLS, entry.name);
|
|
23207
|
+
const dest = join27(SKILLS_PATH, entry.name);
|
|
23208
|
+
if (existsSync25(dest)) continue;
|
|
22718
23209
|
await copyFile(src, dest);
|
|
22719
23210
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
22720
23211
|
}
|
|
@@ -22724,8 +23215,8 @@ async function copyAgentManifestSkills() {
|
|
|
22724
23215
|
}
|
|
22725
23216
|
async function bootstrapSkills() {
|
|
22726
23217
|
await copyAgentManifestSkills();
|
|
22727
|
-
const usmDir =
|
|
22728
|
-
if (
|
|
23218
|
+
const usmDir = join27(SKILLS_PATH, USM_DIR_NAME);
|
|
23219
|
+
if (existsSync25(usmDir)) return;
|
|
22729
23220
|
try {
|
|
22730
23221
|
const entries = await readdir6(SKILLS_PATH);
|
|
22731
23222
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -22747,8 +23238,8 @@ async function bootstrapSkills() {
|
|
|
22747
23238
|
}
|
|
22748
23239
|
}
|
|
22749
23240
|
async function patchUsmForCcClaw(usmDir) {
|
|
22750
|
-
const skillPath =
|
|
22751
|
-
if (!
|
|
23241
|
+
const skillPath = join27(usmDir, "SKILL.md");
|
|
23242
|
+
if (!existsSync25(skillPath)) return;
|
|
22752
23243
|
try {
|
|
22753
23244
|
let content = await readFile8(skillPath, "utf-8");
|
|
22754
23245
|
let patched = false;
|
|
@@ -22793,8 +23284,8 @@ var init_bootstrap = __esm({
|
|
|
22793
23284
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
22794
23285
|
USM_DIR_NAME = "universal-skills-manager";
|
|
22795
23286
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
22796
|
-
PKG_ROOT =
|
|
22797
|
-
PKG_SKILLS =
|
|
23287
|
+
PKG_ROOT = join27(dirname5(fileURLToPath2(import.meta.url)), "..", "..");
|
|
23288
|
+
PKG_SKILLS = join27(PKG_ROOT, "skills");
|
|
22798
23289
|
}
|
|
22799
23290
|
});
|
|
22800
23291
|
|
|
@@ -23016,13 +23507,13 @@ __export(ai_skill_exports, {
|
|
|
23016
23507
|
generateAiSkill: () => generateAiSkill,
|
|
23017
23508
|
installAiSkill: () => installAiSkill
|
|
23018
23509
|
});
|
|
23019
|
-
import { existsSync as
|
|
23020
|
-
import { join as
|
|
23510
|
+
import { existsSync as existsSync26, writeFileSync as writeFileSync8, mkdirSync as mkdirSync11 } from "fs";
|
|
23511
|
+
import { join as join28 } from "path";
|
|
23021
23512
|
import { homedir as homedir9 } from "os";
|
|
23022
23513
|
function generateAiSkill() {
|
|
23023
23514
|
const version = VERSION;
|
|
23024
23515
|
let systemState = "";
|
|
23025
|
-
if (
|
|
23516
|
+
if (existsSync26(DB_PATH)) {
|
|
23026
23517
|
try {
|
|
23027
23518
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
23028
23519
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -23110,6 +23601,7 @@ Use the CC-Claw CLI when you need to:
|
|
|
23110
23601
|
- \`/model_signature\` \u2014 Show/hide model name on responses
|
|
23111
23602
|
- \`/agents mode\` \u2014 Agent mode (auto/native/claw)
|
|
23112
23603
|
- \`/voice_config\` \u2014 Voice provider settings
|
|
23604
|
+
- \`/debug\` \u2014 Toggle per-chat session debug logging (full tool I/O to disk)
|
|
23113
23605
|
|
|
23114
23606
|
**Memory:**
|
|
23115
23607
|
- \`/remember <text>\` \u2014 Save a memory
|
|
@@ -23152,6 +23644,16 @@ cc-claw logs --error # Show error log
|
|
|
23152
23644
|
cc-claw logs --lines 50 # Show last N lines
|
|
23153
23645
|
\`\`\`
|
|
23154
23646
|
|
|
23647
|
+
### Session Debug Logs
|
|
23648
|
+
\`\`\`bash
|
|
23649
|
+
cc-claw session-logs list # List all session debug logs
|
|
23650
|
+
cc-claw session-logs tail # Tail latest session log
|
|
23651
|
+
cc-claw session-logs tail -f # Follow latest log (like tail -f)
|
|
23652
|
+
cc-claw session-logs tail --file <name> # Tail a specific log file
|
|
23653
|
+
cc-claw session-logs clean # Remove old session logs
|
|
23654
|
+
cc-claw session-logs clean --days 3 # Remove logs older than 3 days
|
|
23655
|
+
\`\`\`
|
|
23656
|
+
|
|
23155
23657
|
### Backend & Model
|
|
23156
23658
|
\`\`\`bash
|
|
23157
23659
|
cc-claw backend list --json # Available backends
|
|
@@ -23426,10 +23928,10 @@ function installAiSkill() {
|
|
|
23426
23928
|
const failed = [];
|
|
23427
23929
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
23428
23930
|
for (const dir of dirs) {
|
|
23429
|
-
const skillDir =
|
|
23430
|
-
const skillPath =
|
|
23931
|
+
const skillDir = join28(dir, "cc-claw-cli");
|
|
23932
|
+
const skillPath = join28(skillDir, "SKILL.md");
|
|
23431
23933
|
try {
|
|
23432
|
-
|
|
23934
|
+
mkdirSync11(skillDir, { recursive: true });
|
|
23433
23935
|
writeFileSync8(skillPath, skill, "utf-8");
|
|
23434
23936
|
installed.push(skillPath);
|
|
23435
23937
|
} catch {
|
|
@@ -23446,11 +23948,11 @@ var init_ai_skill = __esm({
|
|
|
23446
23948
|
init_paths();
|
|
23447
23949
|
init_version();
|
|
23448
23950
|
BACKEND_SKILL_DIRS2 = {
|
|
23449
|
-
"cc-claw": [
|
|
23450
|
-
claude: [
|
|
23451
|
-
gemini: [
|
|
23452
|
-
codex: [
|
|
23453
|
-
cursor: [
|
|
23951
|
+
"cc-claw": [join28(homedir9(), ".cc-claw", "workspace", "skills")],
|
|
23952
|
+
claude: [join28(homedir9(), ".claude", "skills")],
|
|
23953
|
+
gemini: [join28(homedir9(), ".gemini", "skills")],
|
|
23954
|
+
codex: [join28(homedir9(), ".agents", "skills")],
|
|
23955
|
+
cursor: [join28(homedir9(), ".cursor", "skills"), join28(homedir9(), ".cursor", "skills-cursor")]
|
|
23454
23956
|
};
|
|
23455
23957
|
}
|
|
23456
23958
|
});
|
|
@@ -23460,21 +23962,21 @@ var index_exports = {};
|
|
|
23460
23962
|
__export(index_exports, {
|
|
23461
23963
|
main: () => main
|
|
23462
23964
|
});
|
|
23463
|
-
import { mkdirSync as
|
|
23464
|
-
import { join as
|
|
23965
|
+
import { mkdirSync as mkdirSync12, existsSync as existsSync27, renameSync as renameSync2, statSync as statSync8, readFileSync as readFileSync16 } from "fs";
|
|
23966
|
+
import { join as join29 } from "path";
|
|
23465
23967
|
import dotenv from "dotenv";
|
|
23466
23968
|
function migrateLayout() {
|
|
23467
23969
|
const moves = [
|
|
23468
|
-
[
|
|
23469
|
-
[
|
|
23470
|
-
[
|
|
23471
|
-
[
|
|
23472
|
-
[
|
|
23473
|
-
[
|
|
23474
|
-
[
|
|
23970
|
+
[join29(CC_CLAW_HOME, "cc-claw.db"), join29(DATA_PATH, "cc-claw.db")],
|
|
23971
|
+
[join29(CC_CLAW_HOME, "cc-claw.db-shm"), join29(DATA_PATH, "cc-claw.db-shm")],
|
|
23972
|
+
[join29(CC_CLAW_HOME, "cc-claw.db-wal"), join29(DATA_PATH, "cc-claw.db-wal")],
|
|
23973
|
+
[join29(CC_CLAW_HOME, "cc-claw.log"), join29(LOGS_PATH, "cc-claw.log")],
|
|
23974
|
+
[join29(CC_CLAW_HOME, "cc-claw.log.1"), join29(LOGS_PATH, "cc-claw.log.1")],
|
|
23975
|
+
[join29(CC_CLAW_HOME, "cc-claw.error.log"), join29(LOGS_PATH, "cc-claw.error.log")],
|
|
23976
|
+
[join29(CC_CLAW_HOME, "cc-claw.error.log.1"), join29(LOGS_PATH, "cc-claw.error.log.1")]
|
|
23475
23977
|
];
|
|
23476
23978
|
for (const [from, to] of moves) {
|
|
23477
|
-
if (
|
|
23979
|
+
if (existsSync27(from) && !existsSync27(to)) {
|
|
23478
23980
|
try {
|
|
23479
23981
|
renameSync2(from, to);
|
|
23480
23982
|
} catch {
|
|
@@ -23485,7 +23987,7 @@ function migrateLayout() {
|
|
|
23485
23987
|
function rotateLogs() {
|
|
23486
23988
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
23487
23989
|
try {
|
|
23488
|
-
const { size } =
|
|
23990
|
+
const { size } = statSync8(file);
|
|
23489
23991
|
if (size > LOG_MAX_BYTES) {
|
|
23490
23992
|
const archivePath = `${file}.1`;
|
|
23491
23993
|
try {
|
|
@@ -23508,6 +24010,7 @@ async function main() {
|
|
|
23508
24010
|
}
|
|
23509
24011
|
log(`[cc-claw] Starting v${version}`);
|
|
23510
24012
|
initDatabase();
|
|
24013
|
+
clearAllPaidSlots();
|
|
23511
24014
|
pruneMessageLog(30, 2e3);
|
|
23512
24015
|
bootstrapBuiltinMcps(getDb());
|
|
23513
24016
|
try {
|
|
@@ -23619,11 +24122,11 @@ async function main() {
|
|
|
23619
24122
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
23620
24123
|
try {
|
|
23621
24124
|
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(
|
|
24125
|
+
const { writeFileSync: writeFileSync13, mkdirSync: mkdirSync19 } = await import("fs");
|
|
24126
|
+
const { join: join35 } = await import("path");
|
|
24127
|
+
const skillDir = join35(SKILLS_PATH, "cc-claw-cli");
|
|
24128
|
+
mkdirSync19(skillDir, { recursive: true });
|
|
24129
|
+
writeFileSync13(join35(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
23627
24130
|
log("[cc-claw] AI skill updated");
|
|
23628
24131
|
} catch {
|
|
23629
24132
|
}
|
|
@@ -23643,6 +24146,12 @@ async function main() {
|
|
|
23643
24146
|
cleanupOldMedia().catch(() => {
|
|
23644
24147
|
});
|
|
23645
24148
|
pruneImageCache();
|
|
24149
|
+
try {
|
|
24150
|
+
const { cleanupSessionLogs: cleanupSessionLogs2, startSessionLogCleanupTimer: startSessionLogCleanupTimer2 } = await Promise.resolve().then(() => (init_session_log2(), session_log_exports2));
|
|
24151
|
+
cleanupSessionLogs2();
|
|
24152
|
+
startSessionLogCleanupTimer2();
|
|
24153
|
+
} catch {
|
|
24154
|
+
}
|
|
23646
24155
|
log("[cc-claw] Ready!");
|
|
23647
24156
|
const shutdown = async (signal) => {
|
|
23648
24157
|
log(`[cc-claw] Received ${signal}, shutting down...`);
|
|
@@ -23695,11 +24204,11 @@ var init_index = __esm({
|
|
|
23695
24204
|
init_bootstrap2();
|
|
23696
24205
|
init_health3();
|
|
23697
24206
|
init_image_gen();
|
|
23698
|
-
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
23699
|
-
if (!
|
|
24207
|
+
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SESSION_LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
24208
|
+
if (!existsSync27(dir)) mkdirSync12(dir, { recursive: true });
|
|
23700
24209
|
}
|
|
23701
24210
|
migrateLayout();
|
|
23702
|
-
if (
|
|
24211
|
+
if (existsSync27(ENV_PATH)) {
|
|
23703
24212
|
dotenv.config({ path: ENV_PATH });
|
|
23704
24213
|
} else {
|
|
23705
24214
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -23720,12 +24229,12 @@ __export(api_client_exports, {
|
|
|
23720
24229
|
apiPost: () => apiPost,
|
|
23721
24230
|
isDaemonRunning: () => isDaemonRunning
|
|
23722
24231
|
});
|
|
23723
|
-
import { readFileSync as readFileSync17, existsSync as
|
|
24232
|
+
import { readFileSync as readFileSync17, existsSync as existsSync28 } from "fs";
|
|
23724
24233
|
import { request as httpRequest, Agent } from "http";
|
|
23725
24234
|
function getToken() {
|
|
23726
24235
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
23727
24236
|
try {
|
|
23728
|
-
if (
|
|
24237
|
+
if (existsSync28(TOKEN_PATH)) return readFileSync17(TOKEN_PATH, "utf-8").trim();
|
|
23729
24238
|
} catch {
|
|
23730
24239
|
}
|
|
23731
24240
|
return null;
|
|
@@ -23824,10 +24333,10 @@ __export(service_exports, {
|
|
|
23824
24333
|
serviceStatus: () => serviceStatus,
|
|
23825
24334
|
uninstallService: () => uninstallService
|
|
23826
24335
|
});
|
|
23827
|
-
import { existsSync as
|
|
24336
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, unlinkSync as unlinkSync7 } from "fs";
|
|
23828
24337
|
import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
|
|
23829
24338
|
import { homedir as homedir10, platform } from "os";
|
|
23830
|
-
import { join as
|
|
24339
|
+
import { join as join30, dirname as dirname6 } from "path";
|
|
23831
24340
|
function xmlEscape(s) {
|
|
23832
24341
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
23833
24342
|
}
|
|
@@ -23836,7 +24345,7 @@ function resolveExecutable2(name) {
|
|
|
23836
24345
|
return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
|
|
23837
24346
|
} catch {
|
|
23838
24347
|
const fallback = process.argv[1];
|
|
23839
|
-
if (fallback &&
|
|
24348
|
+
if (fallback && existsSync29(fallback)) return fallback;
|
|
23840
24349
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
23841
24350
|
}
|
|
23842
24351
|
}
|
|
@@ -23845,14 +24354,14 @@ function getPathDirs() {
|
|
|
23845
24354
|
const home = homedir10();
|
|
23846
24355
|
const dirs = /* @__PURE__ */ new Set([
|
|
23847
24356
|
nodeBin,
|
|
23848
|
-
|
|
24357
|
+
join30(home, ".local", "bin"),
|
|
23849
24358
|
"/usr/local/bin",
|
|
23850
24359
|
"/usr/bin",
|
|
23851
24360
|
"/bin"
|
|
23852
24361
|
]);
|
|
23853
24362
|
try {
|
|
23854
24363
|
const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
23855
|
-
if (prefix) dirs.add(
|
|
24364
|
+
if (prefix) dirs.add(join30(prefix, "bin"));
|
|
23856
24365
|
} catch {
|
|
23857
24366
|
}
|
|
23858
24367
|
return [...dirs].join(":");
|
|
@@ -23911,9 +24420,9 @@ function generatePlist() {
|
|
|
23911
24420
|
}
|
|
23912
24421
|
function installMacOS() {
|
|
23913
24422
|
const agentsDir = dirname6(PLIST_PATH);
|
|
23914
|
-
if (!
|
|
23915
|
-
if (!
|
|
23916
|
-
if (
|
|
24423
|
+
if (!existsSync29(agentsDir)) mkdirSync13(agentsDir, { recursive: true });
|
|
24424
|
+
if (!existsSync29(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
24425
|
+
if (existsSync29(PLIST_PATH)) {
|
|
23917
24426
|
try {
|
|
23918
24427
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
23919
24428
|
} catch {
|
|
@@ -23925,7 +24434,7 @@ function installMacOS() {
|
|
|
23925
24434
|
console.log(" Service loaded and starting.");
|
|
23926
24435
|
}
|
|
23927
24436
|
function uninstallMacOS() {
|
|
23928
|
-
if (!
|
|
24437
|
+
if (!existsSync29(PLIST_PATH)) {
|
|
23929
24438
|
console.log(" No service found to uninstall.");
|
|
23930
24439
|
return;
|
|
23931
24440
|
}
|
|
@@ -23933,7 +24442,7 @@ function uninstallMacOS() {
|
|
|
23933
24442
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
23934
24443
|
} catch {
|
|
23935
24444
|
}
|
|
23936
|
-
|
|
24445
|
+
unlinkSync7(PLIST_PATH);
|
|
23937
24446
|
console.log(" Service uninstalled.");
|
|
23938
24447
|
}
|
|
23939
24448
|
function formatUptime(seconds) {
|
|
@@ -24000,8 +24509,8 @@ WantedBy=default.target
|
|
|
24000
24509
|
`;
|
|
24001
24510
|
}
|
|
24002
24511
|
function installLinux() {
|
|
24003
|
-
if (!
|
|
24004
|
-
if (!
|
|
24512
|
+
if (!existsSync29(SYSTEMD_DIR)) mkdirSync13(SYSTEMD_DIR, { recursive: true });
|
|
24513
|
+
if (!existsSync29(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
24005
24514
|
writeFileSync9(UNIT_PATH, generateUnit());
|
|
24006
24515
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
24007
24516
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -24010,7 +24519,7 @@ function installLinux() {
|
|
|
24010
24519
|
console.log(" Service enabled and started.");
|
|
24011
24520
|
}
|
|
24012
24521
|
function uninstallLinux() {
|
|
24013
|
-
if (!
|
|
24522
|
+
if (!existsSync29(UNIT_PATH)) {
|
|
24014
24523
|
console.log(" No service found to uninstall.");
|
|
24015
24524
|
return;
|
|
24016
24525
|
}
|
|
@@ -24022,7 +24531,7 @@ function uninstallLinux() {
|
|
|
24022
24531
|
execFileSync3("systemctl", ["--user", "disable", "cc-claw"]);
|
|
24023
24532
|
} catch {
|
|
24024
24533
|
}
|
|
24025
|
-
|
|
24534
|
+
unlinkSync7(UNIT_PATH);
|
|
24026
24535
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
24027
24536
|
console.log(" Service uninstalled.");
|
|
24028
24537
|
}
|
|
@@ -24035,7 +24544,7 @@ function statusLinux() {
|
|
|
24035
24544
|
}
|
|
24036
24545
|
}
|
|
24037
24546
|
function installService() {
|
|
24038
|
-
if (!
|
|
24547
|
+
if (!existsSync29(join30(CC_CLAW_HOME, ".env"))) {
|
|
24039
24548
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
24040
24549
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
24041
24550
|
process.exitCode = 1;
|
|
@@ -24064,9 +24573,9 @@ var init_service = __esm({
|
|
|
24064
24573
|
"use strict";
|
|
24065
24574
|
init_paths();
|
|
24066
24575
|
PLIST_LABEL = "com.cc-claw";
|
|
24067
|
-
PLIST_PATH =
|
|
24068
|
-
SYSTEMD_DIR =
|
|
24069
|
-
UNIT_PATH =
|
|
24576
|
+
PLIST_PATH = join30(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
24577
|
+
SYSTEMD_DIR = join30(homedir10(), ".config", "systemd", "user");
|
|
24578
|
+
UNIT_PATH = join30(SYSTEMD_DIR, "cc-claw.service");
|
|
24070
24579
|
}
|
|
24071
24580
|
});
|
|
24072
24581
|
|
|
@@ -24263,7 +24772,7 @@ var status_exports = {};
|
|
|
24263
24772
|
__export(status_exports, {
|
|
24264
24773
|
statusCommand: () => statusCommand
|
|
24265
24774
|
});
|
|
24266
|
-
import { existsSync as
|
|
24775
|
+
import { existsSync as existsSync30, statSync as statSync9 } from "fs";
|
|
24267
24776
|
async function statusCommand(globalOpts, localOpts) {
|
|
24268
24777
|
try {
|
|
24269
24778
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -24303,7 +24812,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
24303
24812
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
24304
24813
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
24305
24814
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
24306
|
-
const dbStat =
|
|
24815
|
+
const dbStat = existsSync30(DB_PATH) ? statSync9(DB_PATH) : null;
|
|
24307
24816
|
let daemonRunning = false;
|
|
24308
24817
|
let daemonInfo = {};
|
|
24309
24818
|
try {
|
|
@@ -24392,12 +24901,12 @@ var doctor_exports = {};
|
|
|
24392
24901
|
__export(doctor_exports, {
|
|
24393
24902
|
doctorCommand: () => doctorCommand
|
|
24394
24903
|
});
|
|
24395
|
-
import { existsSync as
|
|
24904
|
+
import { existsSync as existsSync31, statSync as statSync10, accessSync, constants } from "fs";
|
|
24396
24905
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
24397
24906
|
async function doctorCommand(globalOpts, localOpts) {
|
|
24398
24907
|
const checks = [];
|
|
24399
|
-
if (
|
|
24400
|
-
const size =
|
|
24908
|
+
if (existsSync31(DB_PATH)) {
|
|
24909
|
+
const size = statSync10(DB_PATH).size;
|
|
24401
24910
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
24402
24911
|
try {
|
|
24403
24912
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -24426,7 +24935,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24426
24935
|
} else {
|
|
24427
24936
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
24428
24937
|
}
|
|
24429
|
-
if (
|
|
24938
|
+
if (existsSync31(ENV_PATH)) {
|
|
24430
24939
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
24431
24940
|
} else {
|
|
24432
24941
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -24481,7 +24990,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24481
24990
|
} catch {
|
|
24482
24991
|
}
|
|
24483
24992
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
24484
|
-
if (
|
|
24993
|
+
if (existsSync31(tokenPath)) {
|
|
24485
24994
|
try {
|
|
24486
24995
|
accessSync(tokenPath, constants.R_OK);
|
|
24487
24996
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -24506,10 +25015,10 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
24506
25015
|
}
|
|
24507
25016
|
} catch {
|
|
24508
25017
|
}
|
|
24509
|
-
if (
|
|
25018
|
+
if (existsSync31(ERROR_LOG_PATH)) {
|
|
24510
25019
|
try {
|
|
24511
|
-
const { readFileSync:
|
|
24512
|
-
const logContent =
|
|
25020
|
+
const { readFileSync: readFileSync27 } = await import("fs");
|
|
25021
|
+
const logContent = readFileSync27(ERROR_LOG_PATH, "utf-8");
|
|
24513
25022
|
const recentLines = logContent.split("\n").filter(Boolean).slice(-100);
|
|
24514
25023
|
const last24h = Date.now() - 864e5;
|
|
24515
25024
|
const recentErrors = recentLines.filter((line) => {
|
|
@@ -24632,10 +25141,10 @@ var logs_exports = {};
|
|
|
24632
25141
|
__export(logs_exports, {
|
|
24633
25142
|
logsCommand: () => logsCommand
|
|
24634
25143
|
});
|
|
24635
|
-
import { existsSync as
|
|
25144
|
+
import { existsSync as existsSync32, readFileSync as readFileSync20, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
24636
25145
|
async function logsCommand(opts) {
|
|
24637
25146
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
24638
|
-
if (!
|
|
25147
|
+
if (!existsSync32(logFile)) {
|
|
24639
25148
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
24640
25149
|
process.exit(1);
|
|
24641
25150
|
}
|
|
@@ -24675,6 +25184,105 @@ var init_logs = __esm({
|
|
|
24675
25184
|
}
|
|
24676
25185
|
});
|
|
24677
25186
|
|
|
25187
|
+
// src/cli/commands/session-logs.ts
|
|
25188
|
+
var session_logs_exports = {};
|
|
25189
|
+
__export(session_logs_exports, {
|
|
25190
|
+
sessionLogsClean: () => sessionLogsClean,
|
|
25191
|
+
sessionLogsList: () => sessionLogsList,
|
|
25192
|
+
sessionLogsTail: () => sessionLogsTail
|
|
25193
|
+
});
|
|
25194
|
+
import { readFileSync as readFileSync21, watchFile as watchFile3, unwatchFile as unwatchFile3 } from "fs";
|
|
25195
|
+
async function sessionLogsList(opts) {
|
|
25196
|
+
const logs = listSessionLogs();
|
|
25197
|
+
if (logs.length === 0) {
|
|
25198
|
+
console.log(muted(" No session debug logs found."));
|
|
25199
|
+
console.log(muted(` Enable via /debug in Telegram, then logs will appear in ${SESSION_LOGS_PATH}`));
|
|
25200
|
+
return;
|
|
25201
|
+
}
|
|
25202
|
+
if (opts.json) {
|
|
25203
|
+
console.log(JSON.stringify(logs.map((l) => ({
|
|
25204
|
+
filename: l.filename,
|
|
25205
|
+
chatId: l.chatId,
|
|
25206
|
+
timestamp: l.timestamp,
|
|
25207
|
+
sizeBytes: l.sizeBytes,
|
|
25208
|
+
modifiedAt: l.modifiedAt.toISOString()
|
|
25209
|
+
})), null, 2));
|
|
25210
|
+
return;
|
|
25211
|
+
}
|
|
25212
|
+
console.log(muted(` \u2500\u2500 Session Debug Logs (${logs.length}) \u2500\u2500
|
|
25213
|
+
`));
|
|
25214
|
+
console.log(` ${"Filename".padEnd(55)} ${"Size".padStart(8)} Chat ID`);
|
|
25215
|
+
console.log(` ${"\u2500".repeat(55)} ${"\u2500".repeat(8)} ${"\u2500".repeat(15)}`);
|
|
25216
|
+
for (const log5 of logs) {
|
|
25217
|
+
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`;
|
|
25218
|
+
console.log(` ${log5.filename.padEnd(55)} ${size.padStart(8)} ${log5.chatId}`);
|
|
25219
|
+
}
|
|
25220
|
+
console.log(muted(`
|
|
25221
|
+
Path: ${SESSION_LOGS_PATH}`));
|
|
25222
|
+
console.log(muted(` Retention: ${getRetentionDays()} day(s) (set SESSION_LOG_RETENTION_DAYS to change)`));
|
|
25223
|
+
}
|
|
25224
|
+
async function sessionLogsTail(opts) {
|
|
25225
|
+
const logs = listSessionLogs();
|
|
25226
|
+
if (logs.length === 0) {
|
|
25227
|
+
outputError("NO_LOGS", "No session debug logs found. Enable via /debug in Telegram.");
|
|
25228
|
+
return;
|
|
25229
|
+
}
|
|
25230
|
+
let targetPath;
|
|
25231
|
+
if (opts.file) {
|
|
25232
|
+
const match = logs.find((l) => l.filename.includes(opts.file));
|
|
25233
|
+
if (!match) {
|
|
25234
|
+
outputError("NOT_FOUND", `No session log matching "${opts.file}". Use 'cc-claw logs session list' to see available logs.`);
|
|
25235
|
+
return;
|
|
25236
|
+
}
|
|
25237
|
+
targetPath = match.filePath;
|
|
25238
|
+
} else {
|
|
25239
|
+
targetPath = logs[0].filePath;
|
|
25240
|
+
}
|
|
25241
|
+
const lineCount = parseInt(opts.lines ?? "50", 10);
|
|
25242
|
+
console.log(muted(` \u2500\u2500 ${targetPath} (last ${lineCount} lines) \u2500\u2500
|
|
25243
|
+
`));
|
|
25244
|
+
for await (const line of tailSessionLog(targetPath, lineCount)) {
|
|
25245
|
+
console.log(line);
|
|
25246
|
+
}
|
|
25247
|
+
if (opts.follow) {
|
|
25248
|
+
console.log(muted("\n Following... (Ctrl+C to stop)\n"));
|
|
25249
|
+
let lastLength = 0;
|
|
25250
|
+
try {
|
|
25251
|
+
lastLength = readFileSync21(targetPath, "utf-8").length;
|
|
25252
|
+
} catch {
|
|
25253
|
+
}
|
|
25254
|
+
watchFile3(targetPath, { interval: 500 }, () => {
|
|
25255
|
+
try {
|
|
25256
|
+
const content = readFileSync21(targetPath, "utf-8");
|
|
25257
|
+
if (content.length > lastLength) {
|
|
25258
|
+
process.stdout.write(content.slice(lastLength));
|
|
25259
|
+
lastLength = content.length;
|
|
25260
|
+
}
|
|
25261
|
+
} catch {
|
|
25262
|
+
}
|
|
25263
|
+
});
|
|
25264
|
+
process.on("SIGINT", () => {
|
|
25265
|
+
unwatchFile3(targetPath);
|
|
25266
|
+
process.exit(0);
|
|
25267
|
+
});
|
|
25268
|
+
await new Promise(() => {
|
|
25269
|
+
});
|
|
25270
|
+
}
|
|
25271
|
+
}
|
|
25272
|
+
async function sessionLogsClean(opts) {
|
|
25273
|
+
const days = opts.days ? parseInt(opts.days, 10) : void 0;
|
|
25274
|
+
const cleaned = cleanupSessionLogs(days);
|
|
25275
|
+
console.log(success(`Cleaned ${cleaned} session log(s) older than ${days ?? getRetentionDays()} day(s).`));
|
|
25276
|
+
}
|
|
25277
|
+
var init_session_logs = __esm({
|
|
25278
|
+
"src/cli/commands/session-logs.ts"() {
|
|
25279
|
+
"use strict";
|
|
25280
|
+
init_session_log2();
|
|
25281
|
+
init_paths();
|
|
25282
|
+
init_format2();
|
|
25283
|
+
}
|
|
25284
|
+
});
|
|
25285
|
+
|
|
24678
25286
|
// src/cli/commands/gemini.ts
|
|
24679
25287
|
var gemini_exports = {};
|
|
24680
25288
|
__export(gemini_exports, {
|
|
@@ -24687,11 +25295,11 @@ __export(gemini_exports, {
|
|
|
24687
25295
|
geminiReorder: () => geminiReorder,
|
|
24688
25296
|
geminiRotation: () => geminiRotation
|
|
24689
25297
|
});
|
|
24690
|
-
import { existsSync as
|
|
24691
|
-
import { join as
|
|
24692
|
-
import { createInterface as
|
|
25298
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync14, writeFileSync as writeFileSync10, readFileSync as readFileSync22, chmodSync } from "fs";
|
|
25299
|
+
import { join as join31 } from "path";
|
|
25300
|
+
import { createInterface as createInterface7 } from "readline";
|
|
24693
25301
|
function requireDb() {
|
|
24694
|
-
if (!
|
|
25302
|
+
if (!existsSync34(DB_PATH)) {
|
|
24695
25303
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
24696
25304
|
process.exit(1);
|
|
24697
25305
|
}
|
|
@@ -24716,9 +25324,9 @@ async function resolveSlotId(idOrLabel) {
|
|
|
24716
25324
|
function resolveOAuthEmail(configHome) {
|
|
24717
25325
|
if (!configHome) return null;
|
|
24718
25326
|
try {
|
|
24719
|
-
const accountsPath =
|
|
24720
|
-
if (!
|
|
24721
|
-
const accounts = JSON.parse(
|
|
25327
|
+
const accountsPath = join31(configHome, ".gemini", "google_accounts.json");
|
|
25328
|
+
if (!existsSync34(accountsPath)) return null;
|
|
25329
|
+
const accounts = JSON.parse(readFileSync22(accountsPath, "utf-8"));
|
|
24722
25330
|
return accounts.active || null;
|
|
24723
25331
|
} catch {
|
|
24724
25332
|
return null;
|
|
@@ -24762,7 +25370,7 @@ async function geminiList(globalOpts) {
|
|
|
24762
25370
|
}
|
|
24763
25371
|
async function geminiAddKey(globalOpts, opts) {
|
|
24764
25372
|
await requireWriteDb();
|
|
24765
|
-
const rl2 =
|
|
25373
|
+
const rl2 = createInterface7({ input: process.stdin, output: process.stdout });
|
|
24766
25374
|
const ask2 = (q) => new Promise((r) => rl2.question(q, r));
|
|
24767
25375
|
const key = await ask2("Paste your Gemini API key: ");
|
|
24768
25376
|
rl2.close();
|
|
@@ -24800,14 +25408,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
24800
25408
|
}
|
|
24801
25409
|
async function geminiAddAccount(globalOpts, opts) {
|
|
24802
25410
|
await requireWriteDb();
|
|
24803
|
-
const slotsDir =
|
|
24804
|
-
if (!
|
|
25411
|
+
const slotsDir = join31(CC_CLAW_HOME, "gemini-slots");
|
|
25412
|
+
if (!existsSync34(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
24805
25413
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
24806
25414
|
const tempId = Date.now();
|
|
24807
|
-
const slotDir =
|
|
24808
|
-
|
|
24809
|
-
|
|
24810
|
-
writeFileSync10(
|
|
25415
|
+
const slotDir = join31(slotsDir, `slot-${tempId}`);
|
|
25416
|
+
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
25417
|
+
mkdirSync14(join31(slotDir, ".gemini"), { recursive: true });
|
|
25418
|
+
writeFileSync10(join31(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
24811
25419
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
24812
25420
|
}, null, 2));
|
|
24813
25421
|
console.log("");
|
|
@@ -24824,8 +25432,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
24824
25432
|
});
|
|
24825
25433
|
} catch {
|
|
24826
25434
|
}
|
|
24827
|
-
const oauthPath =
|
|
24828
|
-
if (!
|
|
25435
|
+
const oauthPath = join31(slotDir, ".gemini", "oauth_creds.json");
|
|
25436
|
+
if (!existsSync34(oauthPath)) {
|
|
24829
25437
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
24830
25438
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
24831
25439
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -24833,7 +25441,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
24833
25441
|
}
|
|
24834
25442
|
let accountEmail = "unknown";
|
|
24835
25443
|
try {
|
|
24836
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
25444
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join31(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
24837
25445
|
accountEmail = accounts.active || accountEmail;
|
|
24838
25446
|
} catch {
|
|
24839
25447
|
}
|
|
@@ -24952,11 +25560,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
24952
25560
|
makeReorder: () => makeReorder,
|
|
24953
25561
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
24954
25562
|
});
|
|
24955
|
-
import { existsSync as
|
|
24956
|
-
import { join as
|
|
24957
|
-
import { createInterface as
|
|
25563
|
+
import { existsSync as existsSync35, mkdirSync as mkdirSync15, readFileSync as readFileSync23 } from "fs";
|
|
25564
|
+
import { join as join32 } from "path";
|
|
25565
|
+
import { createInterface as createInterface8 } from "readline";
|
|
24958
25566
|
function requireDb2() {
|
|
24959
|
-
if (!
|
|
25567
|
+
if (!existsSync35(DB_PATH)) {
|
|
24960
25568
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
24961
25569
|
process.exit(1);
|
|
24962
25570
|
}
|
|
@@ -25015,7 +25623,7 @@ Add one with: cc-claw ${backend2} add-account or cc-claw ${backend2} add-key`)
|
|
|
25015
25623
|
function makeAddKey(backend2, displayName) {
|
|
25016
25624
|
return async function addKey(_globalOpts, opts) {
|
|
25017
25625
|
await requireWriteDb2();
|
|
25018
|
-
const rl2 =
|
|
25626
|
+
const rl2 = createInterface8({ input: process.stdin, output: process.stdout });
|
|
25019
25627
|
const ask2 = (q) => new Promise((r) => rl2.question(q, r));
|
|
25020
25628
|
const key = await ask2(`Paste your ${displayName} API key: `);
|
|
25021
25629
|
rl2.close();
|
|
@@ -25045,11 +25653,11 @@ function makeAddAccount(backend2, displayName) {
|
|
|
25045
25653
|
process.exit(1);
|
|
25046
25654
|
}
|
|
25047
25655
|
await requireWriteDb2();
|
|
25048
|
-
const slotsDir =
|
|
25049
|
-
if (!
|
|
25656
|
+
const slotsDir = join32(CC_CLAW_HOME, config2.slotsSubdir);
|
|
25657
|
+
if (!existsSync35(slotsDir)) mkdirSync15(slotsDir, { recursive: true });
|
|
25050
25658
|
const tempId = Date.now();
|
|
25051
|
-
const slotDir =
|
|
25052
|
-
|
|
25659
|
+
const slotDir = join32(slotsDir, `slot-${tempId}`);
|
|
25660
|
+
mkdirSync15(slotDir, { recursive: true, mode: 448 });
|
|
25053
25661
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
25054
25662
|
console.log("");
|
|
25055
25663
|
console.log(` Opening ${displayName} CLI for sign-in...`);
|
|
@@ -25217,22 +25825,22 @@ var init_backend_cmd_factory = __esm({
|
|
|
25217
25825
|
envValue: (slotDir) => slotDir,
|
|
25218
25826
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
25219
25827
|
preSetup: (slotDir) => {
|
|
25220
|
-
|
|
25828
|
+
mkdirSync15(join32(slotDir, ".claude"), { recursive: true });
|
|
25221
25829
|
},
|
|
25222
25830
|
verifyCredentials: (slotDir) => {
|
|
25223
|
-
const claudeJson =
|
|
25224
|
-
const claudeJsonNested =
|
|
25225
|
-
if (
|
|
25831
|
+
const claudeJson = join32(slotDir, ".claude.json");
|
|
25832
|
+
const claudeJsonNested = join32(slotDir, ".claude", ".claude.json");
|
|
25833
|
+
if (existsSync35(claudeJson)) {
|
|
25226
25834
|
try {
|
|
25227
|
-
const data = JSON.parse(
|
|
25835
|
+
const data = JSON.parse(readFileSync23(claudeJson, "utf-8"));
|
|
25228
25836
|
return Boolean(data.oauthAccount);
|
|
25229
25837
|
} catch {
|
|
25230
25838
|
return false;
|
|
25231
25839
|
}
|
|
25232
25840
|
}
|
|
25233
|
-
if (
|
|
25841
|
+
if (existsSync35(claudeJsonNested)) {
|
|
25234
25842
|
try {
|
|
25235
|
-
const data = JSON.parse(
|
|
25843
|
+
const data = JSON.parse(readFileSync23(claudeJsonNested, "utf-8"));
|
|
25236
25844
|
return Boolean(data.oauthAccount);
|
|
25237
25845
|
} catch {
|
|
25238
25846
|
return false;
|
|
@@ -25253,9 +25861,9 @@ var init_backend_cmd_factory = __esm({
|
|
|
25253
25861
|
} catch {
|
|
25254
25862
|
}
|
|
25255
25863
|
try {
|
|
25256
|
-
const claudeJson =
|
|
25257
|
-
if (
|
|
25258
|
-
const data = JSON.parse(
|
|
25864
|
+
const claudeJson = join32(slotDir, ".claude.json");
|
|
25865
|
+
if (existsSync35(claudeJson)) {
|
|
25866
|
+
const data = JSON.parse(readFileSync23(claudeJson, "utf-8"));
|
|
25259
25867
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
25260
25868
|
}
|
|
25261
25869
|
} catch {
|
|
@@ -25270,11 +25878,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
25270
25878
|
envValue: (slotDir) => slotDir,
|
|
25271
25879
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
25272
25880
|
verifyCredentials: (slotDir) => {
|
|
25273
|
-
return
|
|
25881
|
+
return existsSync35(join32(slotDir, "auth.json"));
|
|
25274
25882
|
},
|
|
25275
25883
|
extractLabel: (slotDir) => {
|
|
25276
25884
|
try {
|
|
25277
|
-
const authData = JSON.parse(
|
|
25885
|
+
const authData = JSON.parse(readFileSync23(join32(slotDir, "auth.json"), "utf-8"));
|
|
25278
25886
|
if (authData.email) return authData.email;
|
|
25279
25887
|
if (authData.account_name) return authData.account_name;
|
|
25280
25888
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -25294,12 +25902,12 @@ __export(backend_exports, {
|
|
|
25294
25902
|
backendList: () => backendList,
|
|
25295
25903
|
backendSet: () => backendSet
|
|
25296
25904
|
});
|
|
25297
|
-
import { existsSync as
|
|
25905
|
+
import { existsSync as existsSync36 } from "fs";
|
|
25298
25906
|
async function backendList(globalOpts) {
|
|
25299
25907
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
25300
25908
|
const chatId = resolveChatId(globalOpts);
|
|
25301
25909
|
let activeBackend = null;
|
|
25302
|
-
if (
|
|
25910
|
+
if (existsSync36(DB_PATH)) {
|
|
25303
25911
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25304
25912
|
const readDb = openDatabaseReadOnly2();
|
|
25305
25913
|
try {
|
|
@@ -25330,7 +25938,7 @@ async function backendList(globalOpts) {
|
|
|
25330
25938
|
}
|
|
25331
25939
|
async function backendGet(globalOpts) {
|
|
25332
25940
|
const chatId = resolveChatId(globalOpts);
|
|
25333
|
-
if (!
|
|
25941
|
+
if (!existsSync36(DB_PATH)) {
|
|
25334
25942
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25335
25943
|
process.exit(1);
|
|
25336
25944
|
}
|
|
@@ -25374,13 +25982,13 @@ __export(model_exports, {
|
|
|
25374
25982
|
modelList: () => modelList,
|
|
25375
25983
|
modelSet: () => modelSet
|
|
25376
25984
|
});
|
|
25377
|
-
import { existsSync as
|
|
25985
|
+
import { existsSync as existsSync37 } from "fs";
|
|
25378
25986
|
async function modelList(globalOpts) {
|
|
25379
25987
|
const chatId = resolveChatId(globalOpts);
|
|
25380
25988
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25381
25989
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
25382
25990
|
let backendId = "claude";
|
|
25383
|
-
if (
|
|
25991
|
+
if (existsSync37(DB_PATH)) {
|
|
25384
25992
|
const readDb = openDatabaseReadOnly2();
|
|
25385
25993
|
try {
|
|
25386
25994
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -25413,7 +26021,7 @@ async function modelList(globalOpts) {
|
|
|
25413
26021
|
}
|
|
25414
26022
|
async function modelGet(globalOpts) {
|
|
25415
26023
|
const chatId = resolveChatId(globalOpts);
|
|
25416
|
-
if (!
|
|
26024
|
+
if (!existsSync37(DB_PATH)) {
|
|
25417
26025
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25418
26026
|
process.exit(1);
|
|
25419
26027
|
}
|
|
@@ -25457,9 +26065,9 @@ __export(memory_exports2, {
|
|
|
25457
26065
|
memoryList: () => memoryList,
|
|
25458
26066
|
memorySearch: () => memorySearch
|
|
25459
26067
|
});
|
|
25460
|
-
import { existsSync as
|
|
26068
|
+
import { existsSync as existsSync38 } from "fs";
|
|
25461
26069
|
async function memoryList(globalOpts) {
|
|
25462
|
-
if (!
|
|
26070
|
+
if (!existsSync38(DB_PATH)) {
|
|
25463
26071
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25464
26072
|
process.exit(1);
|
|
25465
26073
|
}
|
|
@@ -25483,7 +26091,7 @@ async function memoryList(globalOpts) {
|
|
|
25483
26091
|
});
|
|
25484
26092
|
}
|
|
25485
26093
|
async function memorySearch(globalOpts, query) {
|
|
25486
|
-
if (!
|
|
26094
|
+
if (!existsSync38(DB_PATH)) {
|
|
25487
26095
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25488
26096
|
process.exit(1);
|
|
25489
26097
|
}
|
|
@@ -25505,7 +26113,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
25505
26113
|
});
|
|
25506
26114
|
}
|
|
25507
26115
|
async function memoryHistory(globalOpts, opts) {
|
|
25508
|
-
if (!
|
|
26116
|
+
if (!existsSync38(DB_PATH)) {
|
|
25509
26117
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25510
26118
|
process.exit(1);
|
|
25511
26119
|
}
|
|
@@ -25553,7 +26161,7 @@ __export(cron_exports2, {
|
|
|
25553
26161
|
cronList: () => cronList,
|
|
25554
26162
|
cronRuns: () => cronRuns
|
|
25555
26163
|
});
|
|
25556
|
-
import { existsSync as
|
|
26164
|
+
import { existsSync as existsSync39 } from "fs";
|
|
25557
26165
|
function parseFallbacks(raw) {
|
|
25558
26166
|
return raw.slice(0, 3).map((f) => {
|
|
25559
26167
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -25574,7 +26182,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
25574
26182
|
return val;
|
|
25575
26183
|
}
|
|
25576
26184
|
async function cronList(globalOpts) {
|
|
25577
|
-
if (!
|
|
26185
|
+
if (!existsSync39(DB_PATH)) {
|
|
25578
26186
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25579
26187
|
process.exit(1);
|
|
25580
26188
|
}
|
|
@@ -25612,7 +26220,7 @@ async function cronList(globalOpts) {
|
|
|
25612
26220
|
});
|
|
25613
26221
|
}
|
|
25614
26222
|
async function cronHealth(globalOpts) {
|
|
25615
|
-
if (!
|
|
26223
|
+
if (!existsSync39(DB_PATH)) {
|
|
25616
26224
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25617
26225
|
process.exit(1);
|
|
25618
26226
|
}
|
|
@@ -25771,7 +26379,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
25771
26379
|
}
|
|
25772
26380
|
}
|
|
25773
26381
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
25774
|
-
if (!
|
|
26382
|
+
if (!existsSync39(DB_PATH)) {
|
|
25775
26383
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25776
26384
|
process.exit(1);
|
|
25777
26385
|
}
|
|
@@ -25818,9 +26426,9 @@ __export(agents_exports, {
|
|
|
25818
26426
|
runnersList: () => runnersList,
|
|
25819
26427
|
tasksList: () => tasksList
|
|
25820
26428
|
});
|
|
25821
|
-
import { existsSync as
|
|
26429
|
+
import { existsSync as existsSync40 } from "fs";
|
|
25822
26430
|
async function agentsList(globalOpts) {
|
|
25823
|
-
if (!
|
|
26431
|
+
if (!existsSync40(DB_PATH)) {
|
|
25824
26432
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25825
26433
|
process.exit(1);
|
|
25826
26434
|
}
|
|
@@ -25851,7 +26459,7 @@ async function agentsList(globalOpts) {
|
|
|
25851
26459
|
});
|
|
25852
26460
|
}
|
|
25853
26461
|
async function tasksList(globalOpts) {
|
|
25854
|
-
if (!
|
|
26462
|
+
if (!existsSync40(DB_PATH)) {
|
|
25855
26463
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
25856
26464
|
process.exit(1);
|
|
25857
26465
|
}
|
|
@@ -25979,18 +26587,18 @@ __export(db_exports, {
|
|
|
25979
26587
|
dbPath: () => dbPath,
|
|
25980
26588
|
dbStats: () => dbStats
|
|
25981
26589
|
});
|
|
25982
|
-
import { existsSync as
|
|
26590
|
+
import { existsSync as existsSync41, statSync as statSync11, copyFileSync as copyFileSync3, mkdirSync as mkdirSync16 } from "fs";
|
|
25983
26591
|
import { dirname as dirname7 } from "path";
|
|
25984
26592
|
async function dbStats(globalOpts) {
|
|
25985
|
-
if (!
|
|
26593
|
+
if (!existsSync41(DB_PATH)) {
|
|
25986
26594
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
25987
26595
|
process.exit(1);
|
|
25988
26596
|
}
|
|
25989
26597
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
25990
26598
|
const readDb = openDatabaseReadOnly2();
|
|
25991
|
-
const mainSize =
|
|
26599
|
+
const mainSize = statSync11(DB_PATH).size;
|
|
25992
26600
|
const walPath = DB_PATH + "-wal";
|
|
25993
|
-
const walSize =
|
|
26601
|
+
const walSize = existsSync41(walPath) ? statSync11(walPath).size : 0;
|
|
25994
26602
|
const tableNames = readDb.prepare(
|
|
25995
26603
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
25996
26604
|
).all();
|
|
@@ -26024,17 +26632,17 @@ async function dbPath(globalOpts) {
|
|
|
26024
26632
|
output({ path: DB_PATH }, (d) => d.path);
|
|
26025
26633
|
}
|
|
26026
26634
|
async function dbBackup(globalOpts, destPath) {
|
|
26027
|
-
if (!
|
|
26635
|
+
if (!existsSync41(DB_PATH)) {
|
|
26028
26636
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
26029
26637
|
process.exit(1);
|
|
26030
26638
|
}
|
|
26031
26639
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
26032
26640
|
try {
|
|
26033
|
-
|
|
26641
|
+
mkdirSync16(dirname7(dest), { recursive: true });
|
|
26034
26642
|
copyFileSync3(DB_PATH, dest);
|
|
26035
26643
|
const walPath = DB_PATH + "-wal";
|
|
26036
|
-
if (
|
|
26037
|
-
output({ path: dest, sizeBytes:
|
|
26644
|
+
if (existsSync41(walPath)) copyFileSync3(walPath, dest + "-wal");
|
|
26645
|
+
output({ path: dest, sizeBytes: statSync11(dest).size }, (d) => {
|
|
26038
26646
|
const b = d;
|
|
26039
26647
|
return `
|
|
26040
26648
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -26062,9 +26670,9 @@ __export(usage_exports, {
|
|
|
26062
26670
|
usageCost: () => usageCost,
|
|
26063
26671
|
usageTokens: () => usageTokens
|
|
26064
26672
|
});
|
|
26065
|
-
import { existsSync as
|
|
26673
|
+
import { existsSync as existsSync42 } from "fs";
|
|
26066
26674
|
function ensureDb() {
|
|
26067
|
-
if (!
|
|
26675
|
+
if (!existsSync42(DB_PATH)) {
|
|
26068
26676
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
26069
26677
|
process.exit(1);
|
|
26070
26678
|
}
|
|
@@ -26254,9 +26862,9 @@ __export(config_exports2, {
|
|
|
26254
26862
|
configList: () => configList,
|
|
26255
26863
|
configSet: () => configSet
|
|
26256
26864
|
});
|
|
26257
|
-
import { existsSync as
|
|
26865
|
+
import { existsSync as existsSync43, readFileSync as readFileSync24 } from "fs";
|
|
26258
26866
|
async function configList(globalOpts) {
|
|
26259
|
-
if (!
|
|
26867
|
+
if (!existsSync43(DB_PATH)) {
|
|
26260
26868
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26261
26869
|
process.exit(1);
|
|
26262
26870
|
}
|
|
@@ -26290,7 +26898,7 @@ async function configGet(globalOpts, key) {
|
|
|
26290
26898
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
26291
26899
|
process.exit(1);
|
|
26292
26900
|
}
|
|
26293
|
-
if (!
|
|
26901
|
+
if (!existsSync43(DB_PATH)) {
|
|
26294
26902
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26295
26903
|
process.exit(1);
|
|
26296
26904
|
}
|
|
@@ -26336,11 +26944,11 @@ async function configSet(globalOpts, key, value) {
|
|
|
26336
26944
|
}
|
|
26337
26945
|
}
|
|
26338
26946
|
async function configEnv(_globalOpts) {
|
|
26339
|
-
if (!
|
|
26947
|
+
if (!existsSync43(ENV_PATH)) {
|
|
26340
26948
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
26341
26949
|
process.exit(1);
|
|
26342
26950
|
}
|
|
26343
|
-
const content =
|
|
26951
|
+
const content = readFileSync24(ENV_PATH, "utf-8");
|
|
26344
26952
|
const entries = {};
|
|
26345
26953
|
const secretPatterns = /TOKEN|KEY|SECRET|PASSWORD|CREDENTIALS/i;
|
|
26346
26954
|
for (const line of content.split("\n")) {
|
|
@@ -26390,9 +26998,9 @@ __export(session_exports, {
|
|
|
26390
26998
|
sessionGet: () => sessionGet,
|
|
26391
26999
|
sessionNew: () => sessionNew
|
|
26392
27000
|
});
|
|
26393
|
-
import { existsSync as
|
|
27001
|
+
import { existsSync as existsSync44 } from "fs";
|
|
26394
27002
|
async function sessionGet(globalOpts) {
|
|
26395
|
-
if (!
|
|
27003
|
+
if (!existsSync44(DB_PATH)) {
|
|
26396
27004
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26397
27005
|
process.exit(1);
|
|
26398
27006
|
}
|
|
@@ -26453,9 +27061,9 @@ __export(permissions_exports, {
|
|
|
26453
27061
|
verboseGet: () => verboseGet,
|
|
26454
27062
|
verboseSet: () => verboseSet
|
|
26455
27063
|
});
|
|
26456
|
-
import { existsSync as
|
|
27064
|
+
import { existsSync as existsSync45 } from "fs";
|
|
26457
27065
|
function ensureDb2() {
|
|
26458
|
-
if (!
|
|
27066
|
+
if (!existsSync45(DB_PATH)) {
|
|
26459
27067
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26460
27068
|
process.exit(1);
|
|
26461
27069
|
}
|
|
@@ -26602,9 +27210,9 @@ __export(cwd_exports, {
|
|
|
26602
27210
|
cwdGet: () => cwdGet,
|
|
26603
27211
|
cwdSet: () => cwdSet
|
|
26604
27212
|
});
|
|
26605
|
-
import { existsSync as
|
|
27213
|
+
import { existsSync as existsSync46 } from "fs";
|
|
26606
27214
|
async function cwdGet(globalOpts) {
|
|
26607
|
-
if (!
|
|
27215
|
+
if (!existsSync46(DB_PATH)) {
|
|
26608
27216
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26609
27217
|
process.exit(1);
|
|
26610
27218
|
}
|
|
@@ -26666,9 +27274,9 @@ __export(voice_exports, {
|
|
|
26666
27274
|
voiceGet: () => voiceGet,
|
|
26667
27275
|
voiceSet: () => voiceSet
|
|
26668
27276
|
});
|
|
26669
|
-
import { existsSync as
|
|
27277
|
+
import { existsSync as existsSync47 } from "fs";
|
|
26670
27278
|
async function voiceGet(globalOpts) {
|
|
26671
|
-
if (!
|
|
27279
|
+
if (!existsSync47(DB_PATH)) {
|
|
26672
27280
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26673
27281
|
process.exit(1);
|
|
26674
27282
|
}
|
|
@@ -26717,9 +27325,9 @@ __export(heartbeat_exports, {
|
|
|
26717
27325
|
heartbeatGet: () => heartbeatGet,
|
|
26718
27326
|
heartbeatSet: () => heartbeatSet
|
|
26719
27327
|
});
|
|
26720
|
-
import { existsSync as
|
|
27328
|
+
import { existsSync as existsSync48 } from "fs";
|
|
26721
27329
|
async function heartbeatGet(globalOpts) {
|
|
26722
|
-
if (!
|
|
27330
|
+
if (!existsSync48(DB_PATH)) {
|
|
26723
27331
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26724
27332
|
process.exit(1);
|
|
26725
27333
|
}
|
|
@@ -26828,9 +27436,9 @@ __export(summarizer_exports, {
|
|
|
26828
27436
|
summarizerGet: () => summarizerGet,
|
|
26829
27437
|
summarizerSet: () => summarizerSet
|
|
26830
27438
|
});
|
|
26831
|
-
import { existsSync as
|
|
27439
|
+
import { existsSync as existsSync49 } from "fs";
|
|
26832
27440
|
async function summarizerGet(globalOpts) {
|
|
26833
|
-
if (!
|
|
27441
|
+
if (!existsSync49(DB_PATH)) {
|
|
26834
27442
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26835
27443
|
process.exit(1);
|
|
26836
27444
|
}
|
|
@@ -26874,9 +27482,9 @@ __export(thinking_exports, {
|
|
|
26874
27482
|
thinkingGet: () => thinkingGet,
|
|
26875
27483
|
thinkingSet: () => thinkingSet
|
|
26876
27484
|
});
|
|
26877
|
-
import { existsSync as
|
|
27485
|
+
import { existsSync as existsSync50 } from "fs";
|
|
26878
27486
|
async function thinkingGet(globalOpts) {
|
|
26879
|
-
if (!
|
|
27487
|
+
if (!existsSync50(DB_PATH)) {
|
|
26880
27488
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26881
27489
|
process.exit(1);
|
|
26882
27490
|
}
|
|
@@ -26920,9 +27528,9 @@ __export(chats_exports, {
|
|
|
26920
27528
|
chatsList: () => chatsList,
|
|
26921
27529
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
26922
27530
|
});
|
|
26923
|
-
import { existsSync as
|
|
27531
|
+
import { existsSync as existsSync51 } from "fs";
|
|
26924
27532
|
async function chatsList(_globalOpts) {
|
|
26925
|
-
if (!
|
|
27533
|
+
if (!existsSync51(DB_PATH)) {
|
|
26926
27534
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
26927
27535
|
process.exit(1);
|
|
26928
27536
|
}
|
|
@@ -27050,9 +27658,9 @@ var mcps_exports2 = {};
|
|
|
27050
27658
|
__export(mcps_exports2, {
|
|
27051
27659
|
mcpsList: () => mcpsList
|
|
27052
27660
|
});
|
|
27053
|
-
import { existsSync as
|
|
27661
|
+
import { existsSync as existsSync52 } from "fs";
|
|
27054
27662
|
async function mcpsList(_globalOpts) {
|
|
27055
|
-
if (!
|
|
27663
|
+
if (!existsSync52(DB_PATH)) {
|
|
27056
27664
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
27057
27665
|
process.exit(1);
|
|
27058
27666
|
}
|
|
@@ -27089,11 +27697,11 @@ __export(chat_exports2, {
|
|
|
27089
27697
|
chatSend: () => chatSend
|
|
27090
27698
|
});
|
|
27091
27699
|
import { request as httpRequest2 } from "http";
|
|
27092
|
-
import { readFileSync as
|
|
27700
|
+
import { readFileSync as readFileSync25, existsSync as existsSync53 } from "fs";
|
|
27093
27701
|
function getToken2() {
|
|
27094
27702
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
27095
27703
|
try {
|
|
27096
|
-
if (
|
|
27704
|
+
if (existsSync53(TOKEN_PATH2)) return readFileSync25(TOKEN_PATH2, "utf-8").trim();
|
|
27097
27705
|
} catch {
|
|
27098
27706
|
}
|
|
27099
27707
|
return null;
|
|
@@ -27230,7 +27838,7 @@ var tui_exports = {};
|
|
|
27230
27838
|
__export(tui_exports, {
|
|
27231
27839
|
tuiCommand: () => tuiCommand
|
|
27232
27840
|
});
|
|
27233
|
-
import { createInterface as
|
|
27841
|
+
import { createInterface as createInterface9 } from "readline";
|
|
27234
27842
|
import pc2 from "picocolors";
|
|
27235
27843
|
async function tuiCommand(globalOpts, cmdOpts) {
|
|
27236
27844
|
const { isDaemonRunning: isDaemonRunning2, apiPost: apiPost2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
@@ -27240,7 +27848,7 @@ async function tuiCommand(globalOpts, cmdOpts) {
|
|
|
27240
27848
|
}
|
|
27241
27849
|
const chatId = resolveChatId(globalOpts);
|
|
27242
27850
|
const { chatSend: chatSend2 } = await Promise.resolve().then(() => (init_chat2(), chat_exports2));
|
|
27243
|
-
const rl2 =
|
|
27851
|
+
const rl2 = createInterface9({
|
|
27244
27852
|
input: process.stdin,
|
|
27245
27853
|
output: process.stdout,
|
|
27246
27854
|
prompt: pc2.cyan("you > "),
|
|
@@ -27372,8 +27980,8 @@ var completion_exports = {};
|
|
|
27372
27980
|
__export(completion_exports, {
|
|
27373
27981
|
completionCommand: () => completionCommand
|
|
27374
27982
|
});
|
|
27375
|
-
import { writeFileSync as writeFileSync11, mkdirSync as
|
|
27376
|
-
import { join as
|
|
27983
|
+
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync17 } from "fs";
|
|
27984
|
+
import { join as join33 } from "path";
|
|
27377
27985
|
import { homedir as homedir11 } from "os";
|
|
27378
27986
|
async function completionCommand(opts) {
|
|
27379
27987
|
const shell = opts.shell ?? detectShell();
|
|
@@ -27389,10 +27997,10 @@ async function completionCommand(opts) {
|
|
|
27389
27997
|
process.exit(1);
|
|
27390
27998
|
}
|
|
27391
27999
|
if (opts.install) {
|
|
27392
|
-
const dir =
|
|
27393
|
-
|
|
28000
|
+
const dir = join33(homedir11(), ".config", "cc-claw", "completions");
|
|
28001
|
+
mkdirSync17(dir, { recursive: true });
|
|
27394
28002
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
27395
|
-
const filepath =
|
|
28003
|
+
const filepath = join33(dir, filename);
|
|
27396
28004
|
writeFileSync11(filepath, script, "utf-8");
|
|
27397
28005
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
27398
28006
|
`);
|
|
@@ -27563,9 +28171,9 @@ __export(evolve_exports2, {
|
|
|
27563
28171
|
evolveStatus: () => evolveStatus,
|
|
27564
28172
|
evolveUndo: () => evolveUndo
|
|
27565
28173
|
});
|
|
27566
|
-
import { existsSync as
|
|
28174
|
+
import { existsSync as existsSync54 } from "fs";
|
|
27567
28175
|
function ensureDb3() {
|
|
27568
|
-
if (!
|
|
28176
|
+
if (!existsSync54(DB_PATH)) {
|
|
27569
28177
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
27570
28178
|
process.exit(1);
|
|
27571
28179
|
}
|
|
@@ -28039,10 +28647,10 @@ var init_optimize2 = __esm({
|
|
|
28039
28647
|
|
|
28040
28648
|
// src/setup.ts
|
|
28041
28649
|
var setup_exports = {};
|
|
28042
|
-
import { existsSync as
|
|
28650
|
+
import { existsSync as existsSync55, writeFileSync as writeFileSync12, readFileSync as readFileSync26, copyFileSync as copyFileSync4, mkdirSync as mkdirSync18, statSync as statSync12 } from "fs";
|
|
28043
28651
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
28044
|
-
import { createInterface as
|
|
28045
|
-
import { join as
|
|
28652
|
+
import { createInterface as createInterface10 } from "readline";
|
|
28653
|
+
import { join as join34 } from "path";
|
|
28046
28654
|
function divider2() {
|
|
28047
28655
|
console.log(dim("\u2500".repeat(55)));
|
|
28048
28656
|
}
|
|
@@ -28117,22 +28725,22 @@ async function setup() {
|
|
|
28117
28725
|
}
|
|
28118
28726
|
console.log("");
|
|
28119
28727
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
28120
|
-
if (!
|
|
28728
|
+
if (!existsSync55(dir)) mkdirSync18(dir, { recursive: true });
|
|
28121
28729
|
}
|
|
28122
28730
|
const env = {};
|
|
28123
|
-
const envSource =
|
|
28731
|
+
const envSource = existsSync55(ENV_PATH) ? ENV_PATH : existsSync55(".env") ? ".env" : null;
|
|
28124
28732
|
if (envSource) {
|
|
28125
28733
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
28126
28734
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
28127
|
-
const existing =
|
|
28735
|
+
const existing = readFileSync26(envSource, "utf-8");
|
|
28128
28736
|
for (const line of existing.split("\n")) {
|
|
28129
28737
|
const match = line.match(/^([^#=]+)=(.*)$/);
|
|
28130
28738
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
28131
28739
|
}
|
|
28132
28740
|
}
|
|
28133
|
-
const cwdDb =
|
|
28134
|
-
if (
|
|
28135
|
-
const { size } =
|
|
28741
|
+
const cwdDb = join34(process.cwd(), "cc-claw.db");
|
|
28742
|
+
if (existsSync55(cwdDb) && !existsSync55(DB_PATH)) {
|
|
28743
|
+
const { size } = statSync12(cwdDb);
|
|
28136
28744
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
28137
28745
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
28138
28746
|
if (migrate) {
|
|
@@ -28404,7 +29012,7 @@ var init_setup = __esm({
|
|
|
28404
29012
|
"src/setup.ts"() {
|
|
28405
29013
|
"use strict";
|
|
28406
29014
|
init_paths();
|
|
28407
|
-
rl =
|
|
29015
|
+
rl = createInterface10({ input: process.stdin, output: process.stdout });
|
|
28408
29016
|
ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
28409
29017
|
bold = (s) => `\x1B[1m${s}\x1B[0m`;
|
|
28410
29018
|
green = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
@@ -28473,6 +29081,19 @@ program.command("logs").description("Tail daemon logs").option("-f, --follow", "
|
|
|
28473
29081
|
const { logsCommand: logsCommand2 } = await Promise.resolve().then(() => (init_logs(), logs_exports));
|
|
28474
29082
|
await logsCommand2(opts);
|
|
28475
29083
|
});
|
|
29084
|
+
var sessionLogs = program.command("session-logs").description("Manage session debug logs (enable via /debug in Telegram)");
|
|
29085
|
+
sessionLogs.command("list").description("List all session debug logs").action(async () => {
|
|
29086
|
+
const { sessionLogsList: sessionLogsList2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
29087
|
+
await sessionLogsList2(program.opts());
|
|
29088
|
+
});
|
|
29089
|
+
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) => {
|
|
29090
|
+
const { sessionLogsTail: sessionLogsTail2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
29091
|
+
await sessionLogsTail2(opts);
|
|
29092
|
+
});
|
|
29093
|
+
sessionLogs.command("clean").description("Remove old session logs").option("--days <n>", "Remove logs older than N days").action(async (opts) => {
|
|
29094
|
+
const { sessionLogsClean: sessionLogsClean2 } = await Promise.resolve().then(() => (init_session_logs(), session_logs_exports));
|
|
29095
|
+
await sessionLogsClean2(opts);
|
|
29096
|
+
});
|
|
28476
29097
|
var gemini = program.command("gemini").description("Manage Gemini credential slots for rotation");
|
|
28477
29098
|
gemini.command("list").description("Show all configured Gemini credential slots").action(async () => {
|
|
28478
29099
|
const { geminiList: geminiList2 } = await Promise.resolve().then(() => (init_gemini2(), gemini_exports));
|