cc-claw 0.11.1 → 0.11.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 +430 -253
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -72,7 +72,7 @@ var VERSION;
|
|
|
72
72
|
var init_version = __esm({
|
|
73
73
|
"src/version.ts"() {
|
|
74
74
|
"use strict";
|
|
75
|
-
VERSION = true ? "0.11.
|
|
75
|
+
VERSION = true ? "0.11.2" : (() => {
|
|
76
76
|
try {
|
|
77
77
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
78
78
|
} catch {
|
|
@@ -1545,6 +1545,7 @@ function initDatabase() {
|
|
|
1545
1545
|
cron TEXT,
|
|
1546
1546
|
at_time TEXT,
|
|
1547
1547
|
every_ms INTEGER,
|
|
1548
|
+
title TEXT,
|
|
1548
1549
|
description TEXT NOT NULL,
|
|
1549
1550
|
chat_id TEXT NOT NULL,
|
|
1550
1551
|
backend TEXT,
|
|
@@ -1581,6 +1582,7 @@ function initDatabase() {
|
|
|
1581
1582
|
cron TEXT,
|
|
1582
1583
|
at_time TEXT,
|
|
1583
1584
|
every_ms INTEGER,
|
|
1585
|
+
title TEXT,
|
|
1584
1586
|
description TEXT NOT NULL,
|
|
1585
1587
|
chat_id TEXT NOT NULL,
|
|
1586
1588
|
backend TEXT,
|
|
@@ -1675,6 +1677,11 @@ function initDatabase() {
|
|
|
1675
1677
|
db.exec("ALTER TABLE jobs ADD COLUMN fallbacks TEXT");
|
|
1676
1678
|
} catch {
|
|
1677
1679
|
}
|
|
1680
|
+
try {
|
|
1681
|
+
db.exec("ALTER TABLE jobs ADD COLUMN title TEXT");
|
|
1682
|
+
} catch {
|
|
1683
|
+
}
|
|
1684
|
+
backfillJobTitles(db);
|
|
1678
1685
|
}
|
|
1679
1686
|
} catch {
|
|
1680
1687
|
}
|
|
@@ -2521,14 +2528,15 @@ function getBackendUsageInWindow(backend2, windowType) {
|
|
|
2521
2528
|
}
|
|
2522
2529
|
function insertJob(params) {
|
|
2523
2530
|
const result = db.prepare(`
|
|
2524
|
-
INSERT INTO jobs (schedule_type, cron, at_time, every_ms, description, chat_id,
|
|
2531
|
+
INSERT INTO jobs (schedule_type, cron, at_time, every_ms, title, description, chat_id,
|
|
2525
2532
|
backend, model, thinking, timeout, fallbacks, session_type, channel, target, delivery_mode, timezone)
|
|
2526
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2533
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2527
2534
|
`).run(
|
|
2528
2535
|
params.scheduleType,
|
|
2529
2536
|
params.cron ?? null,
|
|
2530
2537
|
params.atTime ?? null,
|
|
2531
2538
|
params.everyMs ?? null,
|
|
2539
|
+
params.title ?? null,
|
|
2532
2540
|
params.description,
|
|
2533
2541
|
params.chatId,
|
|
2534
2542
|
params.backend ?? null,
|
|
@@ -2544,6 +2552,26 @@ function insertJob(params) {
|
|
|
2544
2552
|
);
|
|
2545
2553
|
return getJobById(Number(result.lastInsertRowid));
|
|
2546
2554
|
}
|
|
2555
|
+
function backfillJobTitles(database) {
|
|
2556
|
+
const rows = database.prepare("SELECT id, description FROM jobs WHERE title IS NULL AND active = 1").all();
|
|
2557
|
+
if (rows.length === 0) return;
|
|
2558
|
+
const preamblePatterns = [
|
|
2559
|
+
/^you\s+must\s+call\s+the\s+\w+\s+tool\b[^.]*\.\s*/i,
|
|
2560
|
+
/^important:\s*[^.]*\.\s*/i,
|
|
2561
|
+
/^always\s+use\s+[^.]*\.\s*/i,
|
|
2562
|
+
/^note:\s*[^.]*\.\s*/i
|
|
2563
|
+
];
|
|
2564
|
+
for (const row of rows) {
|
|
2565
|
+
let text = row.description;
|
|
2566
|
+
for (const pat of preamblePatterns) {
|
|
2567
|
+
text = text.replace(pat, "");
|
|
2568
|
+
}
|
|
2569
|
+
text = text.trim();
|
|
2570
|
+
const firstSentence = text.match(/^[^.!?\n]{5,60}[.!?]?/)?.[0] ?? text.slice(0, 60);
|
|
2571
|
+
const title = firstSentence.length > 60 ? firstSentence.slice(0, 57) + "\u2026" : firstSentence;
|
|
2572
|
+
database.prepare("UPDATE jobs SET title = ? WHERE id = ?").run(title, row.id);
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2547
2575
|
function mapJobRow(row) {
|
|
2548
2576
|
if (!row) return void 0;
|
|
2549
2577
|
row.fallbacks = row.fallbacks ? JSON.parse(row.fallbacks) : [];
|
|
@@ -2588,6 +2616,7 @@ function updateJob(id, fields) {
|
|
|
2588
2616
|
cron: "cron",
|
|
2589
2617
|
atTime: "at_time",
|
|
2590
2618
|
everyMs: "every_ms",
|
|
2619
|
+
title: "title",
|
|
2591
2620
|
description: "description",
|
|
2592
2621
|
backend: "backend",
|
|
2593
2622
|
model: "model",
|
|
@@ -3032,7 +3061,7 @@ var init_store5 = __esm({
|
|
|
3032
3061
|
ALL_TOOLS = ["Read", "Glob", "Grep", "Bash", "Write", "Edit", "WebFetch", "WebSearch", "Agent", "AskUserQuestion"];
|
|
3033
3062
|
JOB_SELECT = `
|
|
3034
3063
|
SELECT id, schedule_type as scheduleType, cron, at_time as atTime, every_ms as everyMs,
|
|
3035
|
-
description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3064
|
+
title, description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3036
3065
|
session_type as sessionType, channel, target, delivery_mode as deliveryMode,
|
|
3037
3066
|
timezone, enabled, active, created_at as createdAt, last_run_at as lastRunAt,
|
|
3038
3067
|
next_run_at as nextRunAt, consecutive_failures as consecutiveFailures
|
|
@@ -6566,8 +6595,45 @@ __export(analyze_exports, {
|
|
|
6566
6595
|
});
|
|
6567
6596
|
import { spawn as spawn4 } from "child_process";
|
|
6568
6597
|
import { createInterface as createInterface3 } from "readline";
|
|
6569
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
6598
|
+
import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
6570
6599
|
import { join as join10 } from "path";
|
|
6600
|
+
import { homedir as homedir4 } from "os";
|
|
6601
|
+
function discoverReflectionTargets() {
|
|
6602
|
+
const ccClawHome = join10(homedir4(), ".cc-claw");
|
|
6603
|
+
const targets = [];
|
|
6604
|
+
try {
|
|
6605
|
+
const skillsDir = join10(ccClawHome, "workspace", "skills");
|
|
6606
|
+
if (existsSync11(skillsDir)) {
|
|
6607
|
+
for (const entry of readdirSync5(skillsDir)) {
|
|
6608
|
+
const entryPath = join10(skillsDir, entry);
|
|
6609
|
+
if (!statSync3(entryPath).isDirectory()) continue;
|
|
6610
|
+
const skillFile = join10(entryPath, "SKILL.md");
|
|
6611
|
+
if (!existsSync11(skillFile)) continue;
|
|
6612
|
+
let desc = "skill";
|
|
6613
|
+
try {
|
|
6614
|
+
const content = readFileSync6(skillFile, "utf-8").slice(0, 500);
|
|
6615
|
+
const descMatch = content.match(/description:\s*["']?([^"'\n]+)/);
|
|
6616
|
+
if (descMatch) desc = descMatch[1].trim().slice(0, 80);
|
|
6617
|
+
} catch {
|
|
6618
|
+
}
|
|
6619
|
+
targets.push({ path: `workspace/skills/${entry}/SKILL.md`, description: desc });
|
|
6620
|
+
}
|
|
6621
|
+
}
|
|
6622
|
+
} catch {
|
|
6623
|
+
}
|
|
6624
|
+
try {
|
|
6625
|
+
const contextDir = join10(ccClawHome, "workspace", "context");
|
|
6626
|
+
if (existsSync11(contextDir)) {
|
|
6627
|
+
for (const entry of readdirSync5(contextDir)) {
|
|
6628
|
+
if (!entry.endsWith(".md")) continue;
|
|
6629
|
+
const name = entry.replace(/\.md$/, "");
|
|
6630
|
+
targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
} catch {
|
|
6634
|
+
}
|
|
6635
|
+
return targets;
|
|
6636
|
+
}
|
|
6571
6637
|
function buildAnalysisPrompt(params) {
|
|
6572
6638
|
const {
|
|
6573
6639
|
signals,
|
|
@@ -6627,7 +6693,31 @@ ${categoryList}`);
|
|
|
6627
6693
|
sections.push(`- [#${ins.id}] (${ins.category}) ${ins.insight}`);
|
|
6628
6694
|
}
|
|
6629
6695
|
}
|
|
6630
|
-
const
|
|
6696
|
+
const { availableTargets } = params;
|
|
6697
|
+
const targetList = [
|
|
6698
|
+
"identity/SOUL.md \u2014 personality, tone, stable behavioral rules, communication style",
|
|
6699
|
+
"identity/USER.md \u2014 user preferences, personal info, timezone, language, profile"
|
|
6700
|
+
];
|
|
6701
|
+
if (availableTargets) {
|
|
6702
|
+
for (const t of availableTargets) {
|
|
6703
|
+
targetList.push(`${t.path} \u2014 ${t.description}`);
|
|
6704
|
+
}
|
|
6705
|
+
}
|
|
6706
|
+
if (codebaseEnabled) {
|
|
6707
|
+
targetList.push("codebase \u2014 code-level recommendation (advisory only)");
|
|
6708
|
+
}
|
|
6709
|
+
sections.push(`[Target File Routing]
|
|
6710
|
+
Available targets:
|
|
6711
|
+
${targetList.map((t) => `- ${t}`).join("\n")}
|
|
6712
|
+
|
|
6713
|
+
Choose the MOST SPECIFIC target for each insight:
|
|
6714
|
+
- Workflow or process improvements \u2192 the relevant skill file
|
|
6715
|
+
- Tool usage patterns or domain-specific steps \u2192 the relevant skill file
|
|
6716
|
+
- User preference or profile info \u2192 USER.md
|
|
6717
|
+
- Personality, tone, general behavior \u2192 SOUL.md
|
|
6718
|
+
- Domain knowledge or reference material \u2192 a context file
|
|
6719
|
+
- If no matching skill/context file exists, fall back to SOUL.md or USER.md`);
|
|
6720
|
+
const targetOptions = targetList.map((t) => t.split(" \u2014 ")[0]).join(" | ");
|
|
6631
6721
|
sections.push(`[Output Format]
|
|
6632
6722
|
For each insight, output EXACTLY this format. Separate multiple insights with "---" on its own line.
|
|
6633
6723
|
|
|
@@ -6823,6 +6913,7 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6823
6913
|
const applied = getAppliedInsights(db3, chatId);
|
|
6824
6914
|
const rejected = getRejectedInsights(db3, chatId);
|
|
6825
6915
|
const codebaseEnabled = process.env.REFLECTION_CODEBASE_RECOMMENDATIONS === "1";
|
|
6916
|
+
const availableTargets = discoverReflectionTargets();
|
|
6826
6917
|
const prompt = buildAnalysisPrompt({
|
|
6827
6918
|
signals: signals.map((s) => ({
|
|
6828
6919
|
signalType: s.signalType,
|
|
@@ -6844,7 +6935,8 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6844
6935
|
insight: i.insight,
|
|
6845
6936
|
category: i.category
|
|
6846
6937
|
})),
|
|
6847
|
-
codebaseEnabled
|
|
6938
|
+
codebaseEnabled,
|
|
6939
|
+
availableTargets
|
|
6848
6940
|
});
|
|
6849
6941
|
const resolved = resolveReflectionAdapter(chatId);
|
|
6850
6942
|
if (!resolved) {
|
|
@@ -6948,7 +7040,7 @@ __export(apply_exports, {
|
|
|
6948
7040
|
isTargetAllowed: () => isTargetAllowed,
|
|
6949
7041
|
rollbackInsight: () => rollbackInsight
|
|
6950
7042
|
});
|
|
6951
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as
|
|
7043
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync3 } from "fs";
|
|
6952
7044
|
import { join as join11, dirname as dirname2 } from "path";
|
|
6953
7045
|
function isTargetAllowed(relativePath) {
|
|
6954
7046
|
if (relativePath.includes("..")) return false;
|
|
@@ -7016,7 +7108,7 @@ async function applyInsight(insightId) {
|
|
|
7016
7108
|
}
|
|
7017
7109
|
const absolutePath = join11(CC_CLAW_HOME, insight.targetFile);
|
|
7018
7110
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
7019
|
-
if (
|
|
7111
|
+
if (existsSync12(absolutePath)) {
|
|
7020
7112
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
7021
7113
|
const lineCount = currentContent.split("\n").length;
|
|
7022
7114
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
@@ -7036,7 +7128,7 @@ async function applyInsight(insightId) {
|
|
|
7036
7128
|
};
|
|
7037
7129
|
}
|
|
7038
7130
|
let original = "";
|
|
7039
|
-
if (
|
|
7131
|
+
if (existsSync12(absolutePath)) {
|
|
7040
7132
|
original = readFileSync7(absolutePath, "utf-8");
|
|
7041
7133
|
} else if (insight.proposedAction !== "create") {
|
|
7042
7134
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
@@ -7045,7 +7137,7 @@ async function applyInsight(insightId) {
|
|
|
7045
7137
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
7046
7138
|
try {
|
|
7047
7139
|
const parentDir = dirname2(absolutePath);
|
|
7048
|
-
if (!
|
|
7140
|
+
if (!existsSync12(parentDir)) {
|
|
7049
7141
|
mkdirSync3(parentDir, { recursive: true });
|
|
7050
7142
|
}
|
|
7051
7143
|
if (original) {
|
|
@@ -7151,7 +7243,7 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
7151
7243
|
if (!baseline) return 0;
|
|
7152
7244
|
let current = "";
|
|
7153
7245
|
try {
|
|
7154
|
-
if (
|
|
7246
|
+
if (existsSync12(absolutePath)) {
|
|
7155
7247
|
current = readFileSync7(absolutePath, "utf-8");
|
|
7156
7248
|
}
|
|
7157
7249
|
} catch {
|
|
@@ -7203,7 +7295,7 @@ __export(server_exports, {
|
|
|
7203
7295
|
});
|
|
7204
7296
|
import { createServer } from "http";
|
|
7205
7297
|
import { randomBytes } from "crypto";
|
|
7206
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as
|
|
7298
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync13 } from "fs";
|
|
7207
7299
|
function createSubAgentToken(agentId) {
|
|
7208
7300
|
const token = `sub:${agentId.slice(0, 8)}:${randomBytes(16).toString("hex")}`;
|
|
7209
7301
|
subAgentTokens.set(token, agentId);
|
|
@@ -7374,7 +7466,7 @@ function startDashboard() {
|
|
|
7374
7466
|
if (url.pathname === "/api/orchestrator/spawn" && req.method === "POST") {
|
|
7375
7467
|
try {
|
|
7376
7468
|
const body = JSON.parse(await readBody(req));
|
|
7377
|
-
if (body.cwd && !
|
|
7469
|
+
if (body.cwd && !existsSync13(body.cwd)) {
|
|
7378
7470
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
7379
7471
|
}
|
|
7380
7472
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -9674,18 +9766,18 @@ var init_wrap_backend = __esm({
|
|
|
9674
9766
|
});
|
|
9675
9767
|
|
|
9676
9768
|
// src/agents/runners/config-loader.ts
|
|
9677
|
-
import { readFileSync as readFileSync8, readdirSync as
|
|
9769
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync6, existsSync as existsSync14, mkdirSync as mkdirSync5, watchFile, unwatchFile } from "fs";
|
|
9678
9770
|
import { join as join13 } from "path";
|
|
9679
9771
|
import { execFileSync } from "child_process";
|
|
9680
9772
|
function resolveExecutable(config2) {
|
|
9681
|
-
if (
|
|
9773
|
+
if (existsSync14(config2.executable)) return config2.executable;
|
|
9682
9774
|
try {
|
|
9683
9775
|
return execFileSync("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
9684
9776
|
} catch {
|
|
9685
9777
|
}
|
|
9686
9778
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
9687
9779
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
9688
|
-
if (
|
|
9780
|
+
if (existsSync14(resolved)) return resolved;
|
|
9689
9781
|
}
|
|
9690
9782
|
return config2.executable;
|
|
9691
9783
|
}
|
|
@@ -9824,11 +9916,11 @@ function loadRunnerConfig(filePath) {
|
|
|
9824
9916
|
}
|
|
9825
9917
|
}
|
|
9826
9918
|
function loadAllRunnerConfigs() {
|
|
9827
|
-
if (!
|
|
9919
|
+
if (!existsSync14(RUNNERS_PATH)) {
|
|
9828
9920
|
mkdirSync5(RUNNERS_PATH, { recursive: true });
|
|
9829
9921
|
return [];
|
|
9830
9922
|
}
|
|
9831
|
-
const files =
|
|
9923
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9832
9924
|
const configs = [];
|
|
9833
9925
|
for (const file of files) {
|
|
9834
9926
|
const config2 = loadRunnerConfig(join13(RUNNERS_PATH, file));
|
|
@@ -9852,14 +9944,14 @@ function registerConfigRunners() {
|
|
|
9852
9944
|
return count;
|
|
9853
9945
|
}
|
|
9854
9946
|
function watchRunnerConfigs(onChange) {
|
|
9855
|
-
if (!
|
|
9947
|
+
if (!existsSync14(RUNNERS_PATH)) return;
|
|
9856
9948
|
for (const prev of watchedFiles) {
|
|
9857
|
-
if (!
|
|
9949
|
+
if (!existsSync14(prev)) {
|
|
9858
9950
|
unwatchFile(prev);
|
|
9859
9951
|
watchedFiles.delete(prev);
|
|
9860
9952
|
}
|
|
9861
9953
|
}
|
|
9862
|
-
const files =
|
|
9954
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9863
9955
|
for (const file of files) {
|
|
9864
9956
|
const fullPath = join13(RUNNERS_PATH, file);
|
|
9865
9957
|
if (watchedFiles.has(fullPath)) continue;
|
|
@@ -10568,7 +10660,7 @@ __export(discover_exports, {
|
|
|
10568
10660
|
});
|
|
10569
10661
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
10570
10662
|
import { createHash } from "crypto";
|
|
10571
|
-
import { homedir as
|
|
10663
|
+
import { homedir as homedir5 } from "os";
|
|
10572
10664
|
import { join as join14 } from "path";
|
|
10573
10665
|
function invalidateSkillCache() {
|
|
10574
10666
|
cachedSkills = null;
|
|
@@ -10587,7 +10679,7 @@ async function discoverAllSkills() {
|
|
|
10587
10679
|
const rawSkills = [];
|
|
10588
10680
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
10589
10681
|
for (const backendId of getAllBackendIds()) {
|
|
10590
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(
|
|
10682
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(homedir5(), `.${backendId}`, "skills")];
|
|
10591
10683
|
for (const dir of dirs) {
|
|
10592
10684
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
10593
10685
|
}
|
|
@@ -10718,15 +10810,15 @@ var init_discover = __esm({
|
|
|
10718
10810
|
init_backends();
|
|
10719
10811
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
10720
10812
|
BACKEND_SKILL_DIRS = {
|
|
10721
|
-
claude: [join14(
|
|
10722
|
-
gemini: [join14(
|
|
10813
|
+
claude: [join14(homedir5(), ".claude", "skills")],
|
|
10814
|
+
gemini: [join14(homedir5(), ".gemini", "skills")],
|
|
10723
10815
|
codex: [
|
|
10724
|
-
join14(
|
|
10725
|
-
join14(
|
|
10816
|
+
join14(homedir5(), ".agents", "skills"),
|
|
10817
|
+
join14(homedir5(), ".codex", "skills")
|
|
10726
10818
|
],
|
|
10727
10819
|
cursor: [
|
|
10728
|
-
join14(
|
|
10729
|
-
join14(
|
|
10820
|
+
join14(homedir5(), ".cursor", "skills"),
|
|
10821
|
+
join14(homedir5(), ".cursor", "skills-cursor")
|
|
10730
10822
|
]
|
|
10731
10823
|
};
|
|
10732
10824
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -10742,7 +10834,7 @@ __export(install_exports, {
|
|
|
10742
10834
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
10743
10835
|
});
|
|
10744
10836
|
import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
|
|
10745
|
-
import { existsSync as
|
|
10837
|
+
import { existsSync as existsSync15 } from "fs";
|
|
10746
10838
|
import { join as join15, basename } from "path";
|
|
10747
10839
|
import { execSync as execSync6 } from "child_process";
|
|
10748
10840
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
@@ -10761,7 +10853,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10761
10853
|
stdio: "pipe",
|
|
10762
10854
|
timeout: 3e4
|
|
10763
10855
|
});
|
|
10764
|
-
if (!
|
|
10856
|
+
if (!existsSync15(join15(tmpDir, ".git"))) {
|
|
10765
10857
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
10766
10858
|
}
|
|
10767
10859
|
const searchRoot = subPath ? join15(tmpDir, subPath) : tmpDir;
|
|
@@ -10771,7 +10863,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10771
10863
|
}
|
|
10772
10864
|
const skillFolderName = basename(skillDir);
|
|
10773
10865
|
const destDir = join15(SKILLS_PATH, skillFolderName);
|
|
10774
|
-
if (
|
|
10866
|
+
if (existsSync15(destDir)) {
|
|
10775
10867
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
10776
10868
|
}
|
|
10777
10869
|
await mkdir(destDir, { recursive: true });
|
|
@@ -10818,14 +10910,14 @@ function parseGitHubUrl(input) {
|
|
|
10818
10910
|
async function findSkillDir(root) {
|
|
10819
10911
|
const candidates = ["SKILL.md", "skill.md"];
|
|
10820
10912
|
for (const c of candidates) {
|
|
10821
|
-
if (
|
|
10913
|
+
if (existsSync15(join15(root, c))) return root;
|
|
10822
10914
|
}
|
|
10823
10915
|
try {
|
|
10824
10916
|
const entries = await readdir2(root, { withFileTypes: true });
|
|
10825
10917
|
for (const entry of entries) {
|
|
10826
10918
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
10827
10919
|
for (const c of candidates) {
|
|
10828
|
-
if (
|
|
10920
|
+
if (existsSync15(join15(root, entry.name, c))) {
|
|
10829
10921
|
return join15(root, entry.name);
|
|
10830
10922
|
}
|
|
10831
10923
|
}
|
|
@@ -10845,7 +10937,7 @@ async function findSkillDir(root) {
|
|
|
10845
10937
|
for (const sub of subEntries) {
|
|
10846
10938
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
10847
10939
|
for (const c of candidates) {
|
|
10848
|
-
if (
|
|
10940
|
+
if (existsSync15(join15(root, entry.name, sub.name, c))) {
|
|
10849
10941
|
return join15(root, entry.name, sub.name);
|
|
10850
10942
|
}
|
|
10851
10943
|
}
|
|
@@ -10864,7 +10956,7 @@ var init_install = __esm({
|
|
|
10864
10956
|
});
|
|
10865
10957
|
|
|
10866
10958
|
// src/bootstrap/profile.ts
|
|
10867
|
-
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as
|
|
10959
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync16 } from "fs";
|
|
10868
10960
|
import { join as join16 } from "path";
|
|
10869
10961
|
function hasActiveProfile(chatId) {
|
|
10870
10962
|
return activeProfiles.has(chatId);
|
|
@@ -10994,7 +11086,7 @@ function extractUserUpdates(text) {
|
|
|
10994
11086
|
return { cleanText, updates };
|
|
10995
11087
|
}
|
|
10996
11088
|
function appendToUserProfile(key, value) {
|
|
10997
|
-
if (!
|
|
11089
|
+
if (!existsSync16(USER_PATH2)) return;
|
|
10998
11090
|
const content = readFileSync9(USER_PATH2, "utf-8");
|
|
10999
11091
|
const line = `- **${key}**: ${value}`;
|
|
11000
11092
|
if (content.includes(line)) return;
|
|
@@ -11016,7 +11108,7 @@ var init_profile = __esm({
|
|
|
11016
11108
|
});
|
|
11017
11109
|
|
|
11018
11110
|
// src/bootstrap/heartbeat.ts
|
|
11019
|
-
import { readFileSync as readFileSync10, existsSync as
|
|
11111
|
+
import { readFileSync as readFileSync10, existsSync as existsSync17 } from "fs";
|
|
11020
11112
|
import { join as join17 } from "path";
|
|
11021
11113
|
function initHeartbeat(channelReg) {
|
|
11022
11114
|
registry2 = channelReg;
|
|
@@ -11155,7 +11247,7 @@ ${healthLines.join("\n")}`);
|
|
|
11155
11247
|
sections.push(`[Active watches]
|
|
11156
11248
|
${watchLines.join("\n")}`);
|
|
11157
11249
|
}
|
|
11158
|
-
if (
|
|
11250
|
+
if (existsSync17(HEARTBEAT_MD_PATH)) {
|
|
11159
11251
|
try {
|
|
11160
11252
|
const custom = readFileSync10(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
11161
11253
|
if (custom) {
|
|
@@ -11386,7 +11478,7 @@ var init_classify = __esm({
|
|
|
11386
11478
|
});
|
|
11387
11479
|
|
|
11388
11480
|
// src/media/image-gen.ts
|
|
11389
|
-
import { mkdirSync as mkdirSync6, existsSync as
|
|
11481
|
+
import { mkdirSync as mkdirSync6, existsSync as existsSync18 } from "fs";
|
|
11390
11482
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
11391
11483
|
import { join as join18 } from "path";
|
|
11392
11484
|
async function generateImage(prompt) {
|
|
@@ -11435,7 +11527,7 @@ async function generateImage(prompt) {
|
|
|
11435
11527
|
if (!imageData) {
|
|
11436
11528
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
11437
11529
|
}
|
|
11438
|
-
if (!
|
|
11530
|
+
if (!existsSync18(IMAGE_OUTPUT_DIR)) {
|
|
11439
11531
|
mkdirSync6(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
11440
11532
|
}
|
|
11441
11533
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
@@ -12166,11 +12258,31 @@ async function finalizeJob(chatId, channel) {
|
|
|
12166
12258
|
const pending = pendingJobs.get(chatId);
|
|
12167
12259
|
if (!pending) return;
|
|
12168
12260
|
const editJobId = pending._editJobId;
|
|
12261
|
+
let title = pending.title ?? null;
|
|
12262
|
+
if (!title && !editJobId) {
|
|
12263
|
+
try {
|
|
12264
|
+
const { askAgent: askAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
12265
|
+
const resp = await askAgent2(chatId, `Summarize this scheduled task in 5-8 words for a job list title. Output ONLY the title, nothing else:
|
|
12266
|
+
|
|
12267
|
+
${pending.task}`, {
|
|
12268
|
+
bootstrapTier: "chat",
|
|
12269
|
+
maxTurns: 1,
|
|
12270
|
+
timeoutMs: 15e3
|
|
12271
|
+
});
|
|
12272
|
+
const generated = resp.text?.trim().replace(/^["']|["']$/g, "");
|
|
12273
|
+
if (generated && generated.length <= 60) title = generated;
|
|
12274
|
+
} catch {
|
|
12275
|
+
}
|
|
12276
|
+
if (!title) {
|
|
12277
|
+
title = pending.task.length > 60 ? pending.task.slice(0, 57) + "\u2026" : pending.task;
|
|
12278
|
+
}
|
|
12279
|
+
}
|
|
12169
12280
|
const jobParams = {
|
|
12170
12281
|
scheduleType: pending.scheduleType ?? "cron",
|
|
12171
12282
|
cron: pending.cron,
|
|
12172
12283
|
atTime: pending.at ?? null,
|
|
12173
12284
|
everyMs: pending.everyMs ?? null,
|
|
12285
|
+
title,
|
|
12174
12286
|
description: pending.task,
|
|
12175
12287
|
backend: pending.backend ?? null,
|
|
12176
12288
|
model: pending.model ?? null,
|
|
@@ -12194,6 +12306,7 @@ async function finalizeJob(chatId, channel) {
|
|
|
12194
12306
|
chatId,
|
|
12195
12307
|
`Job #${editJobId} updated!
|
|
12196
12308
|
|
|
12309
|
+
Title: ${jobParams.title ?? "\u2014"}
|
|
12197
12310
|
Task: ${jobParams.description}
|
|
12198
12311
|
Schedule: ${jobParams.cron ?? "N/A"}
|
|
12199
12312
|
Timezone: ${jobParams.timezone}`,
|
|
@@ -12208,6 +12321,7 @@ Timezone: ${jobParams.timezone}`,
|
|
|
12208
12321
|
chatId,
|
|
12209
12322
|
`Job #${job.id} created!
|
|
12210
12323
|
|
|
12324
|
+
Title: ${job.title ?? "\u2014"}
|
|
12211
12325
|
Task: ${job.description}
|
|
12212
12326
|
Schedule: ${job.cron ?? "N/A"}
|
|
12213
12327
|
Timezone: ${job.timezone}
|
|
@@ -12808,8 +12922,10 @@ var init_propose = __esm({
|
|
|
12808
12922
|
|
|
12809
12923
|
// src/router.ts
|
|
12810
12924
|
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
|
|
12925
|
+
import { existsSync as existsSync19 } from "fs";
|
|
12811
12926
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
12812
12927
|
import { resolve as resolvePath, join as join19 } from "path";
|
|
12928
|
+
import { homedir as homedir6 } from "os";
|
|
12813
12929
|
function parseMcpListOutput(output2) {
|
|
12814
12930
|
const results = [];
|
|
12815
12931
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14527,8 +14643,8 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14527
14643
|
lines.push(` \u2705 <b>cc-claw</b> <i>Agent orchestrator (spawn, tasks, inbox)</i>`);
|
|
14528
14644
|
}
|
|
14529
14645
|
const { execFile: execFile5 } = await import("child_process");
|
|
14530
|
-
const { homedir:
|
|
14531
|
-
const discoveryCwd =
|
|
14646
|
+
const { homedir: homedir9 } = await import("os");
|
|
14647
|
+
const discoveryCwd = homedir9();
|
|
14532
14648
|
const runnerResults = await Promise.allSettled(
|
|
14533
14649
|
getAllRunners().map((runner) => {
|
|
14534
14650
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -14911,26 +15027,6 @@ async function handleText(msg, channel) {
|
|
|
14911
15027
|
await handleWizardText(chatId, text, channel);
|
|
14912
15028
|
return;
|
|
14913
15029
|
}
|
|
14914
|
-
const discussingInsightId = activeProposalDiscussion.get(chatId);
|
|
14915
|
-
if (discussingInsightId !== void 0) {
|
|
14916
|
-
if (text.toLowerCase() === "done") {
|
|
14917
|
-
activeProposalDiscussion.delete(chatId);
|
|
14918
|
-
const { getInsightById: getInsightById2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
14919
|
-
const { formatProposalCard: formatProposalCard2, buildProposalKeyboard: buildProposalKeyboard2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
14920
|
-
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
14921
|
-
const insight = getInsightById2(getDb2(), discussingInsightId);
|
|
14922
|
-
if (insight && insight.status === "pending") {
|
|
14923
|
-
const card = formatProposalCard2(insight);
|
|
14924
|
-
const kb = buildProposalKeyboard2(insight.id, insight.category);
|
|
14925
|
-
await channel.sendKeyboard(chatId, "Discussion complete. Updated proposal:\n\n" + card, kb);
|
|
14926
|
-
} else {
|
|
14927
|
-
await channel.sendText(chatId, "Discussion ended.", { parseMode: "plain" });
|
|
14928
|
-
}
|
|
14929
|
-
return;
|
|
14930
|
-
}
|
|
14931
|
-
await handleProposalDiscussion(chatId, discussingInsightId, text, channel);
|
|
14932
|
-
return;
|
|
14933
|
-
}
|
|
14934
15030
|
const rememberMatch = text.match(/^remember\s+(?:that\s+)?(.+)/i);
|
|
14935
15031
|
if (rememberMatch) {
|
|
14936
15032
|
const content = rememberMatch[1];
|
|
@@ -15158,65 +15254,6 @@ After installing, restart the service: cc-claw service restart`;
|
|
|
15158
15254
|
}
|
|
15159
15255
|
return `Error: ${msg}`;
|
|
15160
15256
|
}
|
|
15161
|
-
async function handleProposalDiscussion(chatId, insightId, userQuestion, channel) {
|
|
15162
|
-
const { getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15163
|
-
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
15164
|
-
const insight = getInsightById2(getDb2(), insightId);
|
|
15165
|
-
if (!insight) {
|
|
15166
|
-
activeProposalDiscussion.delete(chatId);
|
|
15167
|
-
await channel.sendText(chatId, "Proposal not found. Discussion ended.", { parseMode: "plain" });
|
|
15168
|
-
return;
|
|
15169
|
-
}
|
|
15170
|
-
const prompt = [
|
|
15171
|
-
`You are reviewing a self-learning proposal with the user. They want to discuss it before deciding whether to apply, modify, or reject it.`,
|
|
15172
|
-
``,
|
|
15173
|
-
`Current proposal:`,
|
|
15174
|
-
`- Category: ${insight.category}`,
|
|
15175
|
-
`- Insight: ${insight.insight}`,
|
|
15176
|
-
`- Why: ${insight.why ?? "not specified"}`,
|
|
15177
|
-
`- Target file: ${insight.targetFile ?? "not specified"}`,
|
|
15178
|
-
`- Proposed action: ${insight.proposedAction ?? "not specified"}`,
|
|
15179
|
-
`- Proposed diff: ${insight.proposedDiff ?? "none"}`,
|
|
15180
|
-
`- Confidence: ${Math.round(insight.confidence * 100)}%`,
|
|
15181
|
-
``,
|
|
15182
|
-
`The user asks: "${userQuestion}"`,
|
|
15183
|
-
``,
|
|
15184
|
-
`Answer their question honestly. If they suggest retargeting to a different file or modifying the proposal, agree if it makes sense and output one of these markers:`,
|
|
15185
|
-
`- [RETARGET:filepath] \u2014 to change the target file (e.g., [RETARGET:skills/newsroom/SKILL.md])`,
|
|
15186
|
-
`- [REVISE_DIFF:new diff text] \u2014 to update the proposed change`,
|
|
15187
|
-
`- [REVISE_ACTION:action] \u2014 to change the action type (append/replace/etc.)`,
|
|
15188
|
-
``,
|
|
15189
|
-
`Only output markers when the user explicitly asks for a change. Otherwise just discuss.`,
|
|
15190
|
-
`Keep responses concise \u2014 this is a quick review conversation, not an essay.`
|
|
15191
|
-
].join("\n");
|
|
15192
|
-
try {
|
|
15193
|
-
await channel.sendTyping?.(chatId);
|
|
15194
|
-
const response = await askAgent(chatId, prompt, {
|
|
15195
|
-
bootstrapTier: "chat",
|
|
15196
|
-
maxTurns: 1,
|
|
15197
|
-
timeoutMs: 6e4
|
|
15198
|
-
});
|
|
15199
|
-
const responseText = response.text ?? "";
|
|
15200
|
-
const retargetMatch = responseText.match(/\[RETARGET:([^\]]+)\]/);
|
|
15201
|
-
const reviseDiffMatch = responseText.match(/\[REVISE_DIFF:([^\]]+)\]/);
|
|
15202
|
-
const reviseActionMatch = responseText.match(/\[REVISE_ACTION:([^\]]+)\]/);
|
|
15203
|
-
if (retargetMatch || reviseDiffMatch || reviseActionMatch) {
|
|
15204
|
-
const newTarget = retargetMatch?.[1]?.trim() ?? insight.targetFile ?? "";
|
|
15205
|
-
const newDiff = reviseDiffMatch?.[1]?.trim() ?? insight.proposedDiff ?? null;
|
|
15206
|
-
const newAction = reviseActionMatch?.[1]?.trim() ?? insight.proposedAction ?? null;
|
|
15207
|
-
updateInsightProposal2(getDb2(), insightId, newTarget, newDiff, newAction);
|
|
15208
|
-
}
|
|
15209
|
-
const cleanText = responseText.replace(/\[RETARGET:[^\]]+\]/g, "").replace(/\[REVISE_DIFF:[^\]]+\]/g, "").replace(/\[REVISE_ACTION:[^\]]+\]/g, "").trim();
|
|
15210
|
-
if (cleanText) {
|
|
15211
|
-
await channel.sendText(chatId, cleanText);
|
|
15212
|
-
}
|
|
15213
|
-
await channel.sendKeyboard(chatId, "Continue discussing, or type 'done' to finish.", [
|
|
15214
|
-
[{ label: "Done \u2014 show updated proposal", data: `evolve:discuss-done:${insightId}` }]
|
|
15215
|
-
]);
|
|
15216
|
-
} catch (err) {
|
|
15217
|
-
await channel.sendText(chatId, `Discussion error: ${err.message}`, { parseMode: "plain" });
|
|
15218
|
-
}
|
|
15219
|
-
}
|
|
15220
15257
|
async function handleSideQuest(parentChatId, msg, channel) {
|
|
15221
15258
|
const sqId = `sq:${parentChatId}:${randomUUID3()}`;
|
|
15222
15259
|
const active = activeSideQuests.get(parentChatId) ?? /* @__PURE__ */ new Set();
|
|
@@ -15791,7 +15828,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15791
15828
|
pageSize: 10,
|
|
15792
15829
|
callbackPrefix: "job:",
|
|
15793
15830
|
renderItem: (j) => ({
|
|
15794
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15831
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15795
15832
|
data: `job:view:${j.id}`,
|
|
15796
15833
|
style: "primary"
|
|
15797
15834
|
}),
|
|
@@ -15801,7 +15838,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15801
15838
|
for (const j of pageJobs) {
|
|
15802
15839
|
const emoji = getJobStatusEmoji(j);
|
|
15803
15840
|
const schedule2 = getJobScheduleText(j);
|
|
15804
|
-
const desc = j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description;
|
|
15841
|
+
const desc = j.title ?? (j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description);
|
|
15805
15842
|
lines.push(`${emoji} ${desc} \xB7 ${schedule2}`);
|
|
15806
15843
|
}
|
|
15807
15844
|
lines.push("");
|
|
@@ -15836,8 +15873,9 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15836
15873
|
const runs = getJobRuns(jobId, 1);
|
|
15837
15874
|
const lastRunStatus = runs.length > 0 ? runs[0].status : null;
|
|
15838
15875
|
const lines = [
|
|
15839
|
-
`Job #${job.id}: ${job.description}`,
|
|
15876
|
+
`Job #${job.id}: ${job.title ?? job.description}`,
|
|
15840
15877
|
buildSectionHeader("", 22),
|
|
15878
|
+
...job.title ? [`Task: ${job.description.length > 80 ? job.description.slice(0, 77) + "\u2026" : job.description}`] : [],
|
|
15841
15879
|
`Runs: ${schedule2}${tz}`,
|
|
15842
15880
|
`Backend: ${backend2} | Model: ${model2}`,
|
|
15843
15881
|
`Last run: ${lastRun}${lastRunStatus ? ` (${lastRunStatus})` : ""}`,
|
|
@@ -15944,7 +15982,7 @@ async function sendJobPicker(chatId, channel, action) {
|
|
|
15944
15982
|
const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
|
|
15945
15983
|
const style = action === "run" ? "success" : action === "cancel" ? "danger" : void 0;
|
|
15946
15984
|
const buttons = jobs.map((j) => [{
|
|
15947
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15985
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15948
15986
|
data: action === "cancel" ? `job:cancel:${j.id}` : `job:${action}:${j.id}`,
|
|
15949
15987
|
...style ? { style } : {}
|
|
15950
15988
|
}]);
|
|
@@ -16602,24 +16640,159 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16602
16640
|
}
|
|
16603
16641
|
case "discuss": {
|
|
16604
16642
|
const insId = parseInt(idStr, 10);
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16643
|
+
await channel.sendKeyboard(chatId, [
|
|
16644
|
+
"What would you like to do with this proposal?",
|
|
16645
|
+
"",
|
|
16646
|
+
"Why this file? \u2014 ask the AI to explain its reasoning",
|
|
16647
|
+
"Retarget \u2014 move this change to a different file (e.g., a skill instead of SOUL.md)",
|
|
16648
|
+
"Revise \u2014 ask the AI to rewrite the proposed change"
|
|
16649
|
+
].join("\n"), [
|
|
16650
|
+
[
|
|
16651
|
+
{ label: "Why this file?", data: `evolve:discuss-why:${insId}`, style: "primary" },
|
|
16652
|
+
{ label: "Retarget", data: `evolve:discuss-retarget:${insId}` }
|
|
16653
|
+
],
|
|
16654
|
+
[
|
|
16655
|
+
{ label: "Revise the change", data: `evolve:discuss-revise:${insId}` },
|
|
16656
|
+
{ label: "Back", data: `evolve:discuss-back:${insId}` }
|
|
16657
|
+
]
|
|
16608
16658
|
]);
|
|
16609
16659
|
break;
|
|
16610
16660
|
}
|
|
16611
|
-
case "discuss-
|
|
16612
|
-
|
|
16613
|
-
const {
|
|
16614
|
-
const
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16661
|
+
case "discuss-why": {
|
|
16662
|
+
const { getInsightById: gwIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16663
|
+
const { getDb: gwDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16664
|
+
const gwInsight = gwIns(gwDb(), parseInt(idStr, 10));
|
|
16665
|
+
if (!gwInsight) {
|
|
16666
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16667
|
+
break;
|
|
16668
|
+
}
|
|
16669
|
+
await channel.sendTyping?.(chatId);
|
|
16670
|
+
const whyPrompt = [
|
|
16671
|
+
`Explain in 2-3 sentences why you chose "${gwInsight.targetFile}" as the target file for this insight:`,
|
|
16672
|
+
`"${gwInsight.insight}"`,
|
|
16673
|
+
`Consider what other files could work (skills, context files, USER.md) and explain your reasoning.`
|
|
16674
|
+
].join("\n");
|
|
16675
|
+
try {
|
|
16676
|
+
const whyResp = await askAgent(chatId, whyPrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
|
|
16677
|
+
await channel.sendText(chatId, whyResp.text ?? "No response.");
|
|
16678
|
+
} catch (e) {
|
|
16679
|
+
await channel.sendText(chatId, `Error: ${e.message}`, { parseMode: "plain" });
|
|
16680
|
+
}
|
|
16681
|
+
await channel.sendKeyboard(chatId, "What next?", [
|
|
16682
|
+
[
|
|
16683
|
+
{ label: "OK, Apply", data: `evolve:apply:${idStr}`, style: "success" },
|
|
16684
|
+
{ label: "Retarget instead", data: `evolve:discuss-retarget:${idStr}` }
|
|
16685
|
+
],
|
|
16686
|
+
[
|
|
16687
|
+
{ label: "Reject", data: `evolve:reject:${idStr}`, style: "danger" },
|
|
16688
|
+
{ label: "Back", data: `evolve:discuss-back:${idStr}` }
|
|
16689
|
+
]
|
|
16690
|
+
]);
|
|
16691
|
+
break;
|
|
16692
|
+
}
|
|
16693
|
+
case "discuss-retarget": {
|
|
16694
|
+
const { getInsightById: rtIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16695
|
+
const { getDb: rtDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16696
|
+
const rtInsight = rtIns(rtDb(), parseInt(idStr, 10));
|
|
16697
|
+
if (!rtInsight) {
|
|
16698
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16699
|
+
break;
|
|
16700
|
+
}
|
|
16701
|
+
const currentTarget = rtInsight.targetFile ?? "unknown";
|
|
16702
|
+
const targets = [
|
|
16703
|
+
{ label: "SOUL.md", path: "identity/SOUL.md" },
|
|
16704
|
+
{ label: "USER.md", path: "identity/USER.md" }
|
|
16705
|
+
];
|
|
16706
|
+
const skillDirs = [
|
|
16707
|
+
join19(homedir6(), ".cc-claw", "workspace", "skills")
|
|
16708
|
+
];
|
|
16709
|
+
try {
|
|
16710
|
+
const { readdirSync: readdirSync7, statSync: statSync9 } = await import("fs");
|
|
16711
|
+
for (const dir of skillDirs) {
|
|
16712
|
+
if (!existsSync19(dir)) continue;
|
|
16713
|
+
for (const entry of readdirSync7(dir)) {
|
|
16714
|
+
if (statSync9(join19(dir, entry)).isDirectory()) {
|
|
16715
|
+
targets.push({ label: `skills/${entry}`, path: `workspace/skills/${entry}/SKILL.md` });
|
|
16716
|
+
}
|
|
16717
|
+
}
|
|
16718
|
+
}
|
|
16719
|
+
} catch {
|
|
16720
|
+
}
|
|
16721
|
+
const rows = targets.filter((t) => t.path !== currentTarget).map((t) => [{ label: t.label, data: `evolve:discuss-retarget-to:${idStr}:${t.path}` }]);
|
|
16722
|
+
rows.push([{ label: "Cancel", data: `evolve:discuss-back:${idStr}` }]);
|
|
16723
|
+
await channel.sendKeyboard(chatId, `Current target: ${currentTarget}
|
|
16724
|
+
|
|
16725
|
+
Pick a different file for this change. Identity files (SOUL/USER) shape personality; skills teach specific workflows.`, rows);
|
|
16726
|
+
break;
|
|
16727
|
+
}
|
|
16728
|
+
case "discuss-retarget-to": {
|
|
16729
|
+
const retargetParts = data.split(":");
|
|
16730
|
+
const rtId = parseInt(retargetParts[2], 10);
|
|
16731
|
+
const newPath = retargetParts.slice(3).join(":");
|
|
16732
|
+
const { getInsightById: rt2Ins, updateInsightProposal: rt2Update } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16733
|
+
const { formatProposalCard: rt2Card, buildProposalKeyboard: rt2Kb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16734
|
+
const { getDb: rt2Db } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16735
|
+
const rt2Insight = rt2Ins(rt2Db(), rtId);
|
|
16736
|
+
if (!rt2Insight) {
|
|
16737
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16738
|
+
break;
|
|
16739
|
+
}
|
|
16740
|
+
rt2Update(rt2Db(), rtId, newPath, rt2Insight.proposedDiff, rt2Insight.proposedAction);
|
|
16741
|
+
const updatedIns = rt2Ins(rt2Db(), rtId);
|
|
16742
|
+
if (updatedIns) {
|
|
16743
|
+
const card = rt2Card(updatedIns);
|
|
16744
|
+
const kb = rt2Kb(updatedIns.id, updatedIns.category);
|
|
16745
|
+
await channel.sendKeyboard(chatId, `Retargeted to ${newPath}. Updated proposal:
|
|
16746
|
+
|
|
16747
|
+
` + card, kb);
|
|
16748
|
+
}
|
|
16749
|
+
break;
|
|
16750
|
+
}
|
|
16751
|
+
case "discuss-revise": {
|
|
16752
|
+
const { getInsightById: rvIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16753
|
+
const { getDb: rvDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16754
|
+
const rvInsight = rvIns(rvDb(), parseInt(idStr, 10));
|
|
16755
|
+
if (!rvInsight) {
|
|
16756
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16757
|
+
break;
|
|
16758
|
+
}
|
|
16759
|
+
await channel.sendTyping?.(chatId);
|
|
16760
|
+
const revisePrompt = [
|
|
16761
|
+
`Revise this proposed change to be more specific and actionable:`,
|
|
16762
|
+
`Current insight: "${rvInsight.insight}"`,
|
|
16763
|
+
`Current diff: ${rvInsight.proposedDiff ?? "none"}`,
|
|
16764
|
+
`Target: ${rvInsight.targetFile}`,
|
|
16765
|
+
``,
|
|
16766
|
+
`Output ONLY the revised diff lines (starting with + for additions, - for removals). No explanation.`
|
|
16767
|
+
].join("\n");
|
|
16768
|
+
try {
|
|
16769
|
+
const rvResp = await askAgent(chatId, revisePrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
|
|
16770
|
+
const newDiff = rvResp.text?.trim() ?? rvInsight.proposedDiff;
|
|
16771
|
+
if (newDiff) {
|
|
16772
|
+
const { updateInsightProposal: rvUpdate } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16773
|
+
rvUpdate(rvDb(), parseInt(idStr, 10), rvInsight.targetFile ?? "", newDiff, rvInsight.proposedAction);
|
|
16774
|
+
}
|
|
16775
|
+
const updatedRv = rvIns(rvDb(), parseInt(idStr, 10));
|
|
16776
|
+
if (updatedRv) {
|
|
16777
|
+
const { formatProposalCard: rvCard, buildProposalKeyboard: rvKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16778
|
+
const card = rvCard(updatedRv);
|
|
16779
|
+
const kb = rvKb(updatedRv.id, updatedRv.category);
|
|
16780
|
+
await channel.sendKeyboard(chatId, "Revised proposal:\n\n" + card, kb);
|
|
16781
|
+
}
|
|
16782
|
+
} catch (e) {
|
|
16783
|
+
await channel.sendText(chatId, `Revision error: ${e.message}`, { parseMode: "plain" });
|
|
16784
|
+
}
|
|
16785
|
+
break;
|
|
16786
|
+
}
|
|
16787
|
+
case "discuss-back": {
|
|
16788
|
+
const { getInsightById: bkIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16789
|
+
const { formatProposalCard: bkCard, buildProposalKeyboard: bkKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16790
|
+
const { getDb: bkDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16791
|
+
const bkInsight = bkIns(bkDb(), parseInt(idStr, 10));
|
|
16792
|
+
if (bkInsight && bkInsight.status === "pending") {
|
|
16793
|
+
const card = bkCard(bkInsight);
|
|
16794
|
+
const kb = bkKb(bkInsight.id, bkInsight.category);
|
|
16795
|
+
await channel.sendKeyboard(chatId, card, kb);
|
|
16623
16796
|
}
|
|
16624
16797
|
break;
|
|
16625
16798
|
}
|
|
@@ -16681,13 +16854,13 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16681
16854
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16682
16855
|
const current = getReflectionStatus2(getDb2(), chatId);
|
|
16683
16856
|
if (current === "frozen") {
|
|
16684
|
-
const { readFileSync: readFileSync21, existsSync:
|
|
16857
|
+
const { readFileSync: readFileSync21, existsSync: existsSync47 } = await import("fs");
|
|
16685
16858
|
const { join: join26 } = await import("path");
|
|
16686
16859
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
16687
16860
|
const soulPath = join26(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16688
16861
|
const userPath = join26(CC_CLAW_HOME3, "identity/USER.md");
|
|
16689
|
-
const soul =
|
|
16690
|
-
const user =
|
|
16862
|
+
const soul = existsSync47(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
|
|
16863
|
+
const user = existsSync47(userPath) ? readFileSync21(userPath, "utf-8") : "";
|
|
16691
16864
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
16692
16865
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16693
16866
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -17281,7 +17454,7 @@ Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
|
17281
17454
|
const header2 = totalPages > 1 ? `${skills2.length} skills (page ${safePage}/${totalPages}). Select one to invoke:` : `${skills2.length} skills available. Select one to invoke:`;
|
|
17282
17455
|
await channel.sendKeyboard(chatId, header2, buttons);
|
|
17283
17456
|
}
|
|
17284
|
-
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS,
|
|
17457
|
+
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS, pendingFallbackMessages, dashboardClawWarnings, pendingSummaryUndo, pendingNewchatUndo, CLI_INSTALL_HINTS, BLOCKED_PATH_PATTERNS2, ALLOWED_REACTION_EMOJIS, SKILLS_PER_PAGE;
|
|
17285
17458
|
var init_router = __esm({
|
|
17286
17459
|
"src/router.ts"() {
|
|
17287
17460
|
"use strict";
|
|
@@ -17422,7 +17595,6 @@ var init_router = __esm({
|
|
|
17422
17595
|
bypassBusyCheck = /* @__PURE__ */ new Set();
|
|
17423
17596
|
activeSideQuests = /* @__PURE__ */ new Map();
|
|
17424
17597
|
MAX_SIDE_QUESTS = 2;
|
|
17425
|
-
activeProposalDiscussion = /* @__PURE__ */ new Map();
|
|
17426
17598
|
pendingFallbackMessages = /* @__PURE__ */ new Map();
|
|
17427
17599
|
dashboardClawWarnings = /* @__PURE__ */ new Map();
|
|
17428
17600
|
pendingSummaryUndo = /* @__PURE__ */ new Map();
|
|
@@ -17522,19 +17694,19 @@ var init_router = __esm({
|
|
|
17522
17694
|
});
|
|
17523
17695
|
|
|
17524
17696
|
// src/skills/bootstrap.ts
|
|
17525
|
-
import { existsSync as
|
|
17697
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17526
17698
|
import { readdir as readdir4, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
|
|
17527
17699
|
import { join as join20, dirname as dirname3 } from "path";
|
|
17528
17700
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17529
17701
|
async function copyAgentManifestSkills() {
|
|
17530
|
-
if (!
|
|
17702
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
17531
17703
|
try {
|
|
17532
17704
|
const entries = await readdir4(PKG_SKILLS, { withFileTypes: true });
|
|
17533
17705
|
for (const entry of entries) {
|
|
17534
17706
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
17535
17707
|
const src = join20(PKG_SKILLS, entry.name);
|
|
17536
17708
|
const dest = join20(SKILLS_PATH, entry.name);
|
|
17537
|
-
if (
|
|
17709
|
+
if (existsSync20(dest)) continue;
|
|
17538
17710
|
await copyFile(src, dest);
|
|
17539
17711
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
17540
17712
|
}
|
|
@@ -17545,7 +17717,7 @@ async function copyAgentManifestSkills() {
|
|
|
17545
17717
|
async function bootstrapSkills() {
|
|
17546
17718
|
await copyAgentManifestSkills();
|
|
17547
17719
|
const usmDir = join20(SKILLS_PATH, USM_DIR_NAME);
|
|
17548
|
-
if (
|
|
17720
|
+
if (existsSync20(usmDir)) return;
|
|
17549
17721
|
try {
|
|
17550
17722
|
const entries = await readdir4(SKILLS_PATH);
|
|
17551
17723
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -17568,7 +17740,7 @@ async function bootstrapSkills() {
|
|
|
17568
17740
|
}
|
|
17569
17741
|
async function patchUsmForCcClaw(usmDir) {
|
|
17570
17742
|
const skillPath = join20(usmDir, "SKILL.md");
|
|
17571
|
-
if (!
|
|
17743
|
+
if (!existsSync20(skillPath)) return;
|
|
17572
17744
|
try {
|
|
17573
17745
|
let content = await readFile6(skillPath, "utf-8");
|
|
17574
17746
|
let patched = false;
|
|
@@ -17828,13 +18000,13 @@ __export(ai_skill_exports, {
|
|
|
17828
18000
|
generateAiSkill: () => generateAiSkill,
|
|
17829
18001
|
installAiSkill: () => installAiSkill
|
|
17830
18002
|
});
|
|
17831
|
-
import { existsSync as
|
|
18003
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
|
|
17832
18004
|
import { join as join21 } from "path";
|
|
17833
|
-
import { homedir as
|
|
18005
|
+
import { homedir as homedir7 } from "os";
|
|
17834
18006
|
function generateAiSkill() {
|
|
17835
18007
|
const version = VERSION;
|
|
17836
18008
|
let systemState = "";
|
|
17837
|
-
if (
|
|
18009
|
+
if (existsSync21(DB_PATH)) {
|
|
17838
18010
|
try {
|
|
17839
18011
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
17840
18012
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -18250,11 +18422,11 @@ var init_ai_skill = __esm({
|
|
|
18250
18422
|
init_paths();
|
|
18251
18423
|
init_version();
|
|
18252
18424
|
BACKEND_SKILL_DIRS2 = {
|
|
18253
|
-
"cc-claw": [join21(
|
|
18254
|
-
claude: [join21(
|
|
18255
|
-
gemini: [join21(
|
|
18256
|
-
codex: [join21(
|
|
18257
|
-
cursor: [join21(
|
|
18425
|
+
"cc-claw": [join21(homedir7(), ".cc-claw", "workspace", "skills")],
|
|
18426
|
+
claude: [join21(homedir7(), ".claude", "skills")],
|
|
18427
|
+
gemini: [join21(homedir7(), ".gemini", "skills")],
|
|
18428
|
+
codex: [join21(homedir7(), ".agents", "skills")],
|
|
18429
|
+
cursor: [join21(homedir7(), ".cursor", "skills"), join21(homedir7(), ".cursor", "skills-cursor")]
|
|
18258
18430
|
};
|
|
18259
18431
|
}
|
|
18260
18432
|
});
|
|
@@ -18264,7 +18436,7 @@ var index_exports = {};
|
|
|
18264
18436
|
__export(index_exports, {
|
|
18265
18437
|
main: () => main
|
|
18266
18438
|
});
|
|
18267
|
-
import { mkdirSync as mkdirSync8, existsSync as
|
|
18439
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync22, renameSync, statSync as statSync4, readFileSync as readFileSync12 } from "fs";
|
|
18268
18440
|
import { join as join22 } from "path";
|
|
18269
18441
|
import dotenv from "dotenv";
|
|
18270
18442
|
function migrateLayout() {
|
|
@@ -18278,7 +18450,7 @@ function migrateLayout() {
|
|
|
18278
18450
|
[join22(CC_CLAW_HOME, "cc-claw.error.log.1"), join22(LOGS_PATH, "cc-claw.error.log.1")]
|
|
18279
18451
|
];
|
|
18280
18452
|
for (const [from, to] of moves) {
|
|
18281
|
-
if (
|
|
18453
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
18282
18454
|
try {
|
|
18283
18455
|
renameSync(from, to);
|
|
18284
18456
|
} catch {
|
|
@@ -18289,7 +18461,7 @@ function migrateLayout() {
|
|
|
18289
18461
|
function rotateLogs() {
|
|
18290
18462
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
18291
18463
|
try {
|
|
18292
|
-
const { size } =
|
|
18464
|
+
const { size } = statSync4(file);
|
|
18293
18465
|
if (size > LOG_MAX_BYTES) {
|
|
18294
18466
|
const archivePath = `${file}.1`;
|
|
18295
18467
|
try {
|
|
@@ -18485,10 +18657,10 @@ var init_index = __esm({
|
|
|
18485
18657
|
init_bootstrap2();
|
|
18486
18658
|
init_health3();
|
|
18487
18659
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
18488
|
-
if (!
|
|
18660
|
+
if (!existsSync22(dir)) mkdirSync8(dir, { recursive: true });
|
|
18489
18661
|
}
|
|
18490
18662
|
migrateLayout();
|
|
18491
|
-
if (
|
|
18663
|
+
if (existsSync22(ENV_PATH)) {
|
|
18492
18664
|
dotenv.config({ path: ENV_PATH });
|
|
18493
18665
|
} else {
|
|
18494
18666
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -18509,12 +18681,12 @@ __export(api_client_exports, {
|
|
|
18509
18681
|
apiPost: () => apiPost,
|
|
18510
18682
|
isDaemonRunning: () => isDaemonRunning
|
|
18511
18683
|
});
|
|
18512
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
18684
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
18513
18685
|
import { request as httpRequest } from "http";
|
|
18514
18686
|
function getToken() {
|
|
18515
18687
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
18516
18688
|
try {
|
|
18517
|
-
if (
|
|
18689
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
18518
18690
|
} catch {
|
|
18519
18691
|
}
|
|
18520
18692
|
return null;
|
|
@@ -18609,9 +18781,9 @@ __export(service_exports, {
|
|
|
18609
18781
|
serviceStatus: () => serviceStatus,
|
|
18610
18782
|
uninstallService: () => uninstallService
|
|
18611
18783
|
});
|
|
18612
|
-
import { existsSync as
|
|
18784
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
18613
18785
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
18614
|
-
import { homedir as
|
|
18786
|
+
import { homedir as homedir8, platform } from "os";
|
|
18615
18787
|
import { join as join23, dirname as dirname4 } from "path";
|
|
18616
18788
|
function resolveExecutable2(name) {
|
|
18617
18789
|
try {
|
|
@@ -18622,7 +18794,7 @@ function resolveExecutable2(name) {
|
|
|
18622
18794
|
}
|
|
18623
18795
|
function getPathDirs() {
|
|
18624
18796
|
const nodeBin = dirname4(process.execPath);
|
|
18625
|
-
const home =
|
|
18797
|
+
const home = homedir8();
|
|
18626
18798
|
const dirs = /* @__PURE__ */ new Set([
|
|
18627
18799
|
nodeBin,
|
|
18628
18800
|
join23(home, ".local", "bin"),
|
|
@@ -18640,7 +18812,7 @@ function getPathDirs() {
|
|
|
18640
18812
|
function generatePlist() {
|
|
18641
18813
|
const ccClawBin = resolveExecutable2("cc-claw");
|
|
18642
18814
|
const pathDirs = getPathDirs();
|
|
18643
|
-
const home =
|
|
18815
|
+
const home = homedir8();
|
|
18644
18816
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
18645
18817
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
18646
18818
|
<plist version="1.0">
|
|
@@ -18684,9 +18856,9 @@ function generatePlist() {
|
|
|
18684
18856
|
}
|
|
18685
18857
|
function installMacOS() {
|
|
18686
18858
|
const agentsDir = dirname4(PLIST_PATH);
|
|
18687
|
-
if (!
|
|
18688
|
-
if (!
|
|
18689
|
-
if (
|
|
18859
|
+
if (!existsSync24(agentsDir)) mkdirSync9(agentsDir, { recursive: true });
|
|
18860
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18861
|
+
if (existsSync24(PLIST_PATH)) {
|
|
18690
18862
|
try {
|
|
18691
18863
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
18692
18864
|
} catch {
|
|
@@ -18698,7 +18870,7 @@ function installMacOS() {
|
|
|
18698
18870
|
console.log(" Service loaded and starting.");
|
|
18699
18871
|
}
|
|
18700
18872
|
function uninstallMacOS() {
|
|
18701
|
-
if (!
|
|
18873
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
18702
18874
|
console.log(" No service found to uninstall.");
|
|
18703
18875
|
return;
|
|
18704
18876
|
}
|
|
@@ -18765,15 +18937,15 @@ Restart=on-failure
|
|
|
18765
18937
|
RestartSec=10
|
|
18766
18938
|
WorkingDirectory=${CC_CLAW_HOME}
|
|
18767
18939
|
Environment=PATH=${pathDirs}
|
|
18768
|
-
Environment=HOME=${
|
|
18940
|
+
Environment=HOME=${homedir8()}
|
|
18769
18941
|
|
|
18770
18942
|
[Install]
|
|
18771
18943
|
WantedBy=default.target
|
|
18772
18944
|
`;
|
|
18773
18945
|
}
|
|
18774
18946
|
function installLinux() {
|
|
18775
|
-
if (!
|
|
18776
|
-
if (!
|
|
18947
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync9(SYSTEMD_DIR, { recursive: true });
|
|
18948
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18777
18949
|
writeFileSync7(UNIT_PATH, generateUnit());
|
|
18778
18950
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
18779
18951
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -18782,7 +18954,7 @@ function installLinux() {
|
|
|
18782
18954
|
console.log(" Service enabled and started.");
|
|
18783
18955
|
}
|
|
18784
18956
|
function uninstallLinux() {
|
|
18785
|
-
if (!
|
|
18957
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
18786
18958
|
console.log(" No service found to uninstall.");
|
|
18787
18959
|
return;
|
|
18788
18960
|
}
|
|
@@ -18807,7 +18979,7 @@ function statusLinux() {
|
|
|
18807
18979
|
}
|
|
18808
18980
|
}
|
|
18809
18981
|
function installService() {
|
|
18810
|
-
if (!
|
|
18982
|
+
if (!existsSync24(join23(CC_CLAW_HOME, ".env"))) {
|
|
18811
18983
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
18812
18984
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
18813
18985
|
process.exitCode = 1;
|
|
@@ -18836,8 +19008,8 @@ var init_service = __esm({
|
|
|
18836
19008
|
"use strict";
|
|
18837
19009
|
init_paths();
|
|
18838
19010
|
PLIST_LABEL = "com.cc-claw";
|
|
18839
|
-
PLIST_PATH = join23(
|
|
18840
|
-
SYSTEMD_DIR = join23(
|
|
19011
|
+
PLIST_PATH = join23(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
19012
|
+
SYSTEMD_DIR = join23(homedir8(), ".config", "systemd", "user");
|
|
18841
19013
|
UNIT_PATH = join23(SYSTEMD_DIR, "cc-claw.service");
|
|
18842
19014
|
}
|
|
18843
19015
|
});
|
|
@@ -19035,7 +19207,7 @@ var status_exports = {};
|
|
|
19035
19207
|
__export(status_exports, {
|
|
19036
19208
|
statusCommand: () => statusCommand
|
|
19037
19209
|
});
|
|
19038
|
-
import { existsSync as
|
|
19210
|
+
import { existsSync as existsSync25, statSync as statSync5 } from "fs";
|
|
19039
19211
|
async function statusCommand(globalOpts, localOpts) {
|
|
19040
19212
|
try {
|
|
19041
19213
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19075,7 +19247,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
19075
19247
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
19076
19248
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
19077
19249
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
19078
|
-
const dbStat =
|
|
19250
|
+
const dbStat = existsSync25(DB_PATH) ? statSync5(DB_PATH) : null;
|
|
19079
19251
|
let daemonRunning = false;
|
|
19080
19252
|
let daemonInfo = {};
|
|
19081
19253
|
if (localOpts.deep) {
|
|
@@ -19166,12 +19338,12 @@ var doctor_exports = {};
|
|
|
19166
19338
|
__export(doctor_exports, {
|
|
19167
19339
|
doctorCommand: () => doctorCommand
|
|
19168
19340
|
});
|
|
19169
|
-
import { existsSync as
|
|
19341
|
+
import { existsSync as existsSync26, statSync as statSync6, accessSync, constants } from "fs";
|
|
19170
19342
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
19171
19343
|
async function doctorCommand(globalOpts, localOpts) {
|
|
19172
19344
|
const checks = [];
|
|
19173
|
-
if (
|
|
19174
|
-
const size =
|
|
19345
|
+
if (existsSync26(DB_PATH)) {
|
|
19346
|
+
const size = statSync6(DB_PATH).size;
|
|
19175
19347
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
19176
19348
|
try {
|
|
19177
19349
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19200,7 +19372,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19200
19372
|
} else {
|
|
19201
19373
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
19202
19374
|
}
|
|
19203
|
-
if (
|
|
19375
|
+
if (existsSync26(ENV_PATH)) {
|
|
19204
19376
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
19205
19377
|
} else {
|
|
19206
19378
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -19244,7 +19416,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19244
19416
|
checks.push({ name: "Daemon", status: "warning", message: "could not probe" });
|
|
19245
19417
|
}
|
|
19246
19418
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
19247
|
-
if (
|
|
19419
|
+
if (existsSync26(tokenPath)) {
|
|
19248
19420
|
try {
|
|
19249
19421
|
accessSync(tokenPath, constants.R_OK);
|
|
19250
19422
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -19269,7 +19441,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19269
19441
|
}
|
|
19270
19442
|
} catch {
|
|
19271
19443
|
}
|
|
19272
|
-
if (
|
|
19444
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
19273
19445
|
try {
|
|
19274
19446
|
const { readFileSync: readFileSync21 } = await import("fs");
|
|
19275
19447
|
const logContent = readFileSync21(ERROR_LOG_PATH, "utf-8");
|
|
@@ -19395,10 +19567,10 @@ var logs_exports = {};
|
|
|
19395
19567
|
__export(logs_exports, {
|
|
19396
19568
|
logsCommand: () => logsCommand
|
|
19397
19569
|
});
|
|
19398
|
-
import { existsSync as
|
|
19570
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
19399
19571
|
async function logsCommand(opts) {
|
|
19400
19572
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
19401
|
-
if (!
|
|
19573
|
+
if (!existsSync27(logFile)) {
|
|
19402
19574
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
19403
19575
|
process.exit(1);
|
|
19404
19576
|
}
|
|
@@ -19450,11 +19622,11 @@ __export(gemini_exports, {
|
|
|
19450
19622
|
geminiReorder: () => geminiReorder,
|
|
19451
19623
|
geminiRotation: () => geminiRotation
|
|
19452
19624
|
});
|
|
19453
|
-
import { existsSync as
|
|
19625
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
19454
19626
|
import { join as join24 } from "path";
|
|
19455
19627
|
import { createInterface as createInterface5 } from "readline";
|
|
19456
19628
|
function requireDb() {
|
|
19457
|
-
if (!
|
|
19629
|
+
if (!existsSync28(DB_PATH)) {
|
|
19458
19630
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19459
19631
|
process.exit(1);
|
|
19460
19632
|
}
|
|
@@ -19480,7 +19652,7 @@ function resolveOAuthEmail(configHome) {
|
|
|
19480
19652
|
if (!configHome) return null;
|
|
19481
19653
|
try {
|
|
19482
19654
|
const accountsPath = join24(configHome, ".gemini", "google_accounts.json");
|
|
19483
|
-
if (!
|
|
19655
|
+
if (!existsSync28(accountsPath)) return null;
|
|
19484
19656
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
19485
19657
|
return accounts.active || null;
|
|
19486
19658
|
} catch {
|
|
@@ -19564,7 +19736,7 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
19564
19736
|
async function geminiAddAccount(globalOpts, opts) {
|
|
19565
19737
|
await requireWriteDb();
|
|
19566
19738
|
const slotsDir = join24(CC_CLAW_HOME, "gemini-slots");
|
|
19567
|
-
if (!
|
|
19739
|
+
if (!existsSync28(slotsDir)) mkdirSync10(slotsDir, { recursive: true });
|
|
19568
19740
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19569
19741
|
const tempId = Date.now();
|
|
19570
19742
|
const slotDir = join24(slotsDir, `slot-${tempId}`);
|
|
@@ -19588,7 +19760,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
19588
19760
|
} catch {
|
|
19589
19761
|
}
|
|
19590
19762
|
const oauthPath = join24(slotDir, ".gemini", "oauth_creds.json");
|
|
19591
|
-
if (!
|
|
19763
|
+
if (!existsSync28(oauthPath)) {
|
|
19592
19764
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
19593
19765
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
19594
19766
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -19702,12 +19874,12 @@ __export(backend_exports, {
|
|
|
19702
19874
|
backendList: () => backendList,
|
|
19703
19875
|
backendSet: () => backendSet
|
|
19704
19876
|
});
|
|
19705
|
-
import { existsSync as
|
|
19877
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19706
19878
|
async function backendList(globalOpts) {
|
|
19707
19879
|
const { getAvailableAdapters: getAvailableAdapters2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19708
19880
|
const chatId = resolveChatId(globalOpts);
|
|
19709
19881
|
let activeBackend = null;
|
|
19710
|
-
if (
|
|
19882
|
+
if (existsSync29(DB_PATH)) {
|
|
19711
19883
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19712
19884
|
const readDb = openDatabaseReadOnly2();
|
|
19713
19885
|
try {
|
|
@@ -19738,7 +19910,7 @@ async function backendList(globalOpts) {
|
|
|
19738
19910
|
}
|
|
19739
19911
|
async function backendGet(globalOpts) {
|
|
19740
19912
|
const chatId = resolveChatId(globalOpts);
|
|
19741
|
-
if (!
|
|
19913
|
+
if (!existsSync29(DB_PATH)) {
|
|
19742
19914
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19743
19915
|
process.exit(1);
|
|
19744
19916
|
}
|
|
@@ -19782,13 +19954,13 @@ __export(model_exports, {
|
|
|
19782
19954
|
modelList: () => modelList,
|
|
19783
19955
|
modelSet: () => modelSet
|
|
19784
19956
|
});
|
|
19785
|
-
import { existsSync as
|
|
19957
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19786
19958
|
async function modelList(globalOpts) {
|
|
19787
19959
|
const chatId = resolveChatId(globalOpts);
|
|
19788
19960
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19789
19961
|
const { getAdapter: getAdapter2, getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19790
19962
|
let backendId = "claude";
|
|
19791
|
-
if (
|
|
19963
|
+
if (existsSync30(DB_PATH)) {
|
|
19792
19964
|
const readDb = openDatabaseReadOnly2();
|
|
19793
19965
|
try {
|
|
19794
19966
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -19821,7 +19993,7 @@ async function modelList(globalOpts) {
|
|
|
19821
19993
|
}
|
|
19822
19994
|
async function modelGet(globalOpts) {
|
|
19823
19995
|
const chatId = resolveChatId(globalOpts);
|
|
19824
|
-
if (!
|
|
19996
|
+
if (!existsSync30(DB_PATH)) {
|
|
19825
19997
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19826
19998
|
process.exit(1);
|
|
19827
19999
|
}
|
|
@@ -19865,9 +20037,9 @@ __export(memory_exports, {
|
|
|
19865
20037
|
memoryList: () => memoryList,
|
|
19866
20038
|
memorySearch: () => memorySearch
|
|
19867
20039
|
});
|
|
19868
|
-
import { existsSync as
|
|
20040
|
+
import { existsSync as existsSync31 } from "fs";
|
|
19869
20041
|
async function memoryList(globalOpts) {
|
|
19870
|
-
if (!
|
|
20042
|
+
if (!existsSync31(DB_PATH)) {
|
|
19871
20043
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19872
20044
|
process.exit(1);
|
|
19873
20045
|
}
|
|
@@ -19891,7 +20063,7 @@ async function memoryList(globalOpts) {
|
|
|
19891
20063
|
});
|
|
19892
20064
|
}
|
|
19893
20065
|
async function memorySearch(globalOpts, query) {
|
|
19894
|
-
if (!
|
|
20066
|
+
if (!existsSync31(DB_PATH)) {
|
|
19895
20067
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19896
20068
|
process.exit(1);
|
|
19897
20069
|
}
|
|
@@ -19913,7 +20085,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
19913
20085
|
});
|
|
19914
20086
|
}
|
|
19915
20087
|
async function memoryHistory(globalOpts, opts) {
|
|
19916
|
-
if (!
|
|
20088
|
+
if (!existsSync31(DB_PATH)) {
|
|
19917
20089
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19918
20090
|
process.exit(1);
|
|
19919
20091
|
}
|
|
@@ -19961,7 +20133,7 @@ __export(cron_exports2, {
|
|
|
19961
20133
|
cronList: () => cronList,
|
|
19962
20134
|
cronRuns: () => cronRuns
|
|
19963
20135
|
});
|
|
19964
|
-
import { existsSync as
|
|
20136
|
+
import { existsSync as existsSync32 } from "fs";
|
|
19965
20137
|
function parseFallbacks(raw) {
|
|
19966
20138
|
return raw.slice(0, 3).map((f) => {
|
|
19967
20139
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -19982,7 +20154,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
19982
20154
|
return val;
|
|
19983
20155
|
}
|
|
19984
20156
|
async function cronList(globalOpts) {
|
|
19985
|
-
if (!
|
|
20157
|
+
if (!existsSync32(DB_PATH)) {
|
|
19986
20158
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19987
20159
|
process.exit(1);
|
|
19988
20160
|
}
|
|
@@ -20001,7 +20173,7 @@ async function cronList(globalOpts) {
|
|
|
20001
20173
|
const schedule2 = j.cron ?? (j.at_time ? `at ${j.at_time}` : j.every_ms ? `every ${j.every_ms / 1e3}s` : "?");
|
|
20002
20174
|
const tz = j.timezone !== "UTC" ? ` (${j.timezone})` : "";
|
|
20003
20175
|
lines.push(` ${statusDot(status)} #${j.id} [${status}] ${schedule2}${tz}`);
|
|
20004
|
-
lines.push(` ${j.description}`);
|
|
20176
|
+
lines.push(` ${j.title ?? j.description}`);
|
|
20005
20177
|
if (j.backend) lines.push(` Backend: ${j.backend}${j.model ? ` / ${j.model}` : ""}`);
|
|
20006
20178
|
if (j.fallbacks) {
|
|
20007
20179
|
try {
|
|
@@ -20020,7 +20192,7 @@ async function cronList(globalOpts) {
|
|
|
20020
20192
|
});
|
|
20021
20193
|
}
|
|
20022
20194
|
async function cronHealth(globalOpts) {
|
|
20023
|
-
if (!
|
|
20195
|
+
if (!existsSync32(DB_PATH)) {
|
|
20024
20196
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20025
20197
|
process.exit(1);
|
|
20026
20198
|
}
|
|
@@ -20080,6 +20252,7 @@ async function cronCreate(globalOpts, opts) {
|
|
|
20080
20252
|
cron: opts.cron ?? null,
|
|
20081
20253
|
atTime: opts.at ?? null,
|
|
20082
20254
|
everyMs,
|
|
20255
|
+
title: opts.title ?? null,
|
|
20083
20256
|
description: opts.description,
|
|
20084
20257
|
chatId,
|
|
20085
20258
|
backend: opts.backend ?? null,
|
|
@@ -20134,6 +20307,10 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20134
20307
|
const db3 = getDb2();
|
|
20135
20308
|
const updates = [];
|
|
20136
20309
|
const values = [];
|
|
20310
|
+
if (opts.title) {
|
|
20311
|
+
updates.push("title = ?");
|
|
20312
|
+
values.push(opts.title);
|
|
20313
|
+
}
|
|
20137
20314
|
if (opts.description) {
|
|
20138
20315
|
updates.push("description = ?");
|
|
20139
20316
|
values.push(opts.description);
|
|
@@ -20200,7 +20377,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20200
20377
|
}
|
|
20201
20378
|
}
|
|
20202
20379
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
20203
|
-
if (!
|
|
20380
|
+
if (!existsSync32(DB_PATH)) {
|
|
20204
20381
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20205
20382
|
process.exit(1);
|
|
20206
20383
|
}
|
|
@@ -20247,9 +20424,9 @@ __export(agents_exports, {
|
|
|
20247
20424
|
runnersList: () => runnersList,
|
|
20248
20425
|
tasksList: () => tasksList
|
|
20249
20426
|
});
|
|
20250
|
-
import { existsSync as
|
|
20427
|
+
import { existsSync as existsSync33 } from "fs";
|
|
20251
20428
|
async function agentsList(globalOpts) {
|
|
20252
|
-
if (!
|
|
20429
|
+
if (!existsSync33(DB_PATH)) {
|
|
20253
20430
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20254
20431
|
process.exit(1);
|
|
20255
20432
|
}
|
|
@@ -20280,7 +20457,7 @@ async function agentsList(globalOpts) {
|
|
|
20280
20457
|
});
|
|
20281
20458
|
}
|
|
20282
20459
|
async function tasksList(globalOpts) {
|
|
20283
|
-
if (!
|
|
20460
|
+
if (!existsSync33(DB_PATH)) {
|
|
20284
20461
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20285
20462
|
process.exit(1);
|
|
20286
20463
|
}
|
|
@@ -20408,18 +20585,18 @@ __export(db_exports, {
|
|
|
20408
20585
|
dbPath: () => dbPath,
|
|
20409
20586
|
dbStats: () => dbStats
|
|
20410
20587
|
});
|
|
20411
|
-
import { existsSync as
|
|
20588
|
+
import { existsSync as existsSync34, statSync as statSync7, copyFileSync as copyFileSync2, mkdirSync as mkdirSync11 } from "fs";
|
|
20412
20589
|
import { dirname as dirname5 } from "path";
|
|
20413
20590
|
async function dbStats(globalOpts) {
|
|
20414
|
-
if (!
|
|
20591
|
+
if (!existsSync34(DB_PATH)) {
|
|
20415
20592
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20416
20593
|
process.exit(1);
|
|
20417
20594
|
}
|
|
20418
20595
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
20419
20596
|
const readDb = openDatabaseReadOnly2();
|
|
20420
|
-
const mainSize =
|
|
20597
|
+
const mainSize = statSync7(DB_PATH).size;
|
|
20421
20598
|
const walPath = DB_PATH + "-wal";
|
|
20422
|
-
const walSize =
|
|
20599
|
+
const walSize = existsSync34(walPath) ? statSync7(walPath).size : 0;
|
|
20423
20600
|
const tableNames = readDb.prepare(
|
|
20424
20601
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
20425
20602
|
).all();
|
|
@@ -20453,7 +20630,7 @@ async function dbPath(globalOpts) {
|
|
|
20453
20630
|
output({ path: DB_PATH }, (d) => d.path);
|
|
20454
20631
|
}
|
|
20455
20632
|
async function dbBackup(globalOpts, destPath) {
|
|
20456
|
-
if (!
|
|
20633
|
+
if (!existsSync34(DB_PATH)) {
|
|
20457
20634
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20458
20635
|
process.exit(1);
|
|
20459
20636
|
}
|
|
@@ -20462,8 +20639,8 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
20462
20639
|
mkdirSync11(dirname5(dest), { recursive: true });
|
|
20463
20640
|
copyFileSync2(DB_PATH, dest);
|
|
20464
20641
|
const walPath = DB_PATH + "-wal";
|
|
20465
|
-
if (
|
|
20466
|
-
output({ path: dest, sizeBytes:
|
|
20642
|
+
if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
|
|
20643
|
+
output({ path: dest, sizeBytes: statSync7(dest).size }, (d) => {
|
|
20467
20644
|
const b = d;
|
|
20468
20645
|
return `
|
|
20469
20646
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -20491,9 +20668,9 @@ __export(usage_exports, {
|
|
|
20491
20668
|
usageCost: () => usageCost,
|
|
20492
20669
|
usageTokens: () => usageTokens
|
|
20493
20670
|
});
|
|
20494
|
-
import { existsSync as
|
|
20671
|
+
import { existsSync as existsSync35 } from "fs";
|
|
20495
20672
|
function ensureDb() {
|
|
20496
|
-
if (!
|
|
20673
|
+
if (!existsSync35(DB_PATH)) {
|
|
20497
20674
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
20498
20675
|
process.exit(1);
|
|
20499
20676
|
}
|
|
@@ -20683,9 +20860,9 @@ __export(config_exports, {
|
|
|
20683
20860
|
configList: () => configList,
|
|
20684
20861
|
configSet: () => configSet
|
|
20685
20862
|
});
|
|
20686
|
-
import { existsSync as
|
|
20863
|
+
import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
|
|
20687
20864
|
async function configList(globalOpts) {
|
|
20688
|
-
if (!
|
|
20865
|
+
if (!existsSync36(DB_PATH)) {
|
|
20689
20866
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20690
20867
|
process.exit(1);
|
|
20691
20868
|
}
|
|
@@ -20719,7 +20896,7 @@ async function configGet(globalOpts, key) {
|
|
|
20719
20896
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
20720
20897
|
process.exit(1);
|
|
20721
20898
|
}
|
|
20722
|
-
if (!
|
|
20899
|
+
if (!existsSync36(DB_PATH)) {
|
|
20723
20900
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20724
20901
|
process.exit(1);
|
|
20725
20902
|
}
|
|
@@ -20765,7 +20942,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
20765
20942
|
}
|
|
20766
20943
|
}
|
|
20767
20944
|
async function configEnv(_globalOpts) {
|
|
20768
|
-
if (!
|
|
20945
|
+
if (!existsSync36(ENV_PATH)) {
|
|
20769
20946
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
20770
20947
|
process.exit(1);
|
|
20771
20948
|
}
|
|
@@ -20819,9 +20996,9 @@ __export(session_exports, {
|
|
|
20819
20996
|
sessionGet: () => sessionGet,
|
|
20820
20997
|
sessionNew: () => sessionNew
|
|
20821
20998
|
});
|
|
20822
|
-
import { existsSync as
|
|
20999
|
+
import { existsSync as existsSync37 } from "fs";
|
|
20823
21000
|
async function sessionGet(globalOpts) {
|
|
20824
|
-
if (!
|
|
21001
|
+
if (!existsSync37(DB_PATH)) {
|
|
20825
21002
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20826
21003
|
process.exit(1);
|
|
20827
21004
|
}
|
|
@@ -20882,9 +21059,9 @@ __export(permissions_exports, {
|
|
|
20882
21059
|
verboseGet: () => verboseGet,
|
|
20883
21060
|
verboseSet: () => verboseSet
|
|
20884
21061
|
});
|
|
20885
|
-
import { existsSync as
|
|
21062
|
+
import { existsSync as existsSync38 } from "fs";
|
|
20886
21063
|
function ensureDb2() {
|
|
20887
|
-
if (!
|
|
21064
|
+
if (!existsSync38(DB_PATH)) {
|
|
20888
21065
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20889
21066
|
process.exit(1);
|
|
20890
21067
|
}
|
|
@@ -21031,9 +21208,9 @@ __export(cwd_exports, {
|
|
|
21031
21208
|
cwdGet: () => cwdGet,
|
|
21032
21209
|
cwdSet: () => cwdSet
|
|
21033
21210
|
});
|
|
21034
|
-
import { existsSync as
|
|
21211
|
+
import { existsSync as existsSync39 } from "fs";
|
|
21035
21212
|
async function cwdGet(globalOpts) {
|
|
21036
|
-
if (!
|
|
21213
|
+
if (!existsSync39(DB_PATH)) {
|
|
21037
21214
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21038
21215
|
process.exit(1);
|
|
21039
21216
|
}
|
|
@@ -21095,9 +21272,9 @@ __export(voice_exports, {
|
|
|
21095
21272
|
voiceGet: () => voiceGet,
|
|
21096
21273
|
voiceSet: () => voiceSet
|
|
21097
21274
|
});
|
|
21098
|
-
import { existsSync as
|
|
21275
|
+
import { existsSync as existsSync40 } from "fs";
|
|
21099
21276
|
async function voiceGet(globalOpts) {
|
|
21100
|
-
if (!
|
|
21277
|
+
if (!existsSync40(DB_PATH)) {
|
|
21101
21278
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21102
21279
|
process.exit(1);
|
|
21103
21280
|
}
|
|
@@ -21146,9 +21323,9 @@ __export(heartbeat_exports, {
|
|
|
21146
21323
|
heartbeatGet: () => heartbeatGet,
|
|
21147
21324
|
heartbeatSet: () => heartbeatSet
|
|
21148
21325
|
});
|
|
21149
|
-
import { existsSync as
|
|
21326
|
+
import { existsSync as existsSync41 } from "fs";
|
|
21150
21327
|
async function heartbeatGet(globalOpts) {
|
|
21151
|
-
if (!
|
|
21328
|
+
if (!existsSync41(DB_PATH)) {
|
|
21152
21329
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21153
21330
|
process.exit(1);
|
|
21154
21331
|
}
|
|
@@ -21258,9 +21435,9 @@ __export(chats_exports, {
|
|
|
21258
21435
|
chatsList: () => chatsList,
|
|
21259
21436
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
21260
21437
|
});
|
|
21261
|
-
import { existsSync as
|
|
21438
|
+
import { existsSync as existsSync42 } from "fs";
|
|
21262
21439
|
async function chatsList(_globalOpts) {
|
|
21263
|
-
if (!
|
|
21440
|
+
if (!existsSync42(DB_PATH)) {
|
|
21264
21441
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21265
21442
|
process.exit(1);
|
|
21266
21443
|
}
|
|
@@ -21388,9 +21565,9 @@ var mcps_exports = {};
|
|
|
21388
21565
|
__export(mcps_exports, {
|
|
21389
21566
|
mcpsList: () => mcpsList
|
|
21390
21567
|
});
|
|
21391
|
-
import { existsSync as
|
|
21568
|
+
import { existsSync as existsSync43 } from "fs";
|
|
21392
21569
|
async function mcpsList(_globalOpts) {
|
|
21393
|
-
if (!
|
|
21570
|
+
if (!existsSync43(DB_PATH)) {
|
|
21394
21571
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21395
21572
|
process.exit(1);
|
|
21396
21573
|
}
|
|
@@ -21427,11 +21604,11 @@ __export(chat_exports, {
|
|
|
21427
21604
|
chatSend: () => chatSend
|
|
21428
21605
|
});
|
|
21429
21606
|
import { request as httpRequest2 } from "http";
|
|
21430
|
-
import { readFileSync as readFileSync19, existsSync as
|
|
21607
|
+
import { readFileSync as readFileSync19, existsSync as existsSync44 } from "fs";
|
|
21431
21608
|
function getToken2() {
|
|
21432
21609
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21433
21610
|
try {
|
|
21434
|
-
if (
|
|
21611
|
+
if (existsSync44(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
|
|
21435
21612
|
} catch {
|
|
21436
21613
|
}
|
|
21437
21614
|
return null;
|
|
@@ -21871,9 +22048,9 @@ __export(evolve_exports, {
|
|
|
21871
22048
|
evolveStatus: () => evolveStatus,
|
|
21872
22049
|
evolveUndo: () => evolveUndo
|
|
21873
22050
|
});
|
|
21874
|
-
import { existsSync as
|
|
22051
|
+
import { existsSync as existsSync45 } from "fs";
|
|
21875
22052
|
function ensureDb3() {
|
|
21876
|
-
if (!
|
|
22053
|
+
if (!existsSync45(DB_PATH)) {
|
|
21877
22054
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
21878
22055
|
process.exit(1);
|
|
21879
22056
|
}
|
|
@@ -22235,7 +22412,7 @@ var init_evolve = __esm({
|
|
|
22235
22412
|
|
|
22236
22413
|
// src/setup.ts
|
|
22237
22414
|
var setup_exports = {};
|
|
22238
|
-
import { existsSync as
|
|
22415
|
+
import { existsSync as existsSync46, writeFileSync as writeFileSync9, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, statSync as statSync8 } from "fs";
|
|
22239
22416
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22240
22417
|
import { createInterface as createInterface7 } from "readline";
|
|
22241
22418
|
import { join as join25 } from "path";
|
|
@@ -22313,10 +22490,10 @@ async function setup() {
|
|
|
22313
22490
|
}
|
|
22314
22491
|
console.log("");
|
|
22315
22492
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
22316
|
-
if (!
|
|
22493
|
+
if (!existsSync46(dir)) mkdirSync12(dir, { recursive: true });
|
|
22317
22494
|
}
|
|
22318
22495
|
const env = {};
|
|
22319
|
-
const envSource =
|
|
22496
|
+
const envSource = existsSync46(ENV_PATH) ? ENV_PATH : existsSync46(".env") ? ".env" : null;
|
|
22320
22497
|
if (envSource) {
|
|
22321
22498
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
22322
22499
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -22327,8 +22504,8 @@ async function setup() {
|
|
|
22327
22504
|
}
|
|
22328
22505
|
}
|
|
22329
22506
|
const cwdDb = join25(process.cwd(), "cc-claw.db");
|
|
22330
|
-
if (
|
|
22331
|
-
const { size } =
|
|
22507
|
+
if (existsSync46(cwdDb) && !existsSync46(DB_PATH)) {
|
|
22508
|
+
const { size } = statSync8(cwdDb);
|
|
22332
22509
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
22333
22510
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
22334
22511
|
if (migrate) {
|
|
@@ -22747,7 +22924,7 @@ function registerCronCommands(cmd) {
|
|
|
22747
22924
|
const { cronList: cronList2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22748
22925
|
await cronList2(program.opts());
|
|
22749
22926
|
});
|
|
22750
|
-
cmd.command("create").description("Create a scheduled job").requiredOption("--description <text>", "Job description").option("--prompt <text>", "Agent prompt (defaults to description)").option("--cron <expr>", "Cron expression (e.g. '0 9 * * *')").option("--at <iso8601>", "One-shot time").option("--every <interval>", "Repeat interval (e.g. 30m, 1h)").option("--backend <name>", "Backend for this job").option("--model <name>", "Model for this job").option("--thinking <level>", "Thinking level").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>", "IANA timezone", "UTC").option("--session-type <type>", "Session type (isolated/main)", "isolated").option("--delivery <mode>", "Delivery mode (announce/webhook/none)", "announce").option("--channel <name>", "Delivery channel").option("--target <id>", "Delivery target").option("--cwd <path>", "Working directory").action(async (opts) => {
|
|
22927
|
+
cmd.command("create").description("Create a scheduled job").requiredOption("--description <text>", "Job description").option("--title <text>", "Short title for job list (auto-generated if omitted)").option("--prompt <text>", "Agent prompt (defaults to description)").option("--cron <expr>", "Cron expression (e.g. '0 9 * * *')").option("--at <iso8601>", "One-shot time").option("--every <interval>", "Repeat interval (e.g. 30m, 1h)").option("--backend <name>", "Backend for this job").option("--model <name>", "Model for this job").option("--thinking <level>", "Thinking level").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>", "IANA timezone", "UTC").option("--session-type <type>", "Session type (isolated/main)", "isolated").option("--delivery <mode>", "Delivery mode (announce/webhook/none)", "announce").option("--channel <name>", "Delivery channel").option("--target <id>", "Delivery target").option("--cwd <path>", "Working directory").action(async (opts) => {
|
|
22751
22928
|
const { cronCreate: cronCreate2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22752
22929
|
await cronCreate2(program.opts(), opts);
|
|
22753
22930
|
});
|
|
@@ -22767,7 +22944,7 @@ function registerCronCommands(cmd) {
|
|
|
22767
22944
|
const { cronAction: cronAction2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22768
22945
|
await cronAction2(program.opts(), "run", id);
|
|
22769
22946
|
});
|
|
22770
|
-
cmd.command("edit <id>").description("Edit a job (same flags as create)").option("--description <text>").option("--cron <expr>").option("--at <iso8601>").option("--every <interval>").option("--backend <name>").option("--model <name>").option("--thinking <level>").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>").action(async (id, opts) => {
|
|
22947
|
+
cmd.command("edit <id>").description("Edit a job (same flags as create)").option("--title <text>", "Short title for job list").option("--description <text>").option("--cron <expr>").option("--at <iso8601>").option("--every <interval>").option("--backend <name>").option("--model <name>").option("--thinking <level>").option("--timeout <seconds>", "Job timeout in seconds (30-3600)").option("--fallback <backend:model>", "Fallback backend:model (repeatable, max 3)", (val, prev) => [...prev, val], []).option("--timezone <tz>").action(async (id, opts) => {
|
|
22771
22948
|
const { cronEdit: cronEdit2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22772
22949
|
await cronEdit2(program.opts(), id, opts);
|
|
22773
22950
|
});
|