cc-claw 0.11.1 → 0.11.3
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 +433 -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.3" : (() => {
|
|
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,29 @@ function insertJob(params) {
|
|
|
2544
2552
|
);
|
|
2545
2553
|
return getJobById(Number(result.lastInsertRowid));
|
|
2546
2554
|
}
|
|
2555
|
+
function backfillJobTitles(database) {
|
|
2556
|
+
const rows = database.prepare(
|
|
2557
|
+
"SELECT id, description FROM jobs WHERE active = 1 AND (title IS NULL OR title LIKE 'No thinking%' OR title LIKE 'You must%' OR title LIKE 'You MUST%')"
|
|
2558
|
+
).all();
|
|
2559
|
+
if (rows.length === 0) return;
|
|
2560
|
+
const instructionLinePattern = /^(?:you\s+must|important|always|note|never|no\s+thinking|do\s+not|don't|remember|make\s+sure|ensure|critical|warning|before\s+you|first,?\s+you|use\s+the|call\s+the)\b[^.\n]*[.!]?\s*/i;
|
|
2561
|
+
for (const row of rows) {
|
|
2562
|
+
let text = row.description;
|
|
2563
|
+
let prevLen = 0;
|
|
2564
|
+
while (text.length !== prevLen && text.length > 0) {
|
|
2565
|
+
prevLen = text.length;
|
|
2566
|
+
text = text.replace(instructionLinePattern, "").trim();
|
|
2567
|
+
text = text.replace(/^\n+/, "").trim();
|
|
2568
|
+
}
|
|
2569
|
+
if (text.length < 10) text = row.description;
|
|
2570
|
+
text = text.replace(/https?:\/\/\S+/g, "").trim();
|
|
2571
|
+
text = text.replace(/\([^)]*\)\s*$/, "").trim();
|
|
2572
|
+
const firstLine = text.split(/\n/)[0].trim();
|
|
2573
|
+
const firstSentence = firstLine.match(/^.{5,55}(?:\b|[.!?])/)?.[0] ?? firstLine.slice(0, 55);
|
|
2574
|
+
const title = firstSentence.length > 55 ? firstSentence.slice(0, 52) + "\u2026" : firstSentence;
|
|
2575
|
+
database.prepare("UPDATE jobs SET title = ? WHERE id = ?").run(title, row.id);
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2547
2578
|
function mapJobRow(row) {
|
|
2548
2579
|
if (!row) return void 0;
|
|
2549
2580
|
row.fallbacks = row.fallbacks ? JSON.parse(row.fallbacks) : [];
|
|
@@ -2588,6 +2619,7 @@ function updateJob(id, fields) {
|
|
|
2588
2619
|
cron: "cron",
|
|
2589
2620
|
atTime: "at_time",
|
|
2590
2621
|
everyMs: "every_ms",
|
|
2622
|
+
title: "title",
|
|
2591
2623
|
description: "description",
|
|
2592
2624
|
backend: "backend",
|
|
2593
2625
|
model: "model",
|
|
@@ -3032,7 +3064,7 @@ var init_store5 = __esm({
|
|
|
3032
3064
|
ALL_TOOLS = ["Read", "Glob", "Grep", "Bash", "Write", "Edit", "WebFetch", "WebSearch", "Agent", "AskUserQuestion"];
|
|
3033
3065
|
JOB_SELECT = `
|
|
3034
3066
|
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,
|
|
3067
|
+
title, description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3036
3068
|
session_type as sessionType, channel, target, delivery_mode as deliveryMode,
|
|
3037
3069
|
timezone, enabled, active, created_at as createdAt, last_run_at as lastRunAt,
|
|
3038
3070
|
next_run_at as nextRunAt, consecutive_failures as consecutiveFailures
|
|
@@ -6566,8 +6598,45 @@ __export(analyze_exports, {
|
|
|
6566
6598
|
});
|
|
6567
6599
|
import { spawn as spawn4 } from "child_process";
|
|
6568
6600
|
import { createInterface as createInterface3 } from "readline";
|
|
6569
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
6601
|
+
import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
6570
6602
|
import { join as join10 } from "path";
|
|
6603
|
+
import { homedir as homedir4 } from "os";
|
|
6604
|
+
function discoverReflectionTargets() {
|
|
6605
|
+
const ccClawHome = join10(homedir4(), ".cc-claw");
|
|
6606
|
+
const targets = [];
|
|
6607
|
+
try {
|
|
6608
|
+
const skillsDir = join10(ccClawHome, "workspace", "skills");
|
|
6609
|
+
if (existsSync11(skillsDir)) {
|
|
6610
|
+
for (const entry of readdirSync5(skillsDir)) {
|
|
6611
|
+
const entryPath = join10(skillsDir, entry);
|
|
6612
|
+
if (!statSync3(entryPath).isDirectory()) continue;
|
|
6613
|
+
const skillFile = join10(entryPath, "SKILL.md");
|
|
6614
|
+
if (!existsSync11(skillFile)) continue;
|
|
6615
|
+
let desc = "skill";
|
|
6616
|
+
try {
|
|
6617
|
+
const content = readFileSync6(skillFile, "utf-8").slice(0, 500);
|
|
6618
|
+
const descMatch = content.match(/description:\s*["']?([^"'\n]+)/);
|
|
6619
|
+
if (descMatch) desc = descMatch[1].trim().slice(0, 80);
|
|
6620
|
+
} catch {
|
|
6621
|
+
}
|
|
6622
|
+
targets.push({ path: `workspace/skills/${entry}/SKILL.md`, description: desc });
|
|
6623
|
+
}
|
|
6624
|
+
}
|
|
6625
|
+
} catch {
|
|
6626
|
+
}
|
|
6627
|
+
try {
|
|
6628
|
+
const contextDir = join10(ccClawHome, "workspace", "context");
|
|
6629
|
+
if (existsSync11(contextDir)) {
|
|
6630
|
+
for (const entry of readdirSync5(contextDir)) {
|
|
6631
|
+
if (!entry.endsWith(".md")) continue;
|
|
6632
|
+
const name = entry.replace(/\.md$/, "");
|
|
6633
|
+
targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
} catch {
|
|
6637
|
+
}
|
|
6638
|
+
return targets;
|
|
6639
|
+
}
|
|
6571
6640
|
function buildAnalysisPrompt(params) {
|
|
6572
6641
|
const {
|
|
6573
6642
|
signals,
|
|
@@ -6627,7 +6696,31 @@ ${categoryList}`);
|
|
|
6627
6696
|
sections.push(`- [#${ins.id}] (${ins.category}) ${ins.insight}`);
|
|
6628
6697
|
}
|
|
6629
6698
|
}
|
|
6630
|
-
const
|
|
6699
|
+
const { availableTargets } = params;
|
|
6700
|
+
const targetList = [
|
|
6701
|
+
"identity/SOUL.md \u2014 personality, tone, stable behavioral rules, communication style",
|
|
6702
|
+
"identity/USER.md \u2014 user preferences, personal info, timezone, language, profile"
|
|
6703
|
+
];
|
|
6704
|
+
if (availableTargets) {
|
|
6705
|
+
for (const t of availableTargets) {
|
|
6706
|
+
targetList.push(`${t.path} \u2014 ${t.description}`);
|
|
6707
|
+
}
|
|
6708
|
+
}
|
|
6709
|
+
if (codebaseEnabled) {
|
|
6710
|
+
targetList.push("codebase \u2014 code-level recommendation (advisory only)");
|
|
6711
|
+
}
|
|
6712
|
+
sections.push(`[Target File Routing]
|
|
6713
|
+
Available targets:
|
|
6714
|
+
${targetList.map((t) => `- ${t}`).join("\n")}
|
|
6715
|
+
|
|
6716
|
+
Choose the MOST SPECIFIC target for each insight:
|
|
6717
|
+
- Workflow or process improvements \u2192 the relevant skill file
|
|
6718
|
+
- Tool usage patterns or domain-specific steps \u2192 the relevant skill file
|
|
6719
|
+
- User preference or profile info \u2192 USER.md
|
|
6720
|
+
- Personality, tone, general behavior \u2192 SOUL.md
|
|
6721
|
+
- Domain knowledge or reference material \u2192 a context file
|
|
6722
|
+
- If no matching skill/context file exists, fall back to SOUL.md or USER.md`);
|
|
6723
|
+
const targetOptions = targetList.map((t) => t.split(" \u2014 ")[0]).join(" | ");
|
|
6631
6724
|
sections.push(`[Output Format]
|
|
6632
6725
|
For each insight, output EXACTLY this format. Separate multiple insights with "---" on its own line.
|
|
6633
6726
|
|
|
@@ -6823,6 +6916,7 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6823
6916
|
const applied = getAppliedInsights(db3, chatId);
|
|
6824
6917
|
const rejected = getRejectedInsights(db3, chatId);
|
|
6825
6918
|
const codebaseEnabled = process.env.REFLECTION_CODEBASE_RECOMMENDATIONS === "1";
|
|
6919
|
+
const availableTargets = discoverReflectionTargets();
|
|
6826
6920
|
const prompt = buildAnalysisPrompt({
|
|
6827
6921
|
signals: signals.map((s) => ({
|
|
6828
6922
|
signalType: s.signalType,
|
|
@@ -6844,7 +6938,8 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6844
6938
|
insight: i.insight,
|
|
6845
6939
|
category: i.category
|
|
6846
6940
|
})),
|
|
6847
|
-
codebaseEnabled
|
|
6941
|
+
codebaseEnabled,
|
|
6942
|
+
availableTargets
|
|
6848
6943
|
});
|
|
6849
6944
|
const resolved = resolveReflectionAdapter(chatId);
|
|
6850
6945
|
if (!resolved) {
|
|
@@ -6948,7 +7043,7 @@ __export(apply_exports, {
|
|
|
6948
7043
|
isTargetAllowed: () => isTargetAllowed,
|
|
6949
7044
|
rollbackInsight: () => rollbackInsight
|
|
6950
7045
|
});
|
|
6951
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as
|
|
7046
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync3 } from "fs";
|
|
6952
7047
|
import { join as join11, dirname as dirname2 } from "path";
|
|
6953
7048
|
function isTargetAllowed(relativePath) {
|
|
6954
7049
|
if (relativePath.includes("..")) return false;
|
|
@@ -7016,7 +7111,7 @@ async function applyInsight(insightId) {
|
|
|
7016
7111
|
}
|
|
7017
7112
|
const absolutePath = join11(CC_CLAW_HOME, insight.targetFile);
|
|
7018
7113
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
7019
|
-
if (
|
|
7114
|
+
if (existsSync12(absolutePath)) {
|
|
7020
7115
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
7021
7116
|
const lineCount = currentContent.split("\n").length;
|
|
7022
7117
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
@@ -7036,7 +7131,7 @@ async function applyInsight(insightId) {
|
|
|
7036
7131
|
};
|
|
7037
7132
|
}
|
|
7038
7133
|
let original = "";
|
|
7039
|
-
if (
|
|
7134
|
+
if (existsSync12(absolutePath)) {
|
|
7040
7135
|
original = readFileSync7(absolutePath, "utf-8");
|
|
7041
7136
|
} else if (insight.proposedAction !== "create") {
|
|
7042
7137
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
@@ -7045,7 +7140,7 @@ async function applyInsight(insightId) {
|
|
|
7045
7140
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
7046
7141
|
try {
|
|
7047
7142
|
const parentDir = dirname2(absolutePath);
|
|
7048
|
-
if (!
|
|
7143
|
+
if (!existsSync12(parentDir)) {
|
|
7049
7144
|
mkdirSync3(parentDir, { recursive: true });
|
|
7050
7145
|
}
|
|
7051
7146
|
if (original) {
|
|
@@ -7151,7 +7246,7 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
7151
7246
|
if (!baseline) return 0;
|
|
7152
7247
|
let current = "";
|
|
7153
7248
|
try {
|
|
7154
|
-
if (
|
|
7249
|
+
if (existsSync12(absolutePath)) {
|
|
7155
7250
|
current = readFileSync7(absolutePath, "utf-8");
|
|
7156
7251
|
}
|
|
7157
7252
|
} catch {
|
|
@@ -7203,7 +7298,7 @@ __export(server_exports, {
|
|
|
7203
7298
|
});
|
|
7204
7299
|
import { createServer } from "http";
|
|
7205
7300
|
import { randomBytes } from "crypto";
|
|
7206
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as
|
|
7301
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync13 } from "fs";
|
|
7207
7302
|
function createSubAgentToken(agentId) {
|
|
7208
7303
|
const token = `sub:${agentId.slice(0, 8)}:${randomBytes(16).toString("hex")}`;
|
|
7209
7304
|
subAgentTokens.set(token, agentId);
|
|
@@ -7374,7 +7469,7 @@ function startDashboard() {
|
|
|
7374
7469
|
if (url.pathname === "/api/orchestrator/spawn" && req.method === "POST") {
|
|
7375
7470
|
try {
|
|
7376
7471
|
const body = JSON.parse(await readBody(req));
|
|
7377
|
-
if (body.cwd && !
|
|
7472
|
+
if (body.cwd && !existsSync13(body.cwd)) {
|
|
7378
7473
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
7379
7474
|
}
|
|
7380
7475
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -9674,18 +9769,18 @@ var init_wrap_backend = __esm({
|
|
|
9674
9769
|
});
|
|
9675
9770
|
|
|
9676
9771
|
// src/agents/runners/config-loader.ts
|
|
9677
|
-
import { readFileSync as readFileSync8, readdirSync as
|
|
9772
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync6, existsSync as existsSync14, mkdirSync as mkdirSync5, watchFile, unwatchFile } from "fs";
|
|
9678
9773
|
import { join as join13 } from "path";
|
|
9679
9774
|
import { execFileSync } from "child_process";
|
|
9680
9775
|
function resolveExecutable(config2) {
|
|
9681
|
-
if (
|
|
9776
|
+
if (existsSync14(config2.executable)) return config2.executable;
|
|
9682
9777
|
try {
|
|
9683
9778
|
return execFileSync("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
9684
9779
|
} catch {
|
|
9685
9780
|
}
|
|
9686
9781
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
9687
9782
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
9688
|
-
if (
|
|
9783
|
+
if (existsSync14(resolved)) return resolved;
|
|
9689
9784
|
}
|
|
9690
9785
|
return config2.executable;
|
|
9691
9786
|
}
|
|
@@ -9824,11 +9919,11 @@ function loadRunnerConfig(filePath) {
|
|
|
9824
9919
|
}
|
|
9825
9920
|
}
|
|
9826
9921
|
function loadAllRunnerConfigs() {
|
|
9827
|
-
if (!
|
|
9922
|
+
if (!existsSync14(RUNNERS_PATH)) {
|
|
9828
9923
|
mkdirSync5(RUNNERS_PATH, { recursive: true });
|
|
9829
9924
|
return [];
|
|
9830
9925
|
}
|
|
9831
|
-
const files =
|
|
9926
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9832
9927
|
const configs = [];
|
|
9833
9928
|
for (const file of files) {
|
|
9834
9929
|
const config2 = loadRunnerConfig(join13(RUNNERS_PATH, file));
|
|
@@ -9852,14 +9947,14 @@ function registerConfigRunners() {
|
|
|
9852
9947
|
return count;
|
|
9853
9948
|
}
|
|
9854
9949
|
function watchRunnerConfigs(onChange) {
|
|
9855
|
-
if (!
|
|
9950
|
+
if (!existsSync14(RUNNERS_PATH)) return;
|
|
9856
9951
|
for (const prev of watchedFiles) {
|
|
9857
|
-
if (!
|
|
9952
|
+
if (!existsSync14(prev)) {
|
|
9858
9953
|
unwatchFile(prev);
|
|
9859
9954
|
watchedFiles.delete(prev);
|
|
9860
9955
|
}
|
|
9861
9956
|
}
|
|
9862
|
-
const files =
|
|
9957
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9863
9958
|
for (const file of files) {
|
|
9864
9959
|
const fullPath = join13(RUNNERS_PATH, file);
|
|
9865
9960
|
if (watchedFiles.has(fullPath)) continue;
|
|
@@ -10568,7 +10663,7 @@ __export(discover_exports, {
|
|
|
10568
10663
|
});
|
|
10569
10664
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
10570
10665
|
import { createHash } from "crypto";
|
|
10571
|
-
import { homedir as
|
|
10666
|
+
import { homedir as homedir5 } from "os";
|
|
10572
10667
|
import { join as join14 } from "path";
|
|
10573
10668
|
function invalidateSkillCache() {
|
|
10574
10669
|
cachedSkills = null;
|
|
@@ -10587,7 +10682,7 @@ async function discoverAllSkills() {
|
|
|
10587
10682
|
const rawSkills = [];
|
|
10588
10683
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
10589
10684
|
for (const backendId of getAllBackendIds()) {
|
|
10590
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(
|
|
10685
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(homedir5(), `.${backendId}`, "skills")];
|
|
10591
10686
|
for (const dir of dirs) {
|
|
10592
10687
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
10593
10688
|
}
|
|
@@ -10718,15 +10813,15 @@ var init_discover = __esm({
|
|
|
10718
10813
|
init_backends();
|
|
10719
10814
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
10720
10815
|
BACKEND_SKILL_DIRS = {
|
|
10721
|
-
claude: [join14(
|
|
10722
|
-
gemini: [join14(
|
|
10816
|
+
claude: [join14(homedir5(), ".claude", "skills")],
|
|
10817
|
+
gemini: [join14(homedir5(), ".gemini", "skills")],
|
|
10723
10818
|
codex: [
|
|
10724
|
-
join14(
|
|
10725
|
-
join14(
|
|
10819
|
+
join14(homedir5(), ".agents", "skills"),
|
|
10820
|
+
join14(homedir5(), ".codex", "skills")
|
|
10726
10821
|
],
|
|
10727
10822
|
cursor: [
|
|
10728
|
-
join14(
|
|
10729
|
-
join14(
|
|
10823
|
+
join14(homedir5(), ".cursor", "skills"),
|
|
10824
|
+
join14(homedir5(), ".cursor", "skills-cursor")
|
|
10730
10825
|
]
|
|
10731
10826
|
};
|
|
10732
10827
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -10742,7 +10837,7 @@ __export(install_exports, {
|
|
|
10742
10837
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
10743
10838
|
});
|
|
10744
10839
|
import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
|
|
10745
|
-
import { existsSync as
|
|
10840
|
+
import { existsSync as existsSync15 } from "fs";
|
|
10746
10841
|
import { join as join15, basename } from "path";
|
|
10747
10842
|
import { execSync as execSync6 } from "child_process";
|
|
10748
10843
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
@@ -10761,7 +10856,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10761
10856
|
stdio: "pipe",
|
|
10762
10857
|
timeout: 3e4
|
|
10763
10858
|
});
|
|
10764
|
-
if (!
|
|
10859
|
+
if (!existsSync15(join15(tmpDir, ".git"))) {
|
|
10765
10860
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
10766
10861
|
}
|
|
10767
10862
|
const searchRoot = subPath ? join15(tmpDir, subPath) : tmpDir;
|
|
@@ -10771,7 +10866,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10771
10866
|
}
|
|
10772
10867
|
const skillFolderName = basename(skillDir);
|
|
10773
10868
|
const destDir = join15(SKILLS_PATH, skillFolderName);
|
|
10774
|
-
if (
|
|
10869
|
+
if (existsSync15(destDir)) {
|
|
10775
10870
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
10776
10871
|
}
|
|
10777
10872
|
await mkdir(destDir, { recursive: true });
|
|
@@ -10818,14 +10913,14 @@ function parseGitHubUrl(input) {
|
|
|
10818
10913
|
async function findSkillDir(root) {
|
|
10819
10914
|
const candidates = ["SKILL.md", "skill.md"];
|
|
10820
10915
|
for (const c of candidates) {
|
|
10821
|
-
if (
|
|
10916
|
+
if (existsSync15(join15(root, c))) return root;
|
|
10822
10917
|
}
|
|
10823
10918
|
try {
|
|
10824
10919
|
const entries = await readdir2(root, { withFileTypes: true });
|
|
10825
10920
|
for (const entry of entries) {
|
|
10826
10921
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
10827
10922
|
for (const c of candidates) {
|
|
10828
|
-
if (
|
|
10923
|
+
if (existsSync15(join15(root, entry.name, c))) {
|
|
10829
10924
|
return join15(root, entry.name);
|
|
10830
10925
|
}
|
|
10831
10926
|
}
|
|
@@ -10845,7 +10940,7 @@ async function findSkillDir(root) {
|
|
|
10845
10940
|
for (const sub of subEntries) {
|
|
10846
10941
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
10847
10942
|
for (const c of candidates) {
|
|
10848
|
-
if (
|
|
10943
|
+
if (existsSync15(join15(root, entry.name, sub.name, c))) {
|
|
10849
10944
|
return join15(root, entry.name, sub.name);
|
|
10850
10945
|
}
|
|
10851
10946
|
}
|
|
@@ -10864,7 +10959,7 @@ var init_install = __esm({
|
|
|
10864
10959
|
});
|
|
10865
10960
|
|
|
10866
10961
|
// src/bootstrap/profile.ts
|
|
10867
|
-
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as
|
|
10962
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync16 } from "fs";
|
|
10868
10963
|
import { join as join16 } from "path";
|
|
10869
10964
|
function hasActiveProfile(chatId) {
|
|
10870
10965
|
return activeProfiles.has(chatId);
|
|
@@ -10994,7 +11089,7 @@ function extractUserUpdates(text) {
|
|
|
10994
11089
|
return { cleanText, updates };
|
|
10995
11090
|
}
|
|
10996
11091
|
function appendToUserProfile(key, value) {
|
|
10997
|
-
if (!
|
|
11092
|
+
if (!existsSync16(USER_PATH2)) return;
|
|
10998
11093
|
const content = readFileSync9(USER_PATH2, "utf-8");
|
|
10999
11094
|
const line = `- **${key}**: ${value}`;
|
|
11000
11095
|
if (content.includes(line)) return;
|
|
@@ -11016,7 +11111,7 @@ var init_profile = __esm({
|
|
|
11016
11111
|
});
|
|
11017
11112
|
|
|
11018
11113
|
// src/bootstrap/heartbeat.ts
|
|
11019
|
-
import { readFileSync as readFileSync10, existsSync as
|
|
11114
|
+
import { readFileSync as readFileSync10, existsSync as existsSync17 } from "fs";
|
|
11020
11115
|
import { join as join17 } from "path";
|
|
11021
11116
|
function initHeartbeat(channelReg) {
|
|
11022
11117
|
registry2 = channelReg;
|
|
@@ -11155,7 +11250,7 @@ ${healthLines.join("\n")}`);
|
|
|
11155
11250
|
sections.push(`[Active watches]
|
|
11156
11251
|
${watchLines.join("\n")}`);
|
|
11157
11252
|
}
|
|
11158
|
-
if (
|
|
11253
|
+
if (existsSync17(HEARTBEAT_MD_PATH)) {
|
|
11159
11254
|
try {
|
|
11160
11255
|
const custom = readFileSync10(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
11161
11256
|
if (custom) {
|
|
@@ -11386,7 +11481,7 @@ var init_classify = __esm({
|
|
|
11386
11481
|
});
|
|
11387
11482
|
|
|
11388
11483
|
// src/media/image-gen.ts
|
|
11389
|
-
import { mkdirSync as mkdirSync6, existsSync as
|
|
11484
|
+
import { mkdirSync as mkdirSync6, existsSync as existsSync18 } from "fs";
|
|
11390
11485
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
11391
11486
|
import { join as join18 } from "path";
|
|
11392
11487
|
async function generateImage(prompt) {
|
|
@@ -11435,7 +11530,7 @@ async function generateImage(prompt) {
|
|
|
11435
11530
|
if (!imageData) {
|
|
11436
11531
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
11437
11532
|
}
|
|
11438
|
-
if (!
|
|
11533
|
+
if (!existsSync18(IMAGE_OUTPUT_DIR)) {
|
|
11439
11534
|
mkdirSync6(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
11440
11535
|
}
|
|
11441
11536
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
@@ -12166,11 +12261,31 @@ async function finalizeJob(chatId, channel) {
|
|
|
12166
12261
|
const pending = pendingJobs.get(chatId);
|
|
12167
12262
|
if (!pending) return;
|
|
12168
12263
|
const editJobId = pending._editJobId;
|
|
12264
|
+
let title = pending.title ?? null;
|
|
12265
|
+
if (!title && !editJobId) {
|
|
12266
|
+
try {
|
|
12267
|
+
const { askAgent: askAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
12268
|
+
const resp = await askAgent2(chatId, `Summarize this scheduled task in 5-8 words for a job list title. Output ONLY the title, nothing else:
|
|
12269
|
+
|
|
12270
|
+
${pending.task}`, {
|
|
12271
|
+
bootstrapTier: "chat",
|
|
12272
|
+
maxTurns: 1,
|
|
12273
|
+
timeoutMs: 15e3
|
|
12274
|
+
});
|
|
12275
|
+
const generated = resp.text?.trim().replace(/^["']|["']$/g, "");
|
|
12276
|
+
if (generated && generated.length <= 60) title = generated;
|
|
12277
|
+
} catch {
|
|
12278
|
+
}
|
|
12279
|
+
if (!title) {
|
|
12280
|
+
title = pending.task.length > 60 ? pending.task.slice(0, 57) + "\u2026" : pending.task;
|
|
12281
|
+
}
|
|
12282
|
+
}
|
|
12169
12283
|
const jobParams = {
|
|
12170
12284
|
scheduleType: pending.scheduleType ?? "cron",
|
|
12171
12285
|
cron: pending.cron,
|
|
12172
12286
|
atTime: pending.at ?? null,
|
|
12173
12287
|
everyMs: pending.everyMs ?? null,
|
|
12288
|
+
title,
|
|
12174
12289
|
description: pending.task,
|
|
12175
12290
|
backend: pending.backend ?? null,
|
|
12176
12291
|
model: pending.model ?? null,
|
|
@@ -12194,6 +12309,7 @@ async function finalizeJob(chatId, channel) {
|
|
|
12194
12309
|
chatId,
|
|
12195
12310
|
`Job #${editJobId} updated!
|
|
12196
12311
|
|
|
12312
|
+
Title: ${jobParams.title ?? "\u2014"}
|
|
12197
12313
|
Task: ${jobParams.description}
|
|
12198
12314
|
Schedule: ${jobParams.cron ?? "N/A"}
|
|
12199
12315
|
Timezone: ${jobParams.timezone}`,
|
|
@@ -12208,6 +12324,7 @@ Timezone: ${jobParams.timezone}`,
|
|
|
12208
12324
|
chatId,
|
|
12209
12325
|
`Job #${job.id} created!
|
|
12210
12326
|
|
|
12327
|
+
Title: ${job.title ?? "\u2014"}
|
|
12211
12328
|
Task: ${job.description}
|
|
12212
12329
|
Schedule: ${job.cron ?? "N/A"}
|
|
12213
12330
|
Timezone: ${job.timezone}
|
|
@@ -12808,8 +12925,10 @@ var init_propose = __esm({
|
|
|
12808
12925
|
|
|
12809
12926
|
// src/router.ts
|
|
12810
12927
|
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
|
|
12928
|
+
import { existsSync as existsSync19 } from "fs";
|
|
12811
12929
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
12812
12930
|
import { resolve as resolvePath, join as join19 } from "path";
|
|
12931
|
+
import { homedir as homedir6 } from "os";
|
|
12813
12932
|
function parseMcpListOutput(output2) {
|
|
12814
12933
|
const results = [];
|
|
12815
12934
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14527,8 +14646,8 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14527
14646
|
lines.push(` \u2705 <b>cc-claw</b> <i>Agent orchestrator (spawn, tasks, inbox)</i>`);
|
|
14528
14647
|
}
|
|
14529
14648
|
const { execFile: execFile5 } = await import("child_process");
|
|
14530
|
-
const { homedir:
|
|
14531
|
-
const discoveryCwd =
|
|
14649
|
+
const { homedir: homedir9 } = await import("os");
|
|
14650
|
+
const discoveryCwd = homedir9();
|
|
14532
14651
|
const runnerResults = await Promise.allSettled(
|
|
14533
14652
|
getAllRunners().map((runner) => {
|
|
14534
14653
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -14911,26 +15030,6 @@ async function handleText(msg, channel) {
|
|
|
14911
15030
|
await handleWizardText(chatId, text, channel);
|
|
14912
15031
|
return;
|
|
14913
15032
|
}
|
|
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
15033
|
const rememberMatch = text.match(/^remember\s+(?:that\s+)?(.+)/i);
|
|
14935
15034
|
if (rememberMatch) {
|
|
14936
15035
|
const content = rememberMatch[1];
|
|
@@ -15158,65 +15257,6 @@ After installing, restart the service: cc-claw service restart`;
|
|
|
15158
15257
|
}
|
|
15159
15258
|
return `Error: ${msg}`;
|
|
15160
15259
|
}
|
|
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
15260
|
async function handleSideQuest(parentChatId, msg, channel) {
|
|
15221
15261
|
const sqId = `sq:${parentChatId}:${randomUUID3()}`;
|
|
15222
15262
|
const active = activeSideQuests.get(parentChatId) ?? /* @__PURE__ */ new Set();
|
|
@@ -15791,7 +15831,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15791
15831
|
pageSize: 10,
|
|
15792
15832
|
callbackPrefix: "job:",
|
|
15793
15833
|
renderItem: (j) => ({
|
|
15794
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15834
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15795
15835
|
data: `job:view:${j.id}`,
|
|
15796
15836
|
style: "primary"
|
|
15797
15837
|
}),
|
|
@@ -15801,7 +15841,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15801
15841
|
for (const j of pageJobs) {
|
|
15802
15842
|
const emoji = getJobStatusEmoji(j);
|
|
15803
15843
|
const schedule2 = getJobScheduleText(j);
|
|
15804
|
-
const desc = j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description;
|
|
15844
|
+
const desc = j.title ?? (j.description.length > 24 ? j.description.slice(0, 24) + "\u2026" : j.description);
|
|
15805
15845
|
lines.push(`${emoji} ${desc} \xB7 ${schedule2}`);
|
|
15806
15846
|
}
|
|
15807
15847
|
lines.push("");
|
|
@@ -15836,8 +15876,9 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15836
15876
|
const runs = getJobRuns(jobId, 1);
|
|
15837
15877
|
const lastRunStatus = runs.length > 0 ? runs[0].status : null;
|
|
15838
15878
|
const lines = [
|
|
15839
|
-
`Job #${job.id}: ${job.description}`,
|
|
15879
|
+
`Job #${job.id}: ${job.title ?? job.description}`,
|
|
15840
15880
|
buildSectionHeader("", 22),
|
|
15881
|
+
...job.title ? [`Task: ${job.description}`] : [],
|
|
15841
15882
|
`Runs: ${schedule2}${tz}`,
|
|
15842
15883
|
`Backend: ${backend2} | Model: ${model2}`,
|
|
15843
15884
|
`Last run: ${lastRun}${lastRunStatus ? ` (${lastRunStatus})` : ""}`,
|
|
@@ -15944,7 +15985,7 @@ async function sendJobPicker(chatId, channel, action) {
|
|
|
15944
15985
|
const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
|
|
15945
15986
|
const style = action === "run" ? "success" : action === "cancel" ? "danger" : void 0;
|
|
15946
15987
|
const buttons = jobs.map((j) => [{
|
|
15947
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15988
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15948
15989
|
data: action === "cancel" ? `job:cancel:${j.id}` : `job:${action}:${j.id}`,
|
|
15949
15990
|
...style ? { style } : {}
|
|
15950
15991
|
}]);
|
|
@@ -16602,24 +16643,159 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16602
16643
|
}
|
|
16603
16644
|
case "discuss": {
|
|
16604
16645
|
const insId = parseInt(idStr, 10);
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16646
|
+
await channel.sendKeyboard(chatId, [
|
|
16647
|
+
"What would you like to do with this proposal?",
|
|
16648
|
+
"",
|
|
16649
|
+
"Why this file? \u2014 ask the AI to explain its reasoning",
|
|
16650
|
+
"Retarget \u2014 move this change to a different file (e.g., a skill instead of SOUL.md)",
|
|
16651
|
+
"Revise \u2014 ask the AI to rewrite the proposed change"
|
|
16652
|
+
].join("\n"), [
|
|
16653
|
+
[
|
|
16654
|
+
{ label: "Why this file?", data: `evolve:discuss-why:${insId}`, style: "primary" },
|
|
16655
|
+
{ label: "Retarget", data: `evolve:discuss-retarget:${insId}` }
|
|
16656
|
+
],
|
|
16657
|
+
[
|
|
16658
|
+
{ label: "Revise the change", data: `evolve:discuss-revise:${insId}` },
|
|
16659
|
+
{ label: "Back", data: `evolve:discuss-back:${insId}` }
|
|
16660
|
+
]
|
|
16608
16661
|
]);
|
|
16609
16662
|
break;
|
|
16610
16663
|
}
|
|
16611
|
-
case "discuss-
|
|
16612
|
-
|
|
16613
|
-
const {
|
|
16614
|
-
const
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16664
|
+
case "discuss-why": {
|
|
16665
|
+
const { getInsightById: gwIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16666
|
+
const { getDb: gwDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16667
|
+
const gwInsight = gwIns(gwDb(), parseInt(idStr, 10));
|
|
16668
|
+
if (!gwInsight) {
|
|
16669
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16670
|
+
break;
|
|
16671
|
+
}
|
|
16672
|
+
await channel.sendTyping?.(chatId);
|
|
16673
|
+
const whyPrompt = [
|
|
16674
|
+
`Explain in 2-3 sentences why you chose "${gwInsight.targetFile}" as the target file for this insight:`,
|
|
16675
|
+
`"${gwInsight.insight}"`,
|
|
16676
|
+
`Consider what other files could work (skills, context files, USER.md) and explain your reasoning.`
|
|
16677
|
+
].join("\n");
|
|
16678
|
+
try {
|
|
16679
|
+
const whyResp = await askAgent(chatId, whyPrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
|
|
16680
|
+
await channel.sendText(chatId, whyResp.text ?? "No response.");
|
|
16681
|
+
} catch (e) {
|
|
16682
|
+
await channel.sendText(chatId, `Error: ${e.message}`, { parseMode: "plain" });
|
|
16683
|
+
}
|
|
16684
|
+
await channel.sendKeyboard(chatId, "What next?", [
|
|
16685
|
+
[
|
|
16686
|
+
{ label: "OK, Apply", data: `evolve:apply:${idStr}`, style: "success" },
|
|
16687
|
+
{ label: "Retarget instead", data: `evolve:discuss-retarget:${idStr}` }
|
|
16688
|
+
],
|
|
16689
|
+
[
|
|
16690
|
+
{ label: "Reject", data: `evolve:reject:${idStr}`, style: "danger" },
|
|
16691
|
+
{ label: "Back", data: `evolve:discuss-back:${idStr}` }
|
|
16692
|
+
]
|
|
16693
|
+
]);
|
|
16694
|
+
break;
|
|
16695
|
+
}
|
|
16696
|
+
case "discuss-retarget": {
|
|
16697
|
+
const { getInsightById: rtIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16698
|
+
const { getDb: rtDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16699
|
+
const rtInsight = rtIns(rtDb(), parseInt(idStr, 10));
|
|
16700
|
+
if (!rtInsight) {
|
|
16701
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16702
|
+
break;
|
|
16703
|
+
}
|
|
16704
|
+
const currentTarget = rtInsight.targetFile ?? "unknown";
|
|
16705
|
+
const targets = [
|
|
16706
|
+
{ label: "SOUL.md", path: "identity/SOUL.md" },
|
|
16707
|
+
{ label: "USER.md", path: "identity/USER.md" }
|
|
16708
|
+
];
|
|
16709
|
+
const skillDirs = [
|
|
16710
|
+
join19(homedir6(), ".cc-claw", "workspace", "skills")
|
|
16711
|
+
];
|
|
16712
|
+
try {
|
|
16713
|
+
const { readdirSync: readdirSync7, statSync: statSync9 } = await import("fs");
|
|
16714
|
+
for (const dir of skillDirs) {
|
|
16715
|
+
if (!existsSync19(dir)) continue;
|
|
16716
|
+
for (const entry of readdirSync7(dir)) {
|
|
16717
|
+
if (statSync9(join19(dir, entry)).isDirectory()) {
|
|
16718
|
+
targets.push({ label: `skills/${entry}`, path: `workspace/skills/${entry}/SKILL.md` });
|
|
16719
|
+
}
|
|
16720
|
+
}
|
|
16721
|
+
}
|
|
16722
|
+
} catch {
|
|
16723
|
+
}
|
|
16724
|
+
const rows = targets.filter((t) => t.path !== currentTarget).map((t) => [{ label: t.label, data: `evolve:discuss-retarget-to:${idStr}:${t.path}` }]);
|
|
16725
|
+
rows.push([{ label: "Cancel", data: `evolve:discuss-back:${idStr}` }]);
|
|
16726
|
+
await channel.sendKeyboard(chatId, `Current target: ${currentTarget}
|
|
16727
|
+
|
|
16728
|
+
Pick a different file for this change. Identity files (SOUL/USER) shape personality; skills teach specific workflows.`, rows);
|
|
16729
|
+
break;
|
|
16730
|
+
}
|
|
16731
|
+
case "discuss-retarget-to": {
|
|
16732
|
+
const retargetParts = data.split(":");
|
|
16733
|
+
const rtId = parseInt(retargetParts[2], 10);
|
|
16734
|
+
const newPath = retargetParts.slice(3).join(":");
|
|
16735
|
+
const { getInsightById: rt2Ins, updateInsightProposal: rt2Update } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16736
|
+
const { formatProposalCard: rt2Card, buildProposalKeyboard: rt2Kb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16737
|
+
const { getDb: rt2Db } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16738
|
+
const rt2Insight = rt2Ins(rt2Db(), rtId);
|
|
16739
|
+
if (!rt2Insight) {
|
|
16740
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16741
|
+
break;
|
|
16742
|
+
}
|
|
16743
|
+
rt2Update(rt2Db(), rtId, newPath, rt2Insight.proposedDiff, rt2Insight.proposedAction);
|
|
16744
|
+
const updatedIns = rt2Ins(rt2Db(), rtId);
|
|
16745
|
+
if (updatedIns) {
|
|
16746
|
+
const card = rt2Card(updatedIns);
|
|
16747
|
+
const kb = rt2Kb(updatedIns.id, updatedIns.category);
|
|
16748
|
+
await channel.sendKeyboard(chatId, `Retargeted to ${newPath}. Updated proposal:
|
|
16749
|
+
|
|
16750
|
+
` + card, kb);
|
|
16751
|
+
}
|
|
16752
|
+
break;
|
|
16753
|
+
}
|
|
16754
|
+
case "discuss-revise": {
|
|
16755
|
+
const { getInsightById: rvIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16756
|
+
const { getDb: rvDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16757
|
+
const rvInsight = rvIns(rvDb(), parseInt(idStr, 10));
|
|
16758
|
+
if (!rvInsight) {
|
|
16759
|
+
await channel.sendText(chatId, "Proposal not found.", { parseMode: "plain" });
|
|
16760
|
+
break;
|
|
16761
|
+
}
|
|
16762
|
+
await channel.sendTyping?.(chatId);
|
|
16763
|
+
const revisePrompt = [
|
|
16764
|
+
`Revise this proposed change to be more specific and actionable:`,
|
|
16765
|
+
`Current insight: "${rvInsight.insight}"`,
|
|
16766
|
+
`Current diff: ${rvInsight.proposedDiff ?? "none"}`,
|
|
16767
|
+
`Target: ${rvInsight.targetFile}`,
|
|
16768
|
+
``,
|
|
16769
|
+
`Output ONLY the revised diff lines (starting with + for additions, - for removals). No explanation.`
|
|
16770
|
+
].join("\n");
|
|
16771
|
+
try {
|
|
16772
|
+
const rvResp = await askAgent(chatId, revisePrompt, { bootstrapTier: "chat", maxTurns: 1, timeoutMs: 6e4 });
|
|
16773
|
+
const newDiff = rvResp.text?.trim() ?? rvInsight.proposedDiff;
|
|
16774
|
+
if (newDiff) {
|
|
16775
|
+
const { updateInsightProposal: rvUpdate } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16776
|
+
rvUpdate(rvDb(), parseInt(idStr, 10), rvInsight.targetFile ?? "", newDiff, rvInsight.proposedAction);
|
|
16777
|
+
}
|
|
16778
|
+
const updatedRv = rvIns(rvDb(), parseInt(idStr, 10));
|
|
16779
|
+
if (updatedRv) {
|
|
16780
|
+
const { formatProposalCard: rvCard, buildProposalKeyboard: rvKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16781
|
+
const card = rvCard(updatedRv);
|
|
16782
|
+
const kb = rvKb(updatedRv.id, updatedRv.category);
|
|
16783
|
+
await channel.sendKeyboard(chatId, "Revised proposal:\n\n" + card, kb);
|
|
16784
|
+
}
|
|
16785
|
+
} catch (e) {
|
|
16786
|
+
await channel.sendText(chatId, `Revision error: ${e.message}`, { parseMode: "plain" });
|
|
16787
|
+
}
|
|
16788
|
+
break;
|
|
16789
|
+
}
|
|
16790
|
+
case "discuss-back": {
|
|
16791
|
+
const { getInsightById: bkIns } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16792
|
+
const { formatProposalCard: bkCard, buildProposalKeyboard: bkKb } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
16793
|
+
const { getDb: bkDb } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16794
|
+
const bkInsight = bkIns(bkDb(), parseInt(idStr, 10));
|
|
16795
|
+
if (bkInsight && bkInsight.status === "pending") {
|
|
16796
|
+
const card = bkCard(bkInsight);
|
|
16797
|
+
const kb = bkKb(bkInsight.id, bkInsight.category);
|
|
16798
|
+
await channel.sendKeyboard(chatId, card, kb);
|
|
16623
16799
|
}
|
|
16624
16800
|
break;
|
|
16625
16801
|
}
|
|
@@ -16681,13 +16857,13 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16681
16857
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16682
16858
|
const current = getReflectionStatus2(getDb2(), chatId);
|
|
16683
16859
|
if (current === "frozen") {
|
|
16684
|
-
const { readFileSync: readFileSync21, existsSync:
|
|
16860
|
+
const { readFileSync: readFileSync21, existsSync: existsSync47 } = await import("fs");
|
|
16685
16861
|
const { join: join26 } = await import("path");
|
|
16686
16862
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
16687
16863
|
const soulPath = join26(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16688
16864
|
const userPath = join26(CC_CLAW_HOME3, "identity/USER.md");
|
|
16689
|
-
const soul =
|
|
16690
|
-
const user =
|
|
16865
|
+
const soul = existsSync47(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
|
|
16866
|
+
const user = existsSync47(userPath) ? readFileSync21(userPath, "utf-8") : "";
|
|
16691
16867
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
16692
16868
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16693
16869
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -17281,7 +17457,7 @@ Use /skills <page> to navigate (e.g. /skills 2)` : "";
|
|
|
17281
17457
|
const header2 = totalPages > 1 ? `${skills2.length} skills (page ${safePage}/${totalPages}). Select one to invoke:` : `${skills2.length} skills available. Select one to invoke:`;
|
|
17282
17458
|
await channel.sendKeyboard(chatId, header2, buttons);
|
|
17283
17459
|
}
|
|
17284
|
-
var PERM_MODES, VERBOSE_LEVELS, HELP_CATEGORIES, USAGE_WINDOW_MAP, MEDIA_INCOMING_PATH, TONE_PATTERNS, pendingInterrupts, bypassBusyCheck, activeSideQuests, MAX_SIDE_QUESTS,
|
|
17460
|
+
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
17461
|
var init_router = __esm({
|
|
17286
17462
|
"src/router.ts"() {
|
|
17287
17463
|
"use strict";
|
|
@@ -17422,7 +17598,6 @@ var init_router = __esm({
|
|
|
17422
17598
|
bypassBusyCheck = /* @__PURE__ */ new Set();
|
|
17423
17599
|
activeSideQuests = /* @__PURE__ */ new Map();
|
|
17424
17600
|
MAX_SIDE_QUESTS = 2;
|
|
17425
|
-
activeProposalDiscussion = /* @__PURE__ */ new Map();
|
|
17426
17601
|
pendingFallbackMessages = /* @__PURE__ */ new Map();
|
|
17427
17602
|
dashboardClawWarnings = /* @__PURE__ */ new Map();
|
|
17428
17603
|
pendingSummaryUndo = /* @__PURE__ */ new Map();
|
|
@@ -17522,19 +17697,19 @@ var init_router = __esm({
|
|
|
17522
17697
|
});
|
|
17523
17698
|
|
|
17524
17699
|
// src/skills/bootstrap.ts
|
|
17525
|
-
import { existsSync as
|
|
17700
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17526
17701
|
import { readdir as readdir4, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
|
|
17527
17702
|
import { join as join20, dirname as dirname3 } from "path";
|
|
17528
17703
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17529
17704
|
async function copyAgentManifestSkills() {
|
|
17530
|
-
if (!
|
|
17705
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
17531
17706
|
try {
|
|
17532
17707
|
const entries = await readdir4(PKG_SKILLS, { withFileTypes: true });
|
|
17533
17708
|
for (const entry of entries) {
|
|
17534
17709
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
17535
17710
|
const src = join20(PKG_SKILLS, entry.name);
|
|
17536
17711
|
const dest = join20(SKILLS_PATH, entry.name);
|
|
17537
|
-
if (
|
|
17712
|
+
if (existsSync20(dest)) continue;
|
|
17538
17713
|
await copyFile(src, dest);
|
|
17539
17714
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
17540
17715
|
}
|
|
@@ -17545,7 +17720,7 @@ async function copyAgentManifestSkills() {
|
|
|
17545
17720
|
async function bootstrapSkills() {
|
|
17546
17721
|
await copyAgentManifestSkills();
|
|
17547
17722
|
const usmDir = join20(SKILLS_PATH, USM_DIR_NAME);
|
|
17548
|
-
if (
|
|
17723
|
+
if (existsSync20(usmDir)) return;
|
|
17549
17724
|
try {
|
|
17550
17725
|
const entries = await readdir4(SKILLS_PATH);
|
|
17551
17726
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -17568,7 +17743,7 @@ async function bootstrapSkills() {
|
|
|
17568
17743
|
}
|
|
17569
17744
|
async function patchUsmForCcClaw(usmDir) {
|
|
17570
17745
|
const skillPath = join20(usmDir, "SKILL.md");
|
|
17571
|
-
if (!
|
|
17746
|
+
if (!existsSync20(skillPath)) return;
|
|
17572
17747
|
try {
|
|
17573
17748
|
let content = await readFile6(skillPath, "utf-8");
|
|
17574
17749
|
let patched = false;
|
|
@@ -17828,13 +18003,13 @@ __export(ai_skill_exports, {
|
|
|
17828
18003
|
generateAiSkill: () => generateAiSkill,
|
|
17829
18004
|
installAiSkill: () => installAiSkill
|
|
17830
18005
|
});
|
|
17831
|
-
import { existsSync as
|
|
18006
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
|
|
17832
18007
|
import { join as join21 } from "path";
|
|
17833
|
-
import { homedir as
|
|
18008
|
+
import { homedir as homedir7 } from "os";
|
|
17834
18009
|
function generateAiSkill() {
|
|
17835
18010
|
const version = VERSION;
|
|
17836
18011
|
let systemState = "";
|
|
17837
|
-
if (
|
|
18012
|
+
if (existsSync21(DB_PATH)) {
|
|
17838
18013
|
try {
|
|
17839
18014
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
17840
18015
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -18250,11 +18425,11 @@ var init_ai_skill = __esm({
|
|
|
18250
18425
|
init_paths();
|
|
18251
18426
|
init_version();
|
|
18252
18427
|
BACKEND_SKILL_DIRS2 = {
|
|
18253
|
-
"cc-claw": [join21(
|
|
18254
|
-
claude: [join21(
|
|
18255
|
-
gemini: [join21(
|
|
18256
|
-
codex: [join21(
|
|
18257
|
-
cursor: [join21(
|
|
18428
|
+
"cc-claw": [join21(homedir7(), ".cc-claw", "workspace", "skills")],
|
|
18429
|
+
claude: [join21(homedir7(), ".claude", "skills")],
|
|
18430
|
+
gemini: [join21(homedir7(), ".gemini", "skills")],
|
|
18431
|
+
codex: [join21(homedir7(), ".agents", "skills")],
|
|
18432
|
+
cursor: [join21(homedir7(), ".cursor", "skills"), join21(homedir7(), ".cursor", "skills-cursor")]
|
|
18258
18433
|
};
|
|
18259
18434
|
}
|
|
18260
18435
|
});
|
|
@@ -18264,7 +18439,7 @@ var index_exports = {};
|
|
|
18264
18439
|
__export(index_exports, {
|
|
18265
18440
|
main: () => main
|
|
18266
18441
|
});
|
|
18267
|
-
import { mkdirSync as mkdirSync8, existsSync as
|
|
18442
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync22, renameSync, statSync as statSync4, readFileSync as readFileSync12 } from "fs";
|
|
18268
18443
|
import { join as join22 } from "path";
|
|
18269
18444
|
import dotenv from "dotenv";
|
|
18270
18445
|
function migrateLayout() {
|
|
@@ -18278,7 +18453,7 @@ function migrateLayout() {
|
|
|
18278
18453
|
[join22(CC_CLAW_HOME, "cc-claw.error.log.1"), join22(LOGS_PATH, "cc-claw.error.log.1")]
|
|
18279
18454
|
];
|
|
18280
18455
|
for (const [from, to] of moves) {
|
|
18281
|
-
if (
|
|
18456
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
18282
18457
|
try {
|
|
18283
18458
|
renameSync(from, to);
|
|
18284
18459
|
} catch {
|
|
@@ -18289,7 +18464,7 @@ function migrateLayout() {
|
|
|
18289
18464
|
function rotateLogs() {
|
|
18290
18465
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
18291
18466
|
try {
|
|
18292
|
-
const { size } =
|
|
18467
|
+
const { size } = statSync4(file);
|
|
18293
18468
|
if (size > LOG_MAX_BYTES) {
|
|
18294
18469
|
const archivePath = `${file}.1`;
|
|
18295
18470
|
try {
|
|
@@ -18485,10 +18660,10 @@ var init_index = __esm({
|
|
|
18485
18660
|
init_bootstrap2();
|
|
18486
18661
|
init_health3();
|
|
18487
18662
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
18488
|
-
if (!
|
|
18663
|
+
if (!existsSync22(dir)) mkdirSync8(dir, { recursive: true });
|
|
18489
18664
|
}
|
|
18490
18665
|
migrateLayout();
|
|
18491
|
-
if (
|
|
18666
|
+
if (existsSync22(ENV_PATH)) {
|
|
18492
18667
|
dotenv.config({ path: ENV_PATH });
|
|
18493
18668
|
} else {
|
|
18494
18669
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -18509,12 +18684,12 @@ __export(api_client_exports, {
|
|
|
18509
18684
|
apiPost: () => apiPost,
|
|
18510
18685
|
isDaemonRunning: () => isDaemonRunning
|
|
18511
18686
|
});
|
|
18512
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
18687
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
18513
18688
|
import { request as httpRequest } from "http";
|
|
18514
18689
|
function getToken() {
|
|
18515
18690
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
18516
18691
|
try {
|
|
18517
|
-
if (
|
|
18692
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
18518
18693
|
} catch {
|
|
18519
18694
|
}
|
|
18520
18695
|
return null;
|
|
@@ -18609,9 +18784,9 @@ __export(service_exports, {
|
|
|
18609
18784
|
serviceStatus: () => serviceStatus,
|
|
18610
18785
|
uninstallService: () => uninstallService
|
|
18611
18786
|
});
|
|
18612
|
-
import { existsSync as
|
|
18787
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
18613
18788
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
18614
|
-
import { homedir as
|
|
18789
|
+
import { homedir as homedir8, platform } from "os";
|
|
18615
18790
|
import { join as join23, dirname as dirname4 } from "path";
|
|
18616
18791
|
function resolveExecutable2(name) {
|
|
18617
18792
|
try {
|
|
@@ -18622,7 +18797,7 @@ function resolveExecutable2(name) {
|
|
|
18622
18797
|
}
|
|
18623
18798
|
function getPathDirs() {
|
|
18624
18799
|
const nodeBin = dirname4(process.execPath);
|
|
18625
|
-
const home =
|
|
18800
|
+
const home = homedir8();
|
|
18626
18801
|
const dirs = /* @__PURE__ */ new Set([
|
|
18627
18802
|
nodeBin,
|
|
18628
18803
|
join23(home, ".local", "bin"),
|
|
@@ -18640,7 +18815,7 @@ function getPathDirs() {
|
|
|
18640
18815
|
function generatePlist() {
|
|
18641
18816
|
const ccClawBin = resolveExecutable2("cc-claw");
|
|
18642
18817
|
const pathDirs = getPathDirs();
|
|
18643
|
-
const home =
|
|
18818
|
+
const home = homedir8();
|
|
18644
18819
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
18645
18820
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
18646
18821
|
<plist version="1.0">
|
|
@@ -18684,9 +18859,9 @@ function generatePlist() {
|
|
|
18684
18859
|
}
|
|
18685
18860
|
function installMacOS() {
|
|
18686
18861
|
const agentsDir = dirname4(PLIST_PATH);
|
|
18687
|
-
if (!
|
|
18688
|
-
if (!
|
|
18689
|
-
if (
|
|
18862
|
+
if (!existsSync24(agentsDir)) mkdirSync9(agentsDir, { recursive: true });
|
|
18863
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18864
|
+
if (existsSync24(PLIST_PATH)) {
|
|
18690
18865
|
try {
|
|
18691
18866
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
18692
18867
|
} catch {
|
|
@@ -18698,7 +18873,7 @@ function installMacOS() {
|
|
|
18698
18873
|
console.log(" Service loaded and starting.");
|
|
18699
18874
|
}
|
|
18700
18875
|
function uninstallMacOS() {
|
|
18701
|
-
if (!
|
|
18876
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
18702
18877
|
console.log(" No service found to uninstall.");
|
|
18703
18878
|
return;
|
|
18704
18879
|
}
|
|
@@ -18765,15 +18940,15 @@ Restart=on-failure
|
|
|
18765
18940
|
RestartSec=10
|
|
18766
18941
|
WorkingDirectory=${CC_CLAW_HOME}
|
|
18767
18942
|
Environment=PATH=${pathDirs}
|
|
18768
|
-
Environment=HOME=${
|
|
18943
|
+
Environment=HOME=${homedir8()}
|
|
18769
18944
|
|
|
18770
18945
|
[Install]
|
|
18771
18946
|
WantedBy=default.target
|
|
18772
18947
|
`;
|
|
18773
18948
|
}
|
|
18774
18949
|
function installLinux() {
|
|
18775
|
-
if (!
|
|
18776
|
-
if (!
|
|
18950
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync9(SYSTEMD_DIR, { recursive: true });
|
|
18951
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18777
18952
|
writeFileSync7(UNIT_PATH, generateUnit());
|
|
18778
18953
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
18779
18954
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -18782,7 +18957,7 @@ function installLinux() {
|
|
|
18782
18957
|
console.log(" Service enabled and started.");
|
|
18783
18958
|
}
|
|
18784
18959
|
function uninstallLinux() {
|
|
18785
|
-
if (!
|
|
18960
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
18786
18961
|
console.log(" No service found to uninstall.");
|
|
18787
18962
|
return;
|
|
18788
18963
|
}
|
|
@@ -18807,7 +18982,7 @@ function statusLinux() {
|
|
|
18807
18982
|
}
|
|
18808
18983
|
}
|
|
18809
18984
|
function installService() {
|
|
18810
|
-
if (!
|
|
18985
|
+
if (!existsSync24(join23(CC_CLAW_HOME, ".env"))) {
|
|
18811
18986
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
18812
18987
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
18813
18988
|
process.exitCode = 1;
|
|
@@ -18836,8 +19011,8 @@ var init_service = __esm({
|
|
|
18836
19011
|
"use strict";
|
|
18837
19012
|
init_paths();
|
|
18838
19013
|
PLIST_LABEL = "com.cc-claw";
|
|
18839
|
-
PLIST_PATH = join23(
|
|
18840
|
-
SYSTEMD_DIR = join23(
|
|
19014
|
+
PLIST_PATH = join23(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
19015
|
+
SYSTEMD_DIR = join23(homedir8(), ".config", "systemd", "user");
|
|
18841
19016
|
UNIT_PATH = join23(SYSTEMD_DIR, "cc-claw.service");
|
|
18842
19017
|
}
|
|
18843
19018
|
});
|
|
@@ -19035,7 +19210,7 @@ var status_exports = {};
|
|
|
19035
19210
|
__export(status_exports, {
|
|
19036
19211
|
statusCommand: () => statusCommand
|
|
19037
19212
|
});
|
|
19038
|
-
import { existsSync as
|
|
19213
|
+
import { existsSync as existsSync25, statSync as statSync5 } from "fs";
|
|
19039
19214
|
async function statusCommand(globalOpts, localOpts) {
|
|
19040
19215
|
try {
|
|
19041
19216
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19075,7 +19250,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
19075
19250
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
19076
19251
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
19077
19252
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
19078
|
-
const dbStat =
|
|
19253
|
+
const dbStat = existsSync25(DB_PATH) ? statSync5(DB_PATH) : null;
|
|
19079
19254
|
let daemonRunning = false;
|
|
19080
19255
|
let daemonInfo = {};
|
|
19081
19256
|
if (localOpts.deep) {
|
|
@@ -19166,12 +19341,12 @@ var doctor_exports = {};
|
|
|
19166
19341
|
__export(doctor_exports, {
|
|
19167
19342
|
doctorCommand: () => doctorCommand
|
|
19168
19343
|
});
|
|
19169
|
-
import { existsSync as
|
|
19344
|
+
import { existsSync as existsSync26, statSync as statSync6, accessSync, constants } from "fs";
|
|
19170
19345
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
19171
19346
|
async function doctorCommand(globalOpts, localOpts) {
|
|
19172
19347
|
const checks = [];
|
|
19173
|
-
if (
|
|
19174
|
-
const size =
|
|
19348
|
+
if (existsSync26(DB_PATH)) {
|
|
19349
|
+
const size = statSync6(DB_PATH).size;
|
|
19175
19350
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
19176
19351
|
try {
|
|
19177
19352
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19200,7 +19375,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19200
19375
|
} else {
|
|
19201
19376
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
19202
19377
|
}
|
|
19203
|
-
if (
|
|
19378
|
+
if (existsSync26(ENV_PATH)) {
|
|
19204
19379
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
19205
19380
|
} else {
|
|
19206
19381
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -19244,7 +19419,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19244
19419
|
checks.push({ name: "Daemon", status: "warning", message: "could not probe" });
|
|
19245
19420
|
}
|
|
19246
19421
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
19247
|
-
if (
|
|
19422
|
+
if (existsSync26(tokenPath)) {
|
|
19248
19423
|
try {
|
|
19249
19424
|
accessSync(tokenPath, constants.R_OK);
|
|
19250
19425
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -19269,7 +19444,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19269
19444
|
}
|
|
19270
19445
|
} catch {
|
|
19271
19446
|
}
|
|
19272
|
-
if (
|
|
19447
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
19273
19448
|
try {
|
|
19274
19449
|
const { readFileSync: readFileSync21 } = await import("fs");
|
|
19275
19450
|
const logContent = readFileSync21(ERROR_LOG_PATH, "utf-8");
|
|
@@ -19395,10 +19570,10 @@ var logs_exports = {};
|
|
|
19395
19570
|
__export(logs_exports, {
|
|
19396
19571
|
logsCommand: () => logsCommand
|
|
19397
19572
|
});
|
|
19398
|
-
import { existsSync as
|
|
19573
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
19399
19574
|
async function logsCommand(opts) {
|
|
19400
19575
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
19401
|
-
if (!
|
|
19576
|
+
if (!existsSync27(logFile)) {
|
|
19402
19577
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
19403
19578
|
process.exit(1);
|
|
19404
19579
|
}
|
|
@@ -19450,11 +19625,11 @@ __export(gemini_exports, {
|
|
|
19450
19625
|
geminiReorder: () => geminiReorder,
|
|
19451
19626
|
geminiRotation: () => geminiRotation
|
|
19452
19627
|
});
|
|
19453
|
-
import { existsSync as
|
|
19628
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
19454
19629
|
import { join as join24 } from "path";
|
|
19455
19630
|
import { createInterface as createInterface5 } from "readline";
|
|
19456
19631
|
function requireDb() {
|
|
19457
|
-
if (!
|
|
19632
|
+
if (!existsSync28(DB_PATH)) {
|
|
19458
19633
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19459
19634
|
process.exit(1);
|
|
19460
19635
|
}
|
|
@@ -19480,7 +19655,7 @@ function resolveOAuthEmail(configHome) {
|
|
|
19480
19655
|
if (!configHome) return null;
|
|
19481
19656
|
try {
|
|
19482
19657
|
const accountsPath = join24(configHome, ".gemini", "google_accounts.json");
|
|
19483
|
-
if (!
|
|
19658
|
+
if (!existsSync28(accountsPath)) return null;
|
|
19484
19659
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
19485
19660
|
return accounts.active || null;
|
|
19486
19661
|
} catch {
|
|
@@ -19564,7 +19739,7 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
19564
19739
|
async function geminiAddAccount(globalOpts, opts) {
|
|
19565
19740
|
await requireWriteDb();
|
|
19566
19741
|
const slotsDir = join24(CC_CLAW_HOME, "gemini-slots");
|
|
19567
|
-
if (!
|
|
19742
|
+
if (!existsSync28(slotsDir)) mkdirSync10(slotsDir, { recursive: true });
|
|
19568
19743
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19569
19744
|
const tempId = Date.now();
|
|
19570
19745
|
const slotDir = join24(slotsDir, `slot-${tempId}`);
|
|
@@ -19588,7 +19763,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
19588
19763
|
} catch {
|
|
19589
19764
|
}
|
|
19590
19765
|
const oauthPath = join24(slotDir, ".gemini", "oauth_creds.json");
|
|
19591
|
-
if (!
|
|
19766
|
+
if (!existsSync28(oauthPath)) {
|
|
19592
19767
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
19593
19768
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
19594
19769
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -19702,12 +19877,12 @@ __export(backend_exports, {
|
|
|
19702
19877
|
backendList: () => backendList,
|
|
19703
19878
|
backendSet: () => backendSet
|
|
19704
19879
|
});
|
|
19705
|
-
import { existsSync as
|
|
19880
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19706
19881
|
async function backendList(globalOpts) {
|
|
19707
19882
|
const { getAvailableAdapters: getAvailableAdapters2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19708
19883
|
const chatId = resolveChatId(globalOpts);
|
|
19709
19884
|
let activeBackend = null;
|
|
19710
|
-
if (
|
|
19885
|
+
if (existsSync29(DB_PATH)) {
|
|
19711
19886
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19712
19887
|
const readDb = openDatabaseReadOnly2();
|
|
19713
19888
|
try {
|
|
@@ -19738,7 +19913,7 @@ async function backendList(globalOpts) {
|
|
|
19738
19913
|
}
|
|
19739
19914
|
async function backendGet(globalOpts) {
|
|
19740
19915
|
const chatId = resolveChatId(globalOpts);
|
|
19741
|
-
if (!
|
|
19916
|
+
if (!existsSync29(DB_PATH)) {
|
|
19742
19917
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19743
19918
|
process.exit(1);
|
|
19744
19919
|
}
|
|
@@ -19782,13 +19957,13 @@ __export(model_exports, {
|
|
|
19782
19957
|
modelList: () => modelList,
|
|
19783
19958
|
modelSet: () => modelSet
|
|
19784
19959
|
});
|
|
19785
|
-
import { existsSync as
|
|
19960
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19786
19961
|
async function modelList(globalOpts) {
|
|
19787
19962
|
const chatId = resolveChatId(globalOpts);
|
|
19788
19963
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19789
19964
|
const { getAdapter: getAdapter2, getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19790
19965
|
let backendId = "claude";
|
|
19791
|
-
if (
|
|
19966
|
+
if (existsSync30(DB_PATH)) {
|
|
19792
19967
|
const readDb = openDatabaseReadOnly2();
|
|
19793
19968
|
try {
|
|
19794
19969
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -19821,7 +19996,7 @@ async function modelList(globalOpts) {
|
|
|
19821
19996
|
}
|
|
19822
19997
|
async function modelGet(globalOpts) {
|
|
19823
19998
|
const chatId = resolveChatId(globalOpts);
|
|
19824
|
-
if (!
|
|
19999
|
+
if (!existsSync30(DB_PATH)) {
|
|
19825
20000
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19826
20001
|
process.exit(1);
|
|
19827
20002
|
}
|
|
@@ -19865,9 +20040,9 @@ __export(memory_exports, {
|
|
|
19865
20040
|
memoryList: () => memoryList,
|
|
19866
20041
|
memorySearch: () => memorySearch
|
|
19867
20042
|
});
|
|
19868
|
-
import { existsSync as
|
|
20043
|
+
import { existsSync as existsSync31 } from "fs";
|
|
19869
20044
|
async function memoryList(globalOpts) {
|
|
19870
|
-
if (!
|
|
20045
|
+
if (!existsSync31(DB_PATH)) {
|
|
19871
20046
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19872
20047
|
process.exit(1);
|
|
19873
20048
|
}
|
|
@@ -19891,7 +20066,7 @@ async function memoryList(globalOpts) {
|
|
|
19891
20066
|
});
|
|
19892
20067
|
}
|
|
19893
20068
|
async function memorySearch(globalOpts, query) {
|
|
19894
|
-
if (!
|
|
20069
|
+
if (!existsSync31(DB_PATH)) {
|
|
19895
20070
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19896
20071
|
process.exit(1);
|
|
19897
20072
|
}
|
|
@@ -19913,7 +20088,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
19913
20088
|
});
|
|
19914
20089
|
}
|
|
19915
20090
|
async function memoryHistory(globalOpts, opts) {
|
|
19916
|
-
if (!
|
|
20091
|
+
if (!existsSync31(DB_PATH)) {
|
|
19917
20092
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19918
20093
|
process.exit(1);
|
|
19919
20094
|
}
|
|
@@ -19961,7 +20136,7 @@ __export(cron_exports2, {
|
|
|
19961
20136
|
cronList: () => cronList,
|
|
19962
20137
|
cronRuns: () => cronRuns
|
|
19963
20138
|
});
|
|
19964
|
-
import { existsSync as
|
|
20139
|
+
import { existsSync as existsSync32 } from "fs";
|
|
19965
20140
|
function parseFallbacks(raw) {
|
|
19966
20141
|
return raw.slice(0, 3).map((f) => {
|
|
19967
20142
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -19982,7 +20157,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
19982
20157
|
return val;
|
|
19983
20158
|
}
|
|
19984
20159
|
async function cronList(globalOpts) {
|
|
19985
|
-
if (!
|
|
20160
|
+
if (!existsSync32(DB_PATH)) {
|
|
19986
20161
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19987
20162
|
process.exit(1);
|
|
19988
20163
|
}
|
|
@@ -20001,7 +20176,7 @@ async function cronList(globalOpts) {
|
|
|
20001
20176
|
const schedule2 = j.cron ?? (j.at_time ? `at ${j.at_time}` : j.every_ms ? `every ${j.every_ms / 1e3}s` : "?");
|
|
20002
20177
|
const tz = j.timezone !== "UTC" ? ` (${j.timezone})` : "";
|
|
20003
20178
|
lines.push(` ${statusDot(status)} #${j.id} [${status}] ${schedule2}${tz}`);
|
|
20004
|
-
lines.push(` ${j.description}`);
|
|
20179
|
+
lines.push(` ${j.title ?? j.description}`);
|
|
20005
20180
|
if (j.backend) lines.push(` Backend: ${j.backend}${j.model ? ` / ${j.model}` : ""}`);
|
|
20006
20181
|
if (j.fallbacks) {
|
|
20007
20182
|
try {
|
|
@@ -20020,7 +20195,7 @@ async function cronList(globalOpts) {
|
|
|
20020
20195
|
});
|
|
20021
20196
|
}
|
|
20022
20197
|
async function cronHealth(globalOpts) {
|
|
20023
|
-
if (!
|
|
20198
|
+
if (!existsSync32(DB_PATH)) {
|
|
20024
20199
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20025
20200
|
process.exit(1);
|
|
20026
20201
|
}
|
|
@@ -20080,6 +20255,7 @@ async function cronCreate(globalOpts, opts) {
|
|
|
20080
20255
|
cron: opts.cron ?? null,
|
|
20081
20256
|
atTime: opts.at ?? null,
|
|
20082
20257
|
everyMs,
|
|
20258
|
+
title: opts.title ?? null,
|
|
20083
20259
|
description: opts.description,
|
|
20084
20260
|
chatId,
|
|
20085
20261
|
backend: opts.backend ?? null,
|
|
@@ -20134,6 +20310,10 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20134
20310
|
const db3 = getDb2();
|
|
20135
20311
|
const updates = [];
|
|
20136
20312
|
const values = [];
|
|
20313
|
+
if (opts.title) {
|
|
20314
|
+
updates.push("title = ?");
|
|
20315
|
+
values.push(opts.title);
|
|
20316
|
+
}
|
|
20137
20317
|
if (opts.description) {
|
|
20138
20318
|
updates.push("description = ?");
|
|
20139
20319
|
values.push(opts.description);
|
|
@@ -20200,7 +20380,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20200
20380
|
}
|
|
20201
20381
|
}
|
|
20202
20382
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
20203
|
-
if (!
|
|
20383
|
+
if (!existsSync32(DB_PATH)) {
|
|
20204
20384
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20205
20385
|
process.exit(1);
|
|
20206
20386
|
}
|
|
@@ -20247,9 +20427,9 @@ __export(agents_exports, {
|
|
|
20247
20427
|
runnersList: () => runnersList,
|
|
20248
20428
|
tasksList: () => tasksList
|
|
20249
20429
|
});
|
|
20250
|
-
import { existsSync as
|
|
20430
|
+
import { existsSync as existsSync33 } from "fs";
|
|
20251
20431
|
async function agentsList(globalOpts) {
|
|
20252
|
-
if (!
|
|
20432
|
+
if (!existsSync33(DB_PATH)) {
|
|
20253
20433
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20254
20434
|
process.exit(1);
|
|
20255
20435
|
}
|
|
@@ -20280,7 +20460,7 @@ async function agentsList(globalOpts) {
|
|
|
20280
20460
|
});
|
|
20281
20461
|
}
|
|
20282
20462
|
async function tasksList(globalOpts) {
|
|
20283
|
-
if (!
|
|
20463
|
+
if (!existsSync33(DB_PATH)) {
|
|
20284
20464
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20285
20465
|
process.exit(1);
|
|
20286
20466
|
}
|
|
@@ -20408,18 +20588,18 @@ __export(db_exports, {
|
|
|
20408
20588
|
dbPath: () => dbPath,
|
|
20409
20589
|
dbStats: () => dbStats
|
|
20410
20590
|
});
|
|
20411
|
-
import { existsSync as
|
|
20591
|
+
import { existsSync as existsSync34, statSync as statSync7, copyFileSync as copyFileSync2, mkdirSync as mkdirSync11 } from "fs";
|
|
20412
20592
|
import { dirname as dirname5 } from "path";
|
|
20413
20593
|
async function dbStats(globalOpts) {
|
|
20414
|
-
if (!
|
|
20594
|
+
if (!existsSync34(DB_PATH)) {
|
|
20415
20595
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20416
20596
|
process.exit(1);
|
|
20417
20597
|
}
|
|
20418
20598
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
20419
20599
|
const readDb = openDatabaseReadOnly2();
|
|
20420
|
-
const mainSize =
|
|
20600
|
+
const mainSize = statSync7(DB_PATH).size;
|
|
20421
20601
|
const walPath = DB_PATH + "-wal";
|
|
20422
|
-
const walSize =
|
|
20602
|
+
const walSize = existsSync34(walPath) ? statSync7(walPath).size : 0;
|
|
20423
20603
|
const tableNames = readDb.prepare(
|
|
20424
20604
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
20425
20605
|
).all();
|
|
@@ -20453,7 +20633,7 @@ async function dbPath(globalOpts) {
|
|
|
20453
20633
|
output({ path: DB_PATH }, (d) => d.path);
|
|
20454
20634
|
}
|
|
20455
20635
|
async function dbBackup(globalOpts, destPath) {
|
|
20456
|
-
if (!
|
|
20636
|
+
if (!existsSync34(DB_PATH)) {
|
|
20457
20637
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20458
20638
|
process.exit(1);
|
|
20459
20639
|
}
|
|
@@ -20462,8 +20642,8 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
20462
20642
|
mkdirSync11(dirname5(dest), { recursive: true });
|
|
20463
20643
|
copyFileSync2(DB_PATH, dest);
|
|
20464
20644
|
const walPath = DB_PATH + "-wal";
|
|
20465
|
-
if (
|
|
20466
|
-
output({ path: dest, sizeBytes:
|
|
20645
|
+
if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
|
|
20646
|
+
output({ path: dest, sizeBytes: statSync7(dest).size }, (d) => {
|
|
20467
20647
|
const b = d;
|
|
20468
20648
|
return `
|
|
20469
20649
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -20491,9 +20671,9 @@ __export(usage_exports, {
|
|
|
20491
20671
|
usageCost: () => usageCost,
|
|
20492
20672
|
usageTokens: () => usageTokens
|
|
20493
20673
|
});
|
|
20494
|
-
import { existsSync as
|
|
20674
|
+
import { existsSync as existsSync35 } from "fs";
|
|
20495
20675
|
function ensureDb() {
|
|
20496
|
-
if (!
|
|
20676
|
+
if (!existsSync35(DB_PATH)) {
|
|
20497
20677
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
20498
20678
|
process.exit(1);
|
|
20499
20679
|
}
|
|
@@ -20683,9 +20863,9 @@ __export(config_exports, {
|
|
|
20683
20863
|
configList: () => configList,
|
|
20684
20864
|
configSet: () => configSet
|
|
20685
20865
|
});
|
|
20686
|
-
import { existsSync as
|
|
20866
|
+
import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
|
|
20687
20867
|
async function configList(globalOpts) {
|
|
20688
|
-
if (!
|
|
20868
|
+
if (!existsSync36(DB_PATH)) {
|
|
20689
20869
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20690
20870
|
process.exit(1);
|
|
20691
20871
|
}
|
|
@@ -20719,7 +20899,7 @@ async function configGet(globalOpts, key) {
|
|
|
20719
20899
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
20720
20900
|
process.exit(1);
|
|
20721
20901
|
}
|
|
20722
|
-
if (!
|
|
20902
|
+
if (!existsSync36(DB_PATH)) {
|
|
20723
20903
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20724
20904
|
process.exit(1);
|
|
20725
20905
|
}
|
|
@@ -20765,7 +20945,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
20765
20945
|
}
|
|
20766
20946
|
}
|
|
20767
20947
|
async function configEnv(_globalOpts) {
|
|
20768
|
-
if (!
|
|
20948
|
+
if (!existsSync36(ENV_PATH)) {
|
|
20769
20949
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
20770
20950
|
process.exit(1);
|
|
20771
20951
|
}
|
|
@@ -20819,9 +20999,9 @@ __export(session_exports, {
|
|
|
20819
20999
|
sessionGet: () => sessionGet,
|
|
20820
21000
|
sessionNew: () => sessionNew
|
|
20821
21001
|
});
|
|
20822
|
-
import { existsSync as
|
|
21002
|
+
import { existsSync as existsSync37 } from "fs";
|
|
20823
21003
|
async function sessionGet(globalOpts) {
|
|
20824
|
-
if (!
|
|
21004
|
+
if (!existsSync37(DB_PATH)) {
|
|
20825
21005
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20826
21006
|
process.exit(1);
|
|
20827
21007
|
}
|
|
@@ -20882,9 +21062,9 @@ __export(permissions_exports, {
|
|
|
20882
21062
|
verboseGet: () => verboseGet,
|
|
20883
21063
|
verboseSet: () => verboseSet
|
|
20884
21064
|
});
|
|
20885
|
-
import { existsSync as
|
|
21065
|
+
import { existsSync as existsSync38 } from "fs";
|
|
20886
21066
|
function ensureDb2() {
|
|
20887
|
-
if (!
|
|
21067
|
+
if (!existsSync38(DB_PATH)) {
|
|
20888
21068
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20889
21069
|
process.exit(1);
|
|
20890
21070
|
}
|
|
@@ -21031,9 +21211,9 @@ __export(cwd_exports, {
|
|
|
21031
21211
|
cwdGet: () => cwdGet,
|
|
21032
21212
|
cwdSet: () => cwdSet
|
|
21033
21213
|
});
|
|
21034
|
-
import { existsSync as
|
|
21214
|
+
import { existsSync as existsSync39 } from "fs";
|
|
21035
21215
|
async function cwdGet(globalOpts) {
|
|
21036
|
-
if (!
|
|
21216
|
+
if (!existsSync39(DB_PATH)) {
|
|
21037
21217
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21038
21218
|
process.exit(1);
|
|
21039
21219
|
}
|
|
@@ -21095,9 +21275,9 @@ __export(voice_exports, {
|
|
|
21095
21275
|
voiceGet: () => voiceGet,
|
|
21096
21276
|
voiceSet: () => voiceSet
|
|
21097
21277
|
});
|
|
21098
|
-
import { existsSync as
|
|
21278
|
+
import { existsSync as existsSync40 } from "fs";
|
|
21099
21279
|
async function voiceGet(globalOpts) {
|
|
21100
|
-
if (!
|
|
21280
|
+
if (!existsSync40(DB_PATH)) {
|
|
21101
21281
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21102
21282
|
process.exit(1);
|
|
21103
21283
|
}
|
|
@@ -21146,9 +21326,9 @@ __export(heartbeat_exports, {
|
|
|
21146
21326
|
heartbeatGet: () => heartbeatGet,
|
|
21147
21327
|
heartbeatSet: () => heartbeatSet
|
|
21148
21328
|
});
|
|
21149
|
-
import { existsSync as
|
|
21329
|
+
import { existsSync as existsSync41 } from "fs";
|
|
21150
21330
|
async function heartbeatGet(globalOpts) {
|
|
21151
|
-
if (!
|
|
21331
|
+
if (!existsSync41(DB_PATH)) {
|
|
21152
21332
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21153
21333
|
process.exit(1);
|
|
21154
21334
|
}
|
|
@@ -21258,9 +21438,9 @@ __export(chats_exports, {
|
|
|
21258
21438
|
chatsList: () => chatsList,
|
|
21259
21439
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
21260
21440
|
});
|
|
21261
|
-
import { existsSync as
|
|
21441
|
+
import { existsSync as existsSync42 } from "fs";
|
|
21262
21442
|
async function chatsList(_globalOpts) {
|
|
21263
|
-
if (!
|
|
21443
|
+
if (!existsSync42(DB_PATH)) {
|
|
21264
21444
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21265
21445
|
process.exit(1);
|
|
21266
21446
|
}
|
|
@@ -21388,9 +21568,9 @@ var mcps_exports = {};
|
|
|
21388
21568
|
__export(mcps_exports, {
|
|
21389
21569
|
mcpsList: () => mcpsList
|
|
21390
21570
|
});
|
|
21391
|
-
import { existsSync as
|
|
21571
|
+
import { existsSync as existsSync43 } from "fs";
|
|
21392
21572
|
async function mcpsList(_globalOpts) {
|
|
21393
|
-
if (!
|
|
21573
|
+
if (!existsSync43(DB_PATH)) {
|
|
21394
21574
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21395
21575
|
process.exit(1);
|
|
21396
21576
|
}
|
|
@@ -21427,11 +21607,11 @@ __export(chat_exports, {
|
|
|
21427
21607
|
chatSend: () => chatSend
|
|
21428
21608
|
});
|
|
21429
21609
|
import { request as httpRequest2 } from "http";
|
|
21430
|
-
import { readFileSync as readFileSync19, existsSync as
|
|
21610
|
+
import { readFileSync as readFileSync19, existsSync as existsSync44 } from "fs";
|
|
21431
21611
|
function getToken2() {
|
|
21432
21612
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21433
21613
|
try {
|
|
21434
|
-
if (
|
|
21614
|
+
if (existsSync44(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
|
|
21435
21615
|
} catch {
|
|
21436
21616
|
}
|
|
21437
21617
|
return null;
|
|
@@ -21871,9 +22051,9 @@ __export(evolve_exports, {
|
|
|
21871
22051
|
evolveStatus: () => evolveStatus,
|
|
21872
22052
|
evolveUndo: () => evolveUndo
|
|
21873
22053
|
});
|
|
21874
|
-
import { existsSync as
|
|
22054
|
+
import { existsSync as existsSync45 } from "fs";
|
|
21875
22055
|
function ensureDb3() {
|
|
21876
|
-
if (!
|
|
22056
|
+
if (!existsSync45(DB_PATH)) {
|
|
21877
22057
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
21878
22058
|
process.exit(1);
|
|
21879
22059
|
}
|
|
@@ -22235,7 +22415,7 @@ var init_evolve = __esm({
|
|
|
22235
22415
|
|
|
22236
22416
|
// src/setup.ts
|
|
22237
22417
|
var setup_exports = {};
|
|
22238
|
-
import { existsSync as
|
|
22418
|
+
import { existsSync as existsSync46, writeFileSync as writeFileSync9, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync12, statSync as statSync8 } from "fs";
|
|
22239
22419
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22240
22420
|
import { createInterface as createInterface7 } from "readline";
|
|
22241
22421
|
import { join as join25 } from "path";
|
|
@@ -22313,10 +22493,10 @@ async function setup() {
|
|
|
22313
22493
|
}
|
|
22314
22494
|
console.log("");
|
|
22315
22495
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
22316
|
-
if (!
|
|
22496
|
+
if (!existsSync46(dir)) mkdirSync12(dir, { recursive: true });
|
|
22317
22497
|
}
|
|
22318
22498
|
const env = {};
|
|
22319
|
-
const envSource =
|
|
22499
|
+
const envSource = existsSync46(ENV_PATH) ? ENV_PATH : existsSync46(".env") ? ".env" : null;
|
|
22320
22500
|
if (envSource) {
|
|
22321
22501
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
22322
22502
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -22327,8 +22507,8 @@ async function setup() {
|
|
|
22327
22507
|
}
|
|
22328
22508
|
}
|
|
22329
22509
|
const cwdDb = join25(process.cwd(), "cc-claw.db");
|
|
22330
|
-
if (
|
|
22331
|
-
const { size } =
|
|
22510
|
+
if (existsSync46(cwdDb) && !existsSync46(DB_PATH)) {
|
|
22511
|
+
const { size } = statSync8(cwdDb);
|
|
22332
22512
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
22333
22513
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
22334
22514
|
if (migrate) {
|
|
@@ -22747,7 +22927,7 @@ function registerCronCommands(cmd) {
|
|
|
22747
22927
|
const { cronList: cronList2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22748
22928
|
await cronList2(program.opts());
|
|
22749
22929
|
});
|
|
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) => {
|
|
22930
|
+
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
22931
|
const { cronCreate: cronCreate2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22752
22932
|
await cronCreate2(program.opts(), opts);
|
|
22753
22933
|
});
|
|
@@ -22767,7 +22947,7 @@ function registerCronCommands(cmd) {
|
|
|
22767
22947
|
const { cronAction: cronAction2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22768
22948
|
await cronAction2(program.opts(), "run", id);
|
|
22769
22949
|
});
|
|
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) => {
|
|
22950
|
+
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
22951
|
const { cronEdit: cronEdit2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22772
22952
|
await cronEdit2(program.opts(), id, opts);
|
|
22773
22953
|
});
|