cc-claw 0.11.0 → 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 +470 -168
- 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 {
|
|
@@ -703,6 +703,7 @@ __export(store_exports4, {
|
|
|
703
703
|
setReflectionModelConfig: () => setReflectionModelConfig,
|
|
704
704
|
setReflectionStatus: () => setReflectionStatus,
|
|
705
705
|
updateInsightEffectiveness: () => updateInsightEffectiveness,
|
|
706
|
+
updateInsightProposal: () => updateInsightProposal,
|
|
706
707
|
updateInsightRollback: () => updateInsightRollback,
|
|
707
708
|
updateInsightStatus: () => updateInsightStatus,
|
|
708
709
|
upsertGrowthMetric: () => upsertGrowthMetric
|
|
@@ -932,6 +933,11 @@ function updateInsightStatus(db3, id, status) {
|
|
|
932
933
|
db3.prepare("UPDATE insights SET status = ? WHERE id = ?").run(status, id);
|
|
933
934
|
}
|
|
934
935
|
}
|
|
936
|
+
function updateInsightProposal(db3, id, targetFile, proposedDiff, proposedAction) {
|
|
937
|
+
db3.prepare(`
|
|
938
|
+
UPDATE insights SET targetFile = ?, proposedDiff = ?, proposedAction = ? WHERE id = ?
|
|
939
|
+
`).run(targetFile, proposedDiff ?? null, proposedAction ?? null, id);
|
|
940
|
+
}
|
|
935
941
|
function updateInsightRollback(db3, id, rollbackData) {
|
|
936
942
|
db3.prepare("UPDATE insights SET rollbackData = ? WHERE id = ?").run(rollbackData, id);
|
|
937
943
|
}
|
|
@@ -1539,6 +1545,7 @@ function initDatabase() {
|
|
|
1539
1545
|
cron TEXT,
|
|
1540
1546
|
at_time TEXT,
|
|
1541
1547
|
every_ms INTEGER,
|
|
1548
|
+
title TEXT,
|
|
1542
1549
|
description TEXT NOT NULL,
|
|
1543
1550
|
chat_id TEXT NOT NULL,
|
|
1544
1551
|
backend TEXT,
|
|
@@ -1575,6 +1582,7 @@ function initDatabase() {
|
|
|
1575
1582
|
cron TEXT,
|
|
1576
1583
|
at_time TEXT,
|
|
1577
1584
|
every_ms INTEGER,
|
|
1585
|
+
title TEXT,
|
|
1578
1586
|
description TEXT NOT NULL,
|
|
1579
1587
|
chat_id TEXT NOT NULL,
|
|
1580
1588
|
backend TEXT,
|
|
@@ -1669,6 +1677,11 @@ function initDatabase() {
|
|
|
1669
1677
|
db.exec("ALTER TABLE jobs ADD COLUMN fallbacks TEXT");
|
|
1670
1678
|
} catch {
|
|
1671
1679
|
}
|
|
1680
|
+
try {
|
|
1681
|
+
db.exec("ALTER TABLE jobs ADD COLUMN title TEXT");
|
|
1682
|
+
} catch {
|
|
1683
|
+
}
|
|
1684
|
+
backfillJobTitles(db);
|
|
1672
1685
|
}
|
|
1673
1686
|
} catch {
|
|
1674
1687
|
}
|
|
@@ -2515,14 +2528,15 @@ function getBackendUsageInWindow(backend2, windowType) {
|
|
|
2515
2528
|
}
|
|
2516
2529
|
function insertJob(params) {
|
|
2517
2530
|
const result = db.prepare(`
|
|
2518
|
-
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,
|
|
2519
2532
|
backend, model, thinking, timeout, fallbacks, session_type, channel, target, delivery_mode, timezone)
|
|
2520
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2533
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2521
2534
|
`).run(
|
|
2522
2535
|
params.scheduleType,
|
|
2523
2536
|
params.cron ?? null,
|
|
2524
2537
|
params.atTime ?? null,
|
|
2525
2538
|
params.everyMs ?? null,
|
|
2539
|
+
params.title ?? null,
|
|
2526
2540
|
params.description,
|
|
2527
2541
|
params.chatId,
|
|
2528
2542
|
params.backend ?? null,
|
|
@@ -2538,6 +2552,26 @@ function insertJob(params) {
|
|
|
2538
2552
|
);
|
|
2539
2553
|
return getJobById(Number(result.lastInsertRowid));
|
|
2540
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
|
+
}
|
|
2541
2575
|
function mapJobRow(row) {
|
|
2542
2576
|
if (!row) return void 0;
|
|
2543
2577
|
row.fallbacks = row.fallbacks ? JSON.parse(row.fallbacks) : [];
|
|
@@ -2582,6 +2616,7 @@ function updateJob(id, fields) {
|
|
|
2582
2616
|
cron: "cron",
|
|
2583
2617
|
atTime: "at_time",
|
|
2584
2618
|
everyMs: "every_ms",
|
|
2619
|
+
title: "title",
|
|
2585
2620
|
description: "description",
|
|
2586
2621
|
backend: "backend",
|
|
2587
2622
|
model: "model",
|
|
@@ -3026,7 +3061,7 @@ var init_store5 = __esm({
|
|
|
3026
3061
|
ALL_TOOLS = ["Read", "Glob", "Grep", "Bash", "Write", "Edit", "WebFetch", "WebSearch", "Agent", "AskUserQuestion"];
|
|
3027
3062
|
JOB_SELECT = `
|
|
3028
3063
|
SELECT id, schedule_type as scheduleType, cron, at_time as atTime, every_ms as everyMs,
|
|
3029
|
-
description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3064
|
+
title, description, chat_id as chatId, backend, model, thinking, timeout, fallbacks,
|
|
3030
3065
|
session_type as sessionType, channel, target, delivery_mode as deliveryMode,
|
|
3031
3066
|
timezone, enabled, active, created_at as createdAt, last_run_at as lastRunAt,
|
|
3032
3067
|
next_run_at as nextRunAt, consecutive_failures as consecutiveFailures
|
|
@@ -6560,8 +6595,45 @@ __export(analyze_exports, {
|
|
|
6560
6595
|
});
|
|
6561
6596
|
import { spawn as spawn4 } from "child_process";
|
|
6562
6597
|
import { createInterface as createInterface3 } from "readline";
|
|
6563
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
6598
|
+
import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
|
|
6564
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
|
+
}
|
|
6565
6637
|
function buildAnalysisPrompt(params) {
|
|
6566
6638
|
const {
|
|
6567
6639
|
signals,
|
|
@@ -6621,7 +6693,31 @@ ${categoryList}`);
|
|
|
6621
6693
|
sections.push(`- [#${ins.id}] (${ins.category}) ${ins.insight}`);
|
|
6622
6694
|
}
|
|
6623
6695
|
}
|
|
6624
|
-
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(" | ");
|
|
6625
6721
|
sections.push(`[Output Format]
|
|
6626
6722
|
For each insight, output EXACTLY this format. Separate multiple insights with "---" on its own line.
|
|
6627
6723
|
|
|
@@ -6817,6 +6913,7 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6817
6913
|
const applied = getAppliedInsights(db3, chatId);
|
|
6818
6914
|
const rejected = getRejectedInsights(db3, chatId);
|
|
6819
6915
|
const codebaseEnabled = process.env.REFLECTION_CODEBASE_RECOMMENDATIONS === "1";
|
|
6916
|
+
const availableTargets = discoverReflectionTargets();
|
|
6820
6917
|
const prompt = buildAnalysisPrompt({
|
|
6821
6918
|
signals: signals.map((s) => ({
|
|
6822
6919
|
signalType: s.signalType,
|
|
@@ -6838,7 +6935,8 @@ async function runAnalysis(chatId, opts = {}) {
|
|
|
6838
6935
|
insight: i.insight,
|
|
6839
6936
|
category: i.category
|
|
6840
6937
|
})),
|
|
6841
|
-
codebaseEnabled
|
|
6938
|
+
codebaseEnabled,
|
|
6939
|
+
availableTargets
|
|
6842
6940
|
});
|
|
6843
6941
|
const resolved = resolveReflectionAdapter(chatId);
|
|
6844
6942
|
if (!resolved) {
|
|
@@ -6942,7 +7040,7 @@ __export(apply_exports, {
|
|
|
6942
7040
|
isTargetAllowed: () => isTargetAllowed,
|
|
6943
7041
|
rollbackInsight: () => rollbackInsight
|
|
6944
7042
|
});
|
|
6945
|
-
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";
|
|
6946
7044
|
import { join as join11, dirname as dirname2 } from "path";
|
|
6947
7045
|
function isTargetAllowed(relativePath) {
|
|
6948
7046
|
if (relativePath.includes("..")) return false;
|
|
@@ -7010,7 +7108,7 @@ async function applyInsight(insightId) {
|
|
|
7010
7108
|
}
|
|
7011
7109
|
const absolutePath = join11(CC_CLAW_HOME, insight.targetFile);
|
|
7012
7110
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
7013
|
-
if (
|
|
7111
|
+
if (existsSync12(absolutePath)) {
|
|
7014
7112
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
7015
7113
|
const lineCount = currentContent.split("\n").length;
|
|
7016
7114
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
@@ -7030,7 +7128,7 @@ async function applyInsight(insightId) {
|
|
|
7030
7128
|
};
|
|
7031
7129
|
}
|
|
7032
7130
|
let original = "";
|
|
7033
|
-
if (
|
|
7131
|
+
if (existsSync12(absolutePath)) {
|
|
7034
7132
|
original = readFileSync7(absolutePath, "utf-8");
|
|
7035
7133
|
} else if (insight.proposedAction !== "create") {
|
|
7036
7134
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
@@ -7039,7 +7137,7 @@ async function applyInsight(insightId) {
|
|
|
7039
7137
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
7040
7138
|
try {
|
|
7041
7139
|
const parentDir = dirname2(absolutePath);
|
|
7042
|
-
if (!
|
|
7140
|
+
if (!existsSync12(parentDir)) {
|
|
7043
7141
|
mkdirSync3(parentDir, { recursive: true });
|
|
7044
7142
|
}
|
|
7045
7143
|
if (original) {
|
|
@@ -7145,7 +7243,7 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
7145
7243
|
if (!baseline) return 0;
|
|
7146
7244
|
let current = "";
|
|
7147
7245
|
try {
|
|
7148
|
-
if (
|
|
7246
|
+
if (existsSync12(absolutePath)) {
|
|
7149
7247
|
current = readFileSync7(absolutePath, "utf-8");
|
|
7150
7248
|
}
|
|
7151
7249
|
} catch {
|
|
@@ -7197,7 +7295,7 @@ __export(server_exports, {
|
|
|
7197
7295
|
});
|
|
7198
7296
|
import { createServer } from "http";
|
|
7199
7297
|
import { randomBytes } from "crypto";
|
|
7200
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as
|
|
7298
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync13 } from "fs";
|
|
7201
7299
|
function createSubAgentToken(agentId) {
|
|
7202
7300
|
const token = `sub:${agentId.slice(0, 8)}:${randomBytes(16).toString("hex")}`;
|
|
7203
7301
|
subAgentTokens.set(token, agentId);
|
|
@@ -7368,7 +7466,7 @@ function startDashboard() {
|
|
|
7368
7466
|
if (url.pathname === "/api/orchestrator/spawn" && req.method === "POST") {
|
|
7369
7467
|
try {
|
|
7370
7468
|
const body = JSON.parse(await readBody(req));
|
|
7371
|
-
if (body.cwd && !
|
|
7469
|
+
if (body.cwd && !existsSync13(body.cwd)) {
|
|
7372
7470
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
7373
7471
|
}
|
|
7374
7472
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -9668,18 +9766,18 @@ var init_wrap_backend = __esm({
|
|
|
9668
9766
|
});
|
|
9669
9767
|
|
|
9670
9768
|
// src/agents/runners/config-loader.ts
|
|
9671
|
-
import { readFileSync as readFileSync8, readdirSync as
|
|
9769
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync6, existsSync as existsSync14, mkdirSync as mkdirSync5, watchFile, unwatchFile } from "fs";
|
|
9672
9770
|
import { join as join13 } from "path";
|
|
9673
9771
|
import { execFileSync } from "child_process";
|
|
9674
9772
|
function resolveExecutable(config2) {
|
|
9675
|
-
if (
|
|
9773
|
+
if (existsSync14(config2.executable)) return config2.executable;
|
|
9676
9774
|
try {
|
|
9677
9775
|
return execFileSync("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
9678
9776
|
} catch {
|
|
9679
9777
|
}
|
|
9680
9778
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
9681
9779
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
9682
|
-
if (
|
|
9780
|
+
if (existsSync14(resolved)) return resolved;
|
|
9683
9781
|
}
|
|
9684
9782
|
return config2.executable;
|
|
9685
9783
|
}
|
|
@@ -9818,11 +9916,11 @@ function loadRunnerConfig(filePath) {
|
|
|
9818
9916
|
}
|
|
9819
9917
|
}
|
|
9820
9918
|
function loadAllRunnerConfigs() {
|
|
9821
|
-
if (!
|
|
9919
|
+
if (!existsSync14(RUNNERS_PATH)) {
|
|
9822
9920
|
mkdirSync5(RUNNERS_PATH, { recursive: true });
|
|
9823
9921
|
return [];
|
|
9824
9922
|
}
|
|
9825
|
-
const files =
|
|
9923
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9826
9924
|
const configs = [];
|
|
9827
9925
|
for (const file of files) {
|
|
9828
9926
|
const config2 = loadRunnerConfig(join13(RUNNERS_PATH, file));
|
|
@@ -9846,14 +9944,14 @@ function registerConfigRunners() {
|
|
|
9846
9944
|
return count;
|
|
9847
9945
|
}
|
|
9848
9946
|
function watchRunnerConfigs(onChange) {
|
|
9849
|
-
if (!
|
|
9947
|
+
if (!existsSync14(RUNNERS_PATH)) return;
|
|
9850
9948
|
for (const prev of watchedFiles) {
|
|
9851
|
-
if (!
|
|
9949
|
+
if (!existsSync14(prev)) {
|
|
9852
9950
|
unwatchFile(prev);
|
|
9853
9951
|
watchedFiles.delete(prev);
|
|
9854
9952
|
}
|
|
9855
9953
|
}
|
|
9856
|
-
const files =
|
|
9954
|
+
const files = readdirSync6(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
9857
9955
|
for (const file of files) {
|
|
9858
9956
|
const fullPath = join13(RUNNERS_PATH, file);
|
|
9859
9957
|
if (watchedFiles.has(fullPath)) continue;
|
|
@@ -10562,7 +10660,7 @@ __export(discover_exports, {
|
|
|
10562
10660
|
});
|
|
10563
10661
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
10564
10662
|
import { createHash } from "crypto";
|
|
10565
|
-
import { homedir as
|
|
10663
|
+
import { homedir as homedir5 } from "os";
|
|
10566
10664
|
import { join as join14 } from "path";
|
|
10567
10665
|
function invalidateSkillCache() {
|
|
10568
10666
|
cachedSkills = null;
|
|
@@ -10581,7 +10679,7 @@ async function discoverAllSkills() {
|
|
|
10581
10679
|
const rawSkills = [];
|
|
10582
10680
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
10583
10681
|
for (const backendId of getAllBackendIds()) {
|
|
10584
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(
|
|
10682
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join14(homedir5(), `.${backendId}`, "skills")];
|
|
10585
10683
|
for (const dir of dirs) {
|
|
10586
10684
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
10587
10685
|
}
|
|
@@ -10712,15 +10810,15 @@ var init_discover = __esm({
|
|
|
10712
10810
|
init_backends();
|
|
10713
10811
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
10714
10812
|
BACKEND_SKILL_DIRS = {
|
|
10715
|
-
claude: [join14(
|
|
10716
|
-
gemini: [join14(
|
|
10813
|
+
claude: [join14(homedir5(), ".claude", "skills")],
|
|
10814
|
+
gemini: [join14(homedir5(), ".gemini", "skills")],
|
|
10717
10815
|
codex: [
|
|
10718
|
-
join14(
|
|
10719
|
-
join14(
|
|
10816
|
+
join14(homedir5(), ".agents", "skills"),
|
|
10817
|
+
join14(homedir5(), ".codex", "skills")
|
|
10720
10818
|
],
|
|
10721
10819
|
cursor: [
|
|
10722
|
-
join14(
|
|
10723
|
-
join14(
|
|
10820
|
+
join14(homedir5(), ".cursor", "skills"),
|
|
10821
|
+
join14(homedir5(), ".cursor", "skills-cursor")
|
|
10724
10822
|
]
|
|
10725
10823
|
};
|
|
10726
10824
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -10736,7 +10834,7 @@ __export(install_exports, {
|
|
|
10736
10834
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
10737
10835
|
});
|
|
10738
10836
|
import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
|
|
10739
|
-
import { existsSync as
|
|
10837
|
+
import { existsSync as existsSync15 } from "fs";
|
|
10740
10838
|
import { join as join15, basename } from "path";
|
|
10741
10839
|
import { execSync as execSync6 } from "child_process";
|
|
10742
10840
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
@@ -10755,7 +10853,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10755
10853
|
stdio: "pipe",
|
|
10756
10854
|
timeout: 3e4
|
|
10757
10855
|
});
|
|
10758
|
-
if (!
|
|
10856
|
+
if (!existsSync15(join15(tmpDir, ".git"))) {
|
|
10759
10857
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
10760
10858
|
}
|
|
10761
10859
|
const searchRoot = subPath ? join15(tmpDir, subPath) : tmpDir;
|
|
@@ -10765,7 +10863,7 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
10765
10863
|
}
|
|
10766
10864
|
const skillFolderName = basename(skillDir);
|
|
10767
10865
|
const destDir = join15(SKILLS_PATH, skillFolderName);
|
|
10768
|
-
if (
|
|
10866
|
+
if (existsSync15(destDir)) {
|
|
10769
10867
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
10770
10868
|
}
|
|
10771
10869
|
await mkdir(destDir, { recursive: true });
|
|
@@ -10812,14 +10910,14 @@ function parseGitHubUrl(input) {
|
|
|
10812
10910
|
async function findSkillDir(root) {
|
|
10813
10911
|
const candidates = ["SKILL.md", "skill.md"];
|
|
10814
10912
|
for (const c of candidates) {
|
|
10815
|
-
if (
|
|
10913
|
+
if (existsSync15(join15(root, c))) return root;
|
|
10816
10914
|
}
|
|
10817
10915
|
try {
|
|
10818
10916
|
const entries = await readdir2(root, { withFileTypes: true });
|
|
10819
10917
|
for (const entry of entries) {
|
|
10820
10918
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
10821
10919
|
for (const c of candidates) {
|
|
10822
|
-
if (
|
|
10920
|
+
if (existsSync15(join15(root, entry.name, c))) {
|
|
10823
10921
|
return join15(root, entry.name);
|
|
10824
10922
|
}
|
|
10825
10923
|
}
|
|
@@ -10839,7 +10937,7 @@ async function findSkillDir(root) {
|
|
|
10839
10937
|
for (const sub of subEntries) {
|
|
10840
10938
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
10841
10939
|
for (const c of candidates) {
|
|
10842
|
-
if (
|
|
10940
|
+
if (existsSync15(join15(root, entry.name, sub.name, c))) {
|
|
10843
10941
|
return join15(root, entry.name, sub.name);
|
|
10844
10942
|
}
|
|
10845
10943
|
}
|
|
@@ -10858,7 +10956,7 @@ var init_install = __esm({
|
|
|
10858
10956
|
});
|
|
10859
10957
|
|
|
10860
10958
|
// src/bootstrap/profile.ts
|
|
10861
|
-
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as
|
|
10959
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync5, existsSync as existsSync16 } from "fs";
|
|
10862
10960
|
import { join as join16 } from "path";
|
|
10863
10961
|
function hasActiveProfile(chatId) {
|
|
10864
10962
|
return activeProfiles.has(chatId);
|
|
@@ -10988,7 +11086,7 @@ function extractUserUpdates(text) {
|
|
|
10988
11086
|
return { cleanText, updates };
|
|
10989
11087
|
}
|
|
10990
11088
|
function appendToUserProfile(key, value) {
|
|
10991
|
-
if (!
|
|
11089
|
+
if (!existsSync16(USER_PATH2)) return;
|
|
10992
11090
|
const content = readFileSync9(USER_PATH2, "utf-8");
|
|
10993
11091
|
const line = `- **${key}**: ${value}`;
|
|
10994
11092
|
if (content.includes(line)) return;
|
|
@@ -11010,7 +11108,7 @@ var init_profile = __esm({
|
|
|
11010
11108
|
});
|
|
11011
11109
|
|
|
11012
11110
|
// src/bootstrap/heartbeat.ts
|
|
11013
|
-
import { readFileSync as readFileSync10, existsSync as
|
|
11111
|
+
import { readFileSync as readFileSync10, existsSync as existsSync17 } from "fs";
|
|
11014
11112
|
import { join as join17 } from "path";
|
|
11015
11113
|
function initHeartbeat(channelReg) {
|
|
11016
11114
|
registry2 = channelReg;
|
|
@@ -11149,7 +11247,7 @@ ${healthLines.join("\n")}`);
|
|
|
11149
11247
|
sections.push(`[Active watches]
|
|
11150
11248
|
${watchLines.join("\n")}`);
|
|
11151
11249
|
}
|
|
11152
|
-
if (
|
|
11250
|
+
if (existsSync17(HEARTBEAT_MD_PATH)) {
|
|
11153
11251
|
try {
|
|
11154
11252
|
const custom = readFileSync10(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
11155
11253
|
if (custom) {
|
|
@@ -11380,7 +11478,7 @@ var init_classify = __esm({
|
|
|
11380
11478
|
});
|
|
11381
11479
|
|
|
11382
11480
|
// src/media/image-gen.ts
|
|
11383
|
-
import { mkdirSync as mkdirSync6, existsSync as
|
|
11481
|
+
import { mkdirSync as mkdirSync6, existsSync as existsSync18 } from "fs";
|
|
11384
11482
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
11385
11483
|
import { join as join18 } from "path";
|
|
11386
11484
|
async function generateImage(prompt) {
|
|
@@ -11429,7 +11527,7 @@ async function generateImage(prompt) {
|
|
|
11429
11527
|
if (!imageData) {
|
|
11430
11528
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
11431
11529
|
}
|
|
11432
|
-
if (!
|
|
11530
|
+
if (!existsSync18(IMAGE_OUTPUT_DIR)) {
|
|
11433
11531
|
mkdirSync6(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
11434
11532
|
}
|
|
11435
11533
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
@@ -12160,11 +12258,31 @@ async function finalizeJob(chatId, channel) {
|
|
|
12160
12258
|
const pending = pendingJobs.get(chatId);
|
|
12161
12259
|
if (!pending) return;
|
|
12162
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
|
+
}
|
|
12163
12280
|
const jobParams = {
|
|
12164
12281
|
scheduleType: pending.scheduleType ?? "cron",
|
|
12165
12282
|
cron: pending.cron,
|
|
12166
12283
|
atTime: pending.at ?? null,
|
|
12167
12284
|
everyMs: pending.everyMs ?? null,
|
|
12285
|
+
title,
|
|
12168
12286
|
description: pending.task,
|
|
12169
12287
|
backend: pending.backend ?? null,
|
|
12170
12288
|
model: pending.model ?? null,
|
|
@@ -12188,6 +12306,7 @@ async function finalizeJob(chatId, channel) {
|
|
|
12188
12306
|
chatId,
|
|
12189
12307
|
`Job #${editJobId} updated!
|
|
12190
12308
|
|
|
12309
|
+
Title: ${jobParams.title ?? "\u2014"}
|
|
12191
12310
|
Task: ${jobParams.description}
|
|
12192
12311
|
Schedule: ${jobParams.cron ?? "N/A"}
|
|
12193
12312
|
Timezone: ${jobParams.timezone}`,
|
|
@@ -12202,6 +12321,7 @@ Timezone: ${jobParams.timezone}`,
|
|
|
12202
12321
|
chatId,
|
|
12203
12322
|
`Job #${job.id} created!
|
|
12204
12323
|
|
|
12324
|
+
Title: ${job.title ?? "\u2014"}
|
|
12205
12325
|
Task: ${job.description}
|
|
12206
12326
|
Schedule: ${job.cron ?? "N/A"}
|
|
12207
12327
|
Timezone: ${job.timezone}
|
|
@@ -12680,16 +12800,20 @@ function pct(ratio) {
|
|
|
12680
12800
|
return `${Math.round(ratio * 100)}%`;
|
|
12681
12801
|
}
|
|
12682
12802
|
function formatProposalCard(params) {
|
|
12683
|
-
const { category, insight, why, targetFile, confidence } = params;
|
|
12803
|
+
const { category, insight, why, targetFile, confidence, proposedAction, proposedDiff } = params;
|
|
12684
12804
|
const header2 = `[${category}] ${insight}`;
|
|
12685
|
-
const whyLine = `Why: ${why}
|
|
12805
|
+
const whyLine = why ? `Why: ${why}` : null;
|
|
12686
12806
|
const confidencePct = pct(confidence);
|
|
12687
12807
|
const showTarget = category !== "codebase" && targetFile && targetFile !== "codebase";
|
|
12688
12808
|
const targetLine = showTarget ? `Target: ${targetFile} | Confidence: ${confidencePct}` : `Confidence: ${confidencePct}`;
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12809
|
+
const lines = [header2, ""];
|
|
12810
|
+
if (whyLine) lines.push(whyLine);
|
|
12811
|
+
lines.push(targetLine);
|
|
12812
|
+
if (proposedDiff) {
|
|
12813
|
+
const actionLabel = proposedAction ? ` (${proposedAction})` : "";
|
|
12814
|
+
lines.push("", `Proposed change${actionLabel}:`, "```diff", proposedDiff, "```");
|
|
12815
|
+
}
|
|
12816
|
+
return lines.join("\n");
|
|
12693
12817
|
}
|
|
12694
12818
|
function formatNightlySummary(insights) {
|
|
12695
12819
|
const count = insights.length;
|
|
@@ -12734,7 +12858,7 @@ function buildProposalKeyboard(insightId, category) {
|
|
|
12734
12858
|
return [
|
|
12735
12859
|
[
|
|
12736
12860
|
{ label: "Show Diff", data: `evolve:diff:${insightId}`, style: "primary" },
|
|
12737
|
-
{ label: "
|
|
12861
|
+
{ label: "Discuss", data: `evolve:discuss:${insightId}` },
|
|
12738
12862
|
{ label: "Reject", data: `evolve:reject:${insightId}`, style: "danger" }
|
|
12739
12863
|
]
|
|
12740
12864
|
];
|
|
@@ -12742,7 +12866,7 @@ function buildProposalKeyboard(insightId, category) {
|
|
|
12742
12866
|
return [
|
|
12743
12867
|
[
|
|
12744
12868
|
{ label: "Apply", data: `evolve:apply:${insightId}`, style: "success" },
|
|
12745
|
-
{ label: "
|
|
12869
|
+
{ label: "Discuss", data: `evolve:discuss:${insightId}` },
|
|
12746
12870
|
{ label: "Reject", data: `evolve:reject:${insightId}`, style: "danger" }
|
|
12747
12871
|
]
|
|
12748
12872
|
];
|
|
@@ -12798,8 +12922,10 @@ var init_propose = __esm({
|
|
|
12798
12922
|
|
|
12799
12923
|
// src/router.ts
|
|
12800
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";
|
|
12801
12926
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
12802
12927
|
import { resolve as resolvePath, join as join19 } from "path";
|
|
12928
|
+
import { homedir as homedir6 } from "os";
|
|
12803
12929
|
function parseMcpListOutput(output2) {
|
|
12804
12930
|
const results = [];
|
|
12805
12931
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -14517,8 +14643,8 @@ ${agentLines.join("\n")}`, buttons);
|
|
|
14517
14643
|
lines.push(` \u2705 <b>cc-claw</b> <i>Agent orchestrator (spawn, tasks, inbox)</i>`);
|
|
14518
14644
|
}
|
|
14519
14645
|
const { execFile: execFile5 } = await import("child_process");
|
|
14520
|
-
const { homedir:
|
|
14521
|
-
const discoveryCwd =
|
|
14646
|
+
const { homedir: homedir9 } = await import("os");
|
|
14647
|
+
const discoveryCwd = homedir9();
|
|
14522
14648
|
const runnerResults = await Promise.allSettled(
|
|
14523
14649
|
getAllRunners().map((runner) => {
|
|
14524
14650
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -15702,7 +15828,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15702
15828
|
pageSize: 10,
|
|
15703
15829
|
callbackPrefix: "job:",
|
|
15704
15830
|
renderItem: (j) => ({
|
|
15705
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15831
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15706
15832
|
data: `job:view:${j.id}`,
|
|
15707
15833
|
style: "primary"
|
|
15708
15834
|
}),
|
|
@@ -15712,7 +15838,7 @@ async function sendJobsBoard(chatId, channel, page) {
|
|
|
15712
15838
|
for (const j of pageJobs) {
|
|
15713
15839
|
const emoji = getJobStatusEmoji(j);
|
|
15714
15840
|
const schedule2 = getJobScheduleText(j);
|
|
15715
|
-
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);
|
|
15716
15842
|
lines.push(`${emoji} ${desc} \xB7 ${schedule2}`);
|
|
15717
15843
|
}
|
|
15718
15844
|
lines.push("");
|
|
@@ -15747,8 +15873,9 @@ async function sendJobDetail(chatId, jobId, channel) {
|
|
|
15747
15873
|
const runs = getJobRuns(jobId, 1);
|
|
15748
15874
|
const lastRunStatus = runs.length > 0 ? runs[0].status : null;
|
|
15749
15875
|
const lines = [
|
|
15750
|
-
`Job #${job.id}: ${job.description}`,
|
|
15876
|
+
`Job #${job.id}: ${job.title ?? job.description}`,
|
|
15751
15877
|
buildSectionHeader("", 22),
|
|
15878
|
+
...job.title ? [`Task: ${job.description.length > 80 ? job.description.slice(0, 77) + "\u2026" : job.description}`] : [],
|
|
15752
15879
|
`Runs: ${schedule2}${tz}`,
|
|
15753
15880
|
`Backend: ${backend2} | Model: ${model2}`,
|
|
15754
15881
|
`Last run: ${lastRun}${lastRunStatus ? ` (${lastRunStatus})` : ""}`,
|
|
@@ -15855,7 +15982,7 @@ async function sendJobPicker(chatId, channel, action) {
|
|
|
15855
15982
|
const actionLabel = action.charAt(0).toUpperCase() + action.slice(1);
|
|
15856
15983
|
const style = action === "run" ? "success" : action === "cancel" ? "danger" : void 0;
|
|
15857
15984
|
const buttons = jobs.map((j) => [{
|
|
15858
|
-
label: `#${j.id}: ${j.description.slice(0, 30)}`,
|
|
15985
|
+
label: `#${j.id}: ${(j.title ?? j.description).slice(0, 30)}`,
|
|
15859
15986
|
data: action === "cancel" ? `job:cancel:${j.id}` : `job:${action}:${j.id}`,
|
|
15860
15987
|
...style ? { style } : {}
|
|
15861
15988
|
}]);
|
|
@@ -16464,7 +16591,8 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16464
16591
|
if (insights.length === 0) {
|
|
16465
16592
|
await channel.sendText(chatId, "No new insights from recent interactions.", { parseMode: "plain" });
|
|
16466
16593
|
} else {
|
|
16467
|
-
|
|
16594
|
+
const nightlyItems = insights.map((ins, i) => ({ id: i + 1, ...ins }));
|
|
16595
|
+
await channel.sendText(chatId, formatNightlySummary2(nightlyItems), { parseMode: "plain" });
|
|
16468
16596
|
}
|
|
16469
16597
|
} catch (e) {
|
|
16470
16598
|
await channel.sendText(chatId, `Analysis failed: ${e}`, { parseMode: "plain" });
|
|
@@ -16510,6 +16638,164 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16510
16638
|
await channel.sendText(chatId, "Skipped \u2014 will show again next review.", { parseMode: "plain" });
|
|
16511
16639
|
break;
|
|
16512
16640
|
}
|
|
16641
|
+
case "discuss": {
|
|
16642
|
+
const insId = parseInt(idStr, 10);
|
|
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
|
+
]
|
|
16658
|
+
]);
|
|
16659
|
+
break;
|
|
16660
|
+
}
|
|
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);
|
|
16796
|
+
}
|
|
16797
|
+
break;
|
|
16798
|
+
}
|
|
16513
16799
|
case "reject": {
|
|
16514
16800
|
const { updateInsightStatus: updateInsightStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
16515
16801
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -16524,7 +16810,18 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16524
16810
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16525
16811
|
const reportData = buildGrowthReportData2(getDb2(), chatId, 30);
|
|
16526
16812
|
const modelData = buildModelPerformanceData2(getDb2(), chatId, 30);
|
|
16527
|
-
|
|
16813
|
+
const metricsForReport = {
|
|
16814
|
+
correctionsBefore: reportData.avgCorrectionsFirstHalf,
|
|
16815
|
+
correctionsAfter: reportData.avgCorrectionsSecondHalf,
|
|
16816
|
+
praiseRatio: reportData.praiseRatio,
|
|
16817
|
+
insightsApplied: reportData.totalInsightsApplied,
|
|
16818
|
+
pendingCount: reportData.pendingCount,
|
|
16819
|
+
topInsight: reportData.topInsightId != null ? {
|
|
16820
|
+
insight: `#${reportData.topInsightId}`,
|
|
16821
|
+
effectiveness: reportData.topInsightEffectiveness ?? 0
|
|
16822
|
+
} : null
|
|
16823
|
+
};
|
|
16824
|
+
let report = formatGrowthReport2(metricsForReport, modelData);
|
|
16528
16825
|
const drift = calculateDrift2(chatId);
|
|
16529
16826
|
if (drift && (drift.soulDrift > 0.5 || drift.userDrift > 0.5)) {
|
|
16530
16827
|
report += "\n\nSOUL.md has changed significantly since reflection started.\nTap History in /evolve to review all applied changes.";
|
|
@@ -16557,19 +16854,19 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16557
16854
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
16558
16855
|
const current = getReflectionStatus2(getDb2(), chatId);
|
|
16559
16856
|
if (current === "frozen") {
|
|
16560
|
-
const { readFileSync: readFileSync21, existsSync:
|
|
16857
|
+
const { readFileSync: readFileSync21, existsSync: existsSync47 } = await import("fs");
|
|
16561
16858
|
const { join: join26 } = await import("path");
|
|
16562
16859
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
16563
16860
|
const soulPath = join26(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16564
16861
|
const userPath = join26(CC_CLAW_HOME3, "identity/USER.md");
|
|
16565
|
-
const soul =
|
|
16566
|
-
const user =
|
|
16862
|
+
const soul = existsSync47(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
|
|
16863
|
+
const user = existsSync47(userPath) ? readFileSync21(userPath, "utf-8") : "";
|
|
16567
16864
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
16568
16865
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16569
16866
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
16570
16867
|
await channel.sendText(chatId, "\u2705 Self-learning enabled. Signal detection is now active.\nCreate a nightly cron job with /schedule to enable automatic analysis.", { parseMode: "plain" });
|
|
16571
16868
|
} else {
|
|
16572
|
-
setReflectionStatus2(getDb2(), chatId, "frozen",
|
|
16869
|
+
setReflectionStatus2(getDb2(), chatId, "frozen", void 0, void 0);
|
|
16573
16870
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
16574
16871
|
logActivity2(getDb2(), { chatId, source: "telegram", eventType: "reflection_frozen", summary: "Reflection disabled" });
|
|
16575
16872
|
await channel.sendText(chatId, "\u26D4 Self-learning disabled. No signals will be collected.", { parseMode: "plain" });
|
|
@@ -17397,19 +17694,19 @@ var init_router = __esm({
|
|
|
17397
17694
|
});
|
|
17398
17695
|
|
|
17399
17696
|
// src/skills/bootstrap.ts
|
|
17400
|
-
import { existsSync as
|
|
17697
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17401
17698
|
import { readdir as readdir4, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
|
|
17402
17699
|
import { join as join20, dirname as dirname3 } from "path";
|
|
17403
17700
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17404
17701
|
async function copyAgentManifestSkills() {
|
|
17405
|
-
if (!
|
|
17702
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
17406
17703
|
try {
|
|
17407
17704
|
const entries = await readdir4(PKG_SKILLS, { withFileTypes: true });
|
|
17408
17705
|
for (const entry of entries) {
|
|
17409
17706
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
17410
17707
|
const src = join20(PKG_SKILLS, entry.name);
|
|
17411
17708
|
const dest = join20(SKILLS_PATH, entry.name);
|
|
17412
|
-
if (
|
|
17709
|
+
if (existsSync20(dest)) continue;
|
|
17413
17710
|
await copyFile(src, dest);
|
|
17414
17711
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
17415
17712
|
}
|
|
@@ -17420,7 +17717,7 @@ async function copyAgentManifestSkills() {
|
|
|
17420
17717
|
async function bootstrapSkills() {
|
|
17421
17718
|
await copyAgentManifestSkills();
|
|
17422
17719
|
const usmDir = join20(SKILLS_PATH, USM_DIR_NAME);
|
|
17423
|
-
if (
|
|
17720
|
+
if (existsSync20(usmDir)) return;
|
|
17424
17721
|
try {
|
|
17425
17722
|
const entries = await readdir4(SKILLS_PATH);
|
|
17426
17723
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -17443,7 +17740,7 @@ async function bootstrapSkills() {
|
|
|
17443
17740
|
}
|
|
17444
17741
|
async function patchUsmForCcClaw(usmDir) {
|
|
17445
17742
|
const skillPath = join20(usmDir, "SKILL.md");
|
|
17446
|
-
if (!
|
|
17743
|
+
if (!existsSync20(skillPath)) return;
|
|
17447
17744
|
try {
|
|
17448
17745
|
let content = await readFile6(skillPath, "utf-8");
|
|
17449
17746
|
let patched = false;
|
|
@@ -17703,13 +18000,13 @@ __export(ai_skill_exports, {
|
|
|
17703
18000
|
generateAiSkill: () => generateAiSkill,
|
|
17704
18001
|
installAiSkill: () => installAiSkill
|
|
17705
18002
|
});
|
|
17706
|
-
import { existsSync as
|
|
18003
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync6, mkdirSync as mkdirSync7 } from "fs";
|
|
17707
18004
|
import { join as join21 } from "path";
|
|
17708
|
-
import { homedir as
|
|
18005
|
+
import { homedir as homedir7 } from "os";
|
|
17709
18006
|
function generateAiSkill() {
|
|
17710
18007
|
const version = VERSION;
|
|
17711
18008
|
let systemState = "";
|
|
17712
|
-
if (
|
|
18009
|
+
if (existsSync21(DB_PATH)) {
|
|
17713
18010
|
try {
|
|
17714
18011
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
17715
18012
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -18125,11 +18422,11 @@ var init_ai_skill = __esm({
|
|
|
18125
18422
|
init_paths();
|
|
18126
18423
|
init_version();
|
|
18127
18424
|
BACKEND_SKILL_DIRS2 = {
|
|
18128
|
-
"cc-claw": [join21(
|
|
18129
|
-
claude: [join21(
|
|
18130
|
-
gemini: [join21(
|
|
18131
|
-
codex: [join21(
|
|
18132
|
-
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")]
|
|
18133
18430
|
};
|
|
18134
18431
|
}
|
|
18135
18432
|
});
|
|
@@ -18139,7 +18436,7 @@ var index_exports = {};
|
|
|
18139
18436
|
__export(index_exports, {
|
|
18140
18437
|
main: () => main
|
|
18141
18438
|
});
|
|
18142
|
-
import { mkdirSync as mkdirSync8, existsSync as
|
|
18439
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync22, renameSync, statSync as statSync4, readFileSync as readFileSync12 } from "fs";
|
|
18143
18440
|
import { join as join22 } from "path";
|
|
18144
18441
|
import dotenv from "dotenv";
|
|
18145
18442
|
function migrateLayout() {
|
|
@@ -18153,7 +18450,7 @@ function migrateLayout() {
|
|
|
18153
18450
|
[join22(CC_CLAW_HOME, "cc-claw.error.log.1"), join22(LOGS_PATH, "cc-claw.error.log.1")]
|
|
18154
18451
|
];
|
|
18155
18452
|
for (const [from, to] of moves) {
|
|
18156
|
-
if (
|
|
18453
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
18157
18454
|
try {
|
|
18158
18455
|
renameSync(from, to);
|
|
18159
18456
|
} catch {
|
|
@@ -18164,7 +18461,7 @@ function migrateLayout() {
|
|
|
18164
18461
|
function rotateLogs() {
|
|
18165
18462
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
18166
18463
|
try {
|
|
18167
|
-
const { size } =
|
|
18464
|
+
const { size } = statSync4(file);
|
|
18168
18465
|
if (size > LOG_MAX_BYTES) {
|
|
18169
18466
|
const archivePath = `${file}.1`;
|
|
18170
18467
|
try {
|
|
@@ -18360,10 +18657,10 @@ var init_index = __esm({
|
|
|
18360
18657
|
init_bootstrap2();
|
|
18361
18658
|
init_health3();
|
|
18362
18659
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
18363
|
-
if (!
|
|
18660
|
+
if (!existsSync22(dir)) mkdirSync8(dir, { recursive: true });
|
|
18364
18661
|
}
|
|
18365
18662
|
migrateLayout();
|
|
18366
|
-
if (
|
|
18663
|
+
if (existsSync22(ENV_PATH)) {
|
|
18367
18664
|
dotenv.config({ path: ENV_PATH });
|
|
18368
18665
|
} else {
|
|
18369
18666
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -18384,12 +18681,12 @@ __export(api_client_exports, {
|
|
|
18384
18681
|
apiPost: () => apiPost,
|
|
18385
18682
|
isDaemonRunning: () => isDaemonRunning
|
|
18386
18683
|
});
|
|
18387
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
18684
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
18388
18685
|
import { request as httpRequest } from "http";
|
|
18389
18686
|
function getToken() {
|
|
18390
18687
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
18391
18688
|
try {
|
|
18392
|
-
if (
|
|
18689
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
18393
18690
|
} catch {
|
|
18394
18691
|
}
|
|
18395
18692
|
return null;
|
|
@@ -18484,9 +18781,9 @@ __export(service_exports, {
|
|
|
18484
18781
|
serviceStatus: () => serviceStatus,
|
|
18485
18782
|
uninstallService: () => uninstallService
|
|
18486
18783
|
});
|
|
18487
|
-
import { existsSync as
|
|
18784
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync9, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
|
|
18488
18785
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
18489
|
-
import { homedir as
|
|
18786
|
+
import { homedir as homedir8, platform } from "os";
|
|
18490
18787
|
import { join as join23, dirname as dirname4 } from "path";
|
|
18491
18788
|
function resolveExecutable2(name) {
|
|
18492
18789
|
try {
|
|
@@ -18497,7 +18794,7 @@ function resolveExecutable2(name) {
|
|
|
18497
18794
|
}
|
|
18498
18795
|
function getPathDirs() {
|
|
18499
18796
|
const nodeBin = dirname4(process.execPath);
|
|
18500
|
-
const home =
|
|
18797
|
+
const home = homedir8();
|
|
18501
18798
|
const dirs = /* @__PURE__ */ new Set([
|
|
18502
18799
|
nodeBin,
|
|
18503
18800
|
join23(home, ".local", "bin"),
|
|
@@ -18515,7 +18812,7 @@ function getPathDirs() {
|
|
|
18515
18812
|
function generatePlist() {
|
|
18516
18813
|
const ccClawBin = resolveExecutable2("cc-claw");
|
|
18517
18814
|
const pathDirs = getPathDirs();
|
|
18518
|
-
const home =
|
|
18815
|
+
const home = homedir8();
|
|
18519
18816
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
18520
18817
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
18521
18818
|
<plist version="1.0">
|
|
@@ -18559,9 +18856,9 @@ function generatePlist() {
|
|
|
18559
18856
|
}
|
|
18560
18857
|
function installMacOS() {
|
|
18561
18858
|
const agentsDir = dirname4(PLIST_PATH);
|
|
18562
|
-
if (!
|
|
18563
|
-
if (!
|
|
18564
|
-
if (
|
|
18859
|
+
if (!existsSync24(agentsDir)) mkdirSync9(agentsDir, { recursive: true });
|
|
18860
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18861
|
+
if (existsSync24(PLIST_PATH)) {
|
|
18565
18862
|
try {
|
|
18566
18863
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
18567
18864
|
} catch {
|
|
@@ -18573,7 +18870,7 @@ function installMacOS() {
|
|
|
18573
18870
|
console.log(" Service loaded and starting.");
|
|
18574
18871
|
}
|
|
18575
18872
|
function uninstallMacOS() {
|
|
18576
|
-
if (!
|
|
18873
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
18577
18874
|
console.log(" No service found to uninstall.");
|
|
18578
18875
|
return;
|
|
18579
18876
|
}
|
|
@@ -18640,15 +18937,15 @@ Restart=on-failure
|
|
|
18640
18937
|
RestartSec=10
|
|
18641
18938
|
WorkingDirectory=${CC_CLAW_HOME}
|
|
18642
18939
|
Environment=PATH=${pathDirs}
|
|
18643
|
-
Environment=HOME=${
|
|
18940
|
+
Environment=HOME=${homedir8()}
|
|
18644
18941
|
|
|
18645
18942
|
[Install]
|
|
18646
18943
|
WantedBy=default.target
|
|
18647
18944
|
`;
|
|
18648
18945
|
}
|
|
18649
18946
|
function installLinux() {
|
|
18650
|
-
if (!
|
|
18651
|
-
if (!
|
|
18947
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync9(SYSTEMD_DIR, { recursive: true });
|
|
18948
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync9(LOGS_PATH, { recursive: true });
|
|
18652
18949
|
writeFileSync7(UNIT_PATH, generateUnit());
|
|
18653
18950
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
18654
18951
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -18657,7 +18954,7 @@ function installLinux() {
|
|
|
18657
18954
|
console.log(" Service enabled and started.");
|
|
18658
18955
|
}
|
|
18659
18956
|
function uninstallLinux() {
|
|
18660
|
-
if (!
|
|
18957
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
18661
18958
|
console.log(" No service found to uninstall.");
|
|
18662
18959
|
return;
|
|
18663
18960
|
}
|
|
@@ -18682,7 +18979,7 @@ function statusLinux() {
|
|
|
18682
18979
|
}
|
|
18683
18980
|
}
|
|
18684
18981
|
function installService() {
|
|
18685
|
-
if (!
|
|
18982
|
+
if (!existsSync24(join23(CC_CLAW_HOME, ".env"))) {
|
|
18686
18983
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
18687
18984
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
18688
18985
|
process.exitCode = 1;
|
|
@@ -18711,8 +19008,8 @@ var init_service = __esm({
|
|
|
18711
19008
|
"use strict";
|
|
18712
19009
|
init_paths();
|
|
18713
19010
|
PLIST_LABEL = "com.cc-claw";
|
|
18714
|
-
PLIST_PATH = join23(
|
|
18715
|
-
SYSTEMD_DIR = join23(
|
|
19011
|
+
PLIST_PATH = join23(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
19012
|
+
SYSTEMD_DIR = join23(homedir8(), ".config", "systemd", "user");
|
|
18716
19013
|
UNIT_PATH = join23(SYSTEMD_DIR, "cc-claw.service");
|
|
18717
19014
|
}
|
|
18718
19015
|
});
|
|
@@ -18910,7 +19207,7 @@ var status_exports = {};
|
|
|
18910
19207
|
__export(status_exports, {
|
|
18911
19208
|
statusCommand: () => statusCommand
|
|
18912
19209
|
});
|
|
18913
|
-
import { existsSync as
|
|
19210
|
+
import { existsSync as existsSync25, statSync as statSync5 } from "fs";
|
|
18914
19211
|
async function statusCommand(globalOpts, localOpts) {
|
|
18915
19212
|
try {
|
|
18916
19213
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -18950,7 +19247,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
18950
19247
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
18951
19248
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
18952
19249
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
18953
|
-
const dbStat =
|
|
19250
|
+
const dbStat = existsSync25(DB_PATH) ? statSync5(DB_PATH) : null;
|
|
18954
19251
|
let daemonRunning = false;
|
|
18955
19252
|
let daemonInfo = {};
|
|
18956
19253
|
if (localOpts.deep) {
|
|
@@ -19041,12 +19338,12 @@ var doctor_exports = {};
|
|
|
19041
19338
|
__export(doctor_exports, {
|
|
19042
19339
|
doctorCommand: () => doctorCommand
|
|
19043
19340
|
});
|
|
19044
|
-
import { existsSync as
|
|
19341
|
+
import { existsSync as existsSync26, statSync as statSync6, accessSync, constants } from "fs";
|
|
19045
19342
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
19046
19343
|
async function doctorCommand(globalOpts, localOpts) {
|
|
19047
19344
|
const checks = [];
|
|
19048
|
-
if (
|
|
19049
|
-
const size =
|
|
19345
|
+
if (existsSync26(DB_PATH)) {
|
|
19346
|
+
const size = statSync6(DB_PATH).size;
|
|
19050
19347
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
19051
19348
|
try {
|
|
19052
19349
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19075,7 +19372,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19075
19372
|
} else {
|
|
19076
19373
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
19077
19374
|
}
|
|
19078
|
-
if (
|
|
19375
|
+
if (existsSync26(ENV_PATH)) {
|
|
19079
19376
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
19080
19377
|
} else {
|
|
19081
19378
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -19119,7 +19416,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19119
19416
|
checks.push({ name: "Daemon", status: "warning", message: "could not probe" });
|
|
19120
19417
|
}
|
|
19121
19418
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
19122
|
-
if (
|
|
19419
|
+
if (existsSync26(tokenPath)) {
|
|
19123
19420
|
try {
|
|
19124
19421
|
accessSync(tokenPath, constants.R_OK);
|
|
19125
19422
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -19144,7 +19441,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
19144
19441
|
}
|
|
19145
19442
|
} catch {
|
|
19146
19443
|
}
|
|
19147
|
-
if (
|
|
19444
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
19148
19445
|
try {
|
|
19149
19446
|
const { readFileSync: readFileSync21 } = await import("fs");
|
|
19150
19447
|
const logContent = readFileSync21(ERROR_LOG_PATH, "utf-8");
|
|
@@ -19270,10 +19567,10 @@ var logs_exports = {};
|
|
|
19270
19567
|
__export(logs_exports, {
|
|
19271
19568
|
logsCommand: () => logsCommand
|
|
19272
19569
|
});
|
|
19273
|
-
import { existsSync as
|
|
19570
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
19274
19571
|
async function logsCommand(opts) {
|
|
19275
19572
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
19276
|
-
if (!
|
|
19573
|
+
if (!existsSync27(logFile)) {
|
|
19277
19574
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
19278
19575
|
process.exit(1);
|
|
19279
19576
|
}
|
|
@@ -19325,11 +19622,11 @@ __export(gemini_exports, {
|
|
|
19325
19622
|
geminiReorder: () => geminiReorder,
|
|
19326
19623
|
geminiRotation: () => geminiRotation
|
|
19327
19624
|
});
|
|
19328
|
-
import { existsSync as
|
|
19625
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
19329
19626
|
import { join as join24 } from "path";
|
|
19330
19627
|
import { createInterface as createInterface5 } from "readline";
|
|
19331
19628
|
function requireDb() {
|
|
19332
|
-
if (!
|
|
19629
|
+
if (!existsSync28(DB_PATH)) {
|
|
19333
19630
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19334
19631
|
process.exit(1);
|
|
19335
19632
|
}
|
|
@@ -19355,7 +19652,7 @@ function resolveOAuthEmail(configHome) {
|
|
|
19355
19652
|
if (!configHome) return null;
|
|
19356
19653
|
try {
|
|
19357
19654
|
const accountsPath = join24(configHome, ".gemini", "google_accounts.json");
|
|
19358
|
-
if (!
|
|
19655
|
+
if (!existsSync28(accountsPath)) return null;
|
|
19359
19656
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
19360
19657
|
return accounts.active || null;
|
|
19361
19658
|
} catch {
|
|
@@ -19439,7 +19736,7 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
19439
19736
|
async function geminiAddAccount(globalOpts, opts) {
|
|
19440
19737
|
await requireWriteDb();
|
|
19441
19738
|
const slotsDir = join24(CC_CLAW_HOME, "gemini-slots");
|
|
19442
|
-
if (!
|
|
19739
|
+
if (!existsSync28(slotsDir)) mkdirSync10(slotsDir, { recursive: true });
|
|
19443
19740
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19444
19741
|
const tempId = Date.now();
|
|
19445
19742
|
const slotDir = join24(slotsDir, `slot-${tempId}`);
|
|
@@ -19463,7 +19760,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
19463
19760
|
} catch {
|
|
19464
19761
|
}
|
|
19465
19762
|
const oauthPath = join24(slotDir, ".gemini", "oauth_creds.json");
|
|
19466
|
-
if (!
|
|
19763
|
+
if (!existsSync28(oauthPath)) {
|
|
19467
19764
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
19468
19765
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
19469
19766
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -19577,12 +19874,12 @@ __export(backend_exports, {
|
|
|
19577
19874
|
backendList: () => backendList,
|
|
19578
19875
|
backendSet: () => backendSet
|
|
19579
19876
|
});
|
|
19580
|
-
import { existsSync as
|
|
19877
|
+
import { existsSync as existsSync29 } from "fs";
|
|
19581
19878
|
async function backendList(globalOpts) {
|
|
19582
19879
|
const { getAvailableAdapters: getAvailableAdapters2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19583
19880
|
const chatId = resolveChatId(globalOpts);
|
|
19584
19881
|
let activeBackend = null;
|
|
19585
|
-
if (
|
|
19882
|
+
if (existsSync29(DB_PATH)) {
|
|
19586
19883
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19587
19884
|
const readDb = openDatabaseReadOnly2();
|
|
19588
19885
|
try {
|
|
@@ -19613,7 +19910,7 @@ async function backendList(globalOpts) {
|
|
|
19613
19910
|
}
|
|
19614
19911
|
async function backendGet(globalOpts) {
|
|
19615
19912
|
const chatId = resolveChatId(globalOpts);
|
|
19616
|
-
if (!
|
|
19913
|
+
if (!existsSync29(DB_PATH)) {
|
|
19617
19914
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19618
19915
|
process.exit(1);
|
|
19619
19916
|
}
|
|
@@ -19657,13 +19954,13 @@ __export(model_exports, {
|
|
|
19657
19954
|
modelList: () => modelList,
|
|
19658
19955
|
modelSet: () => modelSet
|
|
19659
19956
|
});
|
|
19660
|
-
import { existsSync as
|
|
19957
|
+
import { existsSync as existsSync30 } from "fs";
|
|
19661
19958
|
async function modelList(globalOpts) {
|
|
19662
19959
|
const chatId = resolveChatId(globalOpts);
|
|
19663
19960
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19664
19961
|
const { getAdapter: getAdapter2, getAllAdapters: getAllAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
19665
19962
|
let backendId = "claude";
|
|
19666
|
-
if (
|
|
19963
|
+
if (existsSync30(DB_PATH)) {
|
|
19667
19964
|
const readDb = openDatabaseReadOnly2();
|
|
19668
19965
|
try {
|
|
19669
19966
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -19696,7 +19993,7 @@ async function modelList(globalOpts) {
|
|
|
19696
19993
|
}
|
|
19697
19994
|
async function modelGet(globalOpts) {
|
|
19698
19995
|
const chatId = resolveChatId(globalOpts);
|
|
19699
|
-
if (!
|
|
19996
|
+
if (!existsSync30(DB_PATH)) {
|
|
19700
19997
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19701
19998
|
process.exit(1);
|
|
19702
19999
|
}
|
|
@@ -19740,9 +20037,9 @@ __export(memory_exports, {
|
|
|
19740
20037
|
memoryList: () => memoryList,
|
|
19741
20038
|
memorySearch: () => memorySearch
|
|
19742
20039
|
});
|
|
19743
|
-
import { existsSync as
|
|
20040
|
+
import { existsSync as existsSync31 } from "fs";
|
|
19744
20041
|
async function memoryList(globalOpts) {
|
|
19745
|
-
if (!
|
|
20042
|
+
if (!existsSync31(DB_PATH)) {
|
|
19746
20043
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
19747
20044
|
process.exit(1);
|
|
19748
20045
|
}
|
|
@@ -19766,7 +20063,7 @@ async function memoryList(globalOpts) {
|
|
|
19766
20063
|
});
|
|
19767
20064
|
}
|
|
19768
20065
|
async function memorySearch(globalOpts, query) {
|
|
19769
|
-
if (!
|
|
20066
|
+
if (!existsSync31(DB_PATH)) {
|
|
19770
20067
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19771
20068
|
process.exit(1);
|
|
19772
20069
|
}
|
|
@@ -19788,7 +20085,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
19788
20085
|
});
|
|
19789
20086
|
}
|
|
19790
20087
|
async function memoryHistory(globalOpts, opts) {
|
|
19791
|
-
if (!
|
|
20088
|
+
if (!existsSync31(DB_PATH)) {
|
|
19792
20089
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19793
20090
|
process.exit(1);
|
|
19794
20091
|
}
|
|
@@ -19836,7 +20133,7 @@ __export(cron_exports2, {
|
|
|
19836
20133
|
cronList: () => cronList,
|
|
19837
20134
|
cronRuns: () => cronRuns
|
|
19838
20135
|
});
|
|
19839
|
-
import { existsSync as
|
|
20136
|
+
import { existsSync as existsSync32 } from "fs";
|
|
19840
20137
|
function parseFallbacks(raw) {
|
|
19841
20138
|
return raw.slice(0, 3).map((f) => {
|
|
19842
20139
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -19857,7 +20154,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
19857
20154
|
return val;
|
|
19858
20155
|
}
|
|
19859
20156
|
async function cronList(globalOpts) {
|
|
19860
|
-
if (!
|
|
20157
|
+
if (!existsSync32(DB_PATH)) {
|
|
19861
20158
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19862
20159
|
process.exit(1);
|
|
19863
20160
|
}
|
|
@@ -19876,7 +20173,7 @@ async function cronList(globalOpts) {
|
|
|
19876
20173
|
const schedule2 = j.cron ?? (j.at_time ? `at ${j.at_time}` : j.every_ms ? `every ${j.every_ms / 1e3}s` : "?");
|
|
19877
20174
|
const tz = j.timezone !== "UTC" ? ` (${j.timezone})` : "";
|
|
19878
20175
|
lines.push(` ${statusDot(status)} #${j.id} [${status}] ${schedule2}${tz}`);
|
|
19879
|
-
lines.push(` ${j.description}`);
|
|
20176
|
+
lines.push(` ${j.title ?? j.description}`);
|
|
19880
20177
|
if (j.backend) lines.push(` Backend: ${j.backend}${j.model ? ` / ${j.model}` : ""}`);
|
|
19881
20178
|
if (j.fallbacks) {
|
|
19882
20179
|
try {
|
|
@@ -19895,7 +20192,7 @@ async function cronList(globalOpts) {
|
|
|
19895
20192
|
});
|
|
19896
20193
|
}
|
|
19897
20194
|
async function cronHealth(globalOpts) {
|
|
19898
|
-
if (!
|
|
20195
|
+
if (!existsSync32(DB_PATH)) {
|
|
19899
20196
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
19900
20197
|
process.exit(1);
|
|
19901
20198
|
}
|
|
@@ -19955,6 +20252,7 @@ async function cronCreate(globalOpts, opts) {
|
|
|
19955
20252
|
cron: opts.cron ?? null,
|
|
19956
20253
|
atTime: opts.at ?? null,
|
|
19957
20254
|
everyMs,
|
|
20255
|
+
title: opts.title ?? null,
|
|
19958
20256
|
description: opts.description,
|
|
19959
20257
|
chatId,
|
|
19960
20258
|
backend: opts.backend ?? null,
|
|
@@ -20009,6 +20307,10 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20009
20307
|
const db3 = getDb2();
|
|
20010
20308
|
const updates = [];
|
|
20011
20309
|
const values = [];
|
|
20310
|
+
if (opts.title) {
|
|
20311
|
+
updates.push("title = ?");
|
|
20312
|
+
values.push(opts.title);
|
|
20313
|
+
}
|
|
20012
20314
|
if (opts.description) {
|
|
20013
20315
|
updates.push("description = ?");
|
|
20014
20316
|
values.push(opts.description);
|
|
@@ -20075,7 +20377,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
20075
20377
|
}
|
|
20076
20378
|
}
|
|
20077
20379
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
20078
|
-
if (!
|
|
20380
|
+
if (!existsSync32(DB_PATH)) {
|
|
20079
20381
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20080
20382
|
process.exit(1);
|
|
20081
20383
|
}
|
|
@@ -20122,9 +20424,9 @@ __export(agents_exports, {
|
|
|
20122
20424
|
runnersList: () => runnersList,
|
|
20123
20425
|
tasksList: () => tasksList
|
|
20124
20426
|
});
|
|
20125
|
-
import { existsSync as
|
|
20427
|
+
import { existsSync as existsSync33 } from "fs";
|
|
20126
20428
|
async function agentsList(globalOpts) {
|
|
20127
|
-
if (!
|
|
20429
|
+
if (!existsSync33(DB_PATH)) {
|
|
20128
20430
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20129
20431
|
process.exit(1);
|
|
20130
20432
|
}
|
|
@@ -20155,7 +20457,7 @@ async function agentsList(globalOpts) {
|
|
|
20155
20457
|
});
|
|
20156
20458
|
}
|
|
20157
20459
|
async function tasksList(globalOpts) {
|
|
20158
|
-
if (!
|
|
20460
|
+
if (!existsSync33(DB_PATH)) {
|
|
20159
20461
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20160
20462
|
process.exit(1);
|
|
20161
20463
|
}
|
|
@@ -20283,18 +20585,18 @@ __export(db_exports, {
|
|
|
20283
20585
|
dbPath: () => dbPath,
|
|
20284
20586
|
dbStats: () => dbStats
|
|
20285
20587
|
});
|
|
20286
|
-
import { existsSync as
|
|
20588
|
+
import { existsSync as existsSync34, statSync as statSync7, copyFileSync as copyFileSync2, mkdirSync as mkdirSync11 } from "fs";
|
|
20287
20589
|
import { dirname as dirname5 } from "path";
|
|
20288
20590
|
async function dbStats(globalOpts) {
|
|
20289
|
-
if (!
|
|
20591
|
+
if (!existsSync34(DB_PATH)) {
|
|
20290
20592
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20291
20593
|
process.exit(1);
|
|
20292
20594
|
}
|
|
20293
20595
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
20294
20596
|
const readDb = openDatabaseReadOnly2();
|
|
20295
|
-
const mainSize =
|
|
20597
|
+
const mainSize = statSync7(DB_PATH).size;
|
|
20296
20598
|
const walPath = DB_PATH + "-wal";
|
|
20297
|
-
const walSize =
|
|
20599
|
+
const walSize = existsSync34(walPath) ? statSync7(walPath).size : 0;
|
|
20298
20600
|
const tableNames = readDb.prepare(
|
|
20299
20601
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
20300
20602
|
).all();
|
|
@@ -20328,7 +20630,7 @@ async function dbPath(globalOpts) {
|
|
|
20328
20630
|
output({ path: DB_PATH }, (d) => d.path);
|
|
20329
20631
|
}
|
|
20330
20632
|
async function dbBackup(globalOpts, destPath) {
|
|
20331
|
-
if (!
|
|
20633
|
+
if (!existsSync34(DB_PATH)) {
|
|
20332
20634
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
20333
20635
|
process.exit(1);
|
|
20334
20636
|
}
|
|
@@ -20337,8 +20639,8 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
20337
20639
|
mkdirSync11(dirname5(dest), { recursive: true });
|
|
20338
20640
|
copyFileSync2(DB_PATH, dest);
|
|
20339
20641
|
const walPath = DB_PATH + "-wal";
|
|
20340
|
-
if (
|
|
20341
|
-
output({ path: dest, sizeBytes:
|
|
20642
|
+
if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
|
|
20643
|
+
output({ path: dest, sizeBytes: statSync7(dest).size }, (d) => {
|
|
20342
20644
|
const b = d;
|
|
20343
20645
|
return `
|
|
20344
20646
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -20366,9 +20668,9 @@ __export(usage_exports, {
|
|
|
20366
20668
|
usageCost: () => usageCost,
|
|
20367
20669
|
usageTokens: () => usageTokens
|
|
20368
20670
|
});
|
|
20369
|
-
import { existsSync as
|
|
20671
|
+
import { existsSync as existsSync35 } from "fs";
|
|
20370
20672
|
function ensureDb() {
|
|
20371
|
-
if (!
|
|
20673
|
+
if (!existsSync35(DB_PATH)) {
|
|
20372
20674
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
20373
20675
|
process.exit(1);
|
|
20374
20676
|
}
|
|
@@ -20558,9 +20860,9 @@ __export(config_exports, {
|
|
|
20558
20860
|
configList: () => configList,
|
|
20559
20861
|
configSet: () => configSet
|
|
20560
20862
|
});
|
|
20561
|
-
import { existsSync as
|
|
20863
|
+
import { existsSync as existsSync36, readFileSync as readFileSync18 } from "fs";
|
|
20562
20864
|
async function configList(globalOpts) {
|
|
20563
|
-
if (!
|
|
20865
|
+
if (!existsSync36(DB_PATH)) {
|
|
20564
20866
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20565
20867
|
process.exit(1);
|
|
20566
20868
|
}
|
|
@@ -20594,7 +20896,7 @@ async function configGet(globalOpts, key) {
|
|
|
20594
20896
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
20595
20897
|
process.exit(1);
|
|
20596
20898
|
}
|
|
20597
|
-
if (!
|
|
20899
|
+
if (!existsSync36(DB_PATH)) {
|
|
20598
20900
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20599
20901
|
process.exit(1);
|
|
20600
20902
|
}
|
|
@@ -20640,7 +20942,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
20640
20942
|
}
|
|
20641
20943
|
}
|
|
20642
20944
|
async function configEnv(_globalOpts) {
|
|
20643
|
-
if (!
|
|
20945
|
+
if (!existsSync36(ENV_PATH)) {
|
|
20644
20946
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
20645
20947
|
process.exit(1);
|
|
20646
20948
|
}
|
|
@@ -20694,9 +20996,9 @@ __export(session_exports, {
|
|
|
20694
20996
|
sessionGet: () => sessionGet,
|
|
20695
20997
|
sessionNew: () => sessionNew
|
|
20696
20998
|
});
|
|
20697
|
-
import { existsSync as
|
|
20999
|
+
import { existsSync as existsSync37 } from "fs";
|
|
20698
21000
|
async function sessionGet(globalOpts) {
|
|
20699
|
-
if (!
|
|
21001
|
+
if (!existsSync37(DB_PATH)) {
|
|
20700
21002
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20701
21003
|
process.exit(1);
|
|
20702
21004
|
}
|
|
@@ -20757,9 +21059,9 @@ __export(permissions_exports, {
|
|
|
20757
21059
|
verboseGet: () => verboseGet,
|
|
20758
21060
|
verboseSet: () => verboseSet
|
|
20759
21061
|
});
|
|
20760
|
-
import { existsSync as
|
|
21062
|
+
import { existsSync as existsSync38 } from "fs";
|
|
20761
21063
|
function ensureDb2() {
|
|
20762
|
-
if (!
|
|
21064
|
+
if (!existsSync38(DB_PATH)) {
|
|
20763
21065
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20764
21066
|
process.exit(1);
|
|
20765
21067
|
}
|
|
@@ -20906,9 +21208,9 @@ __export(cwd_exports, {
|
|
|
20906
21208
|
cwdGet: () => cwdGet,
|
|
20907
21209
|
cwdSet: () => cwdSet
|
|
20908
21210
|
});
|
|
20909
|
-
import { existsSync as
|
|
21211
|
+
import { existsSync as existsSync39 } from "fs";
|
|
20910
21212
|
async function cwdGet(globalOpts) {
|
|
20911
|
-
if (!
|
|
21213
|
+
if (!existsSync39(DB_PATH)) {
|
|
20912
21214
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20913
21215
|
process.exit(1);
|
|
20914
21216
|
}
|
|
@@ -20970,9 +21272,9 @@ __export(voice_exports, {
|
|
|
20970
21272
|
voiceGet: () => voiceGet,
|
|
20971
21273
|
voiceSet: () => voiceSet
|
|
20972
21274
|
});
|
|
20973
|
-
import { existsSync as
|
|
21275
|
+
import { existsSync as existsSync40 } from "fs";
|
|
20974
21276
|
async function voiceGet(globalOpts) {
|
|
20975
|
-
if (!
|
|
21277
|
+
if (!existsSync40(DB_PATH)) {
|
|
20976
21278
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
20977
21279
|
process.exit(1);
|
|
20978
21280
|
}
|
|
@@ -21021,9 +21323,9 @@ __export(heartbeat_exports, {
|
|
|
21021
21323
|
heartbeatGet: () => heartbeatGet,
|
|
21022
21324
|
heartbeatSet: () => heartbeatSet
|
|
21023
21325
|
});
|
|
21024
|
-
import { existsSync as
|
|
21326
|
+
import { existsSync as existsSync41 } from "fs";
|
|
21025
21327
|
async function heartbeatGet(globalOpts) {
|
|
21026
|
-
if (!
|
|
21328
|
+
if (!existsSync41(DB_PATH)) {
|
|
21027
21329
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21028
21330
|
process.exit(1);
|
|
21029
21331
|
}
|
|
@@ -21133,9 +21435,9 @@ __export(chats_exports, {
|
|
|
21133
21435
|
chatsList: () => chatsList,
|
|
21134
21436
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
21135
21437
|
});
|
|
21136
|
-
import { existsSync as
|
|
21438
|
+
import { existsSync as existsSync42 } from "fs";
|
|
21137
21439
|
async function chatsList(_globalOpts) {
|
|
21138
|
-
if (!
|
|
21440
|
+
if (!existsSync42(DB_PATH)) {
|
|
21139
21441
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21140
21442
|
process.exit(1);
|
|
21141
21443
|
}
|
|
@@ -21263,9 +21565,9 @@ var mcps_exports = {};
|
|
|
21263
21565
|
__export(mcps_exports, {
|
|
21264
21566
|
mcpsList: () => mcpsList
|
|
21265
21567
|
});
|
|
21266
|
-
import { existsSync as
|
|
21568
|
+
import { existsSync as existsSync43 } from "fs";
|
|
21267
21569
|
async function mcpsList(_globalOpts) {
|
|
21268
|
-
if (!
|
|
21570
|
+
if (!existsSync43(DB_PATH)) {
|
|
21269
21571
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
21270
21572
|
process.exit(1);
|
|
21271
21573
|
}
|
|
@@ -21302,11 +21604,11 @@ __export(chat_exports, {
|
|
|
21302
21604
|
chatSend: () => chatSend
|
|
21303
21605
|
});
|
|
21304
21606
|
import { request as httpRequest2 } from "http";
|
|
21305
|
-
import { readFileSync as readFileSync19, existsSync as
|
|
21607
|
+
import { readFileSync as readFileSync19, existsSync as existsSync44 } from "fs";
|
|
21306
21608
|
function getToken2() {
|
|
21307
21609
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21308
21610
|
try {
|
|
21309
|
-
if (
|
|
21611
|
+
if (existsSync44(TOKEN_PATH2)) return readFileSync19(TOKEN_PATH2, "utf-8").trim();
|
|
21310
21612
|
} catch {
|
|
21311
21613
|
}
|
|
21312
21614
|
return null;
|
|
@@ -21746,9 +22048,9 @@ __export(evolve_exports, {
|
|
|
21746
22048
|
evolveStatus: () => evolveStatus,
|
|
21747
22049
|
evolveUndo: () => evolveUndo
|
|
21748
22050
|
});
|
|
21749
|
-
import { existsSync as
|
|
22051
|
+
import { existsSync as existsSync45 } from "fs";
|
|
21750
22052
|
function ensureDb3() {
|
|
21751
|
-
if (!
|
|
22053
|
+
if (!existsSync45(DB_PATH)) {
|
|
21752
22054
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
21753
22055
|
process.exit(1);
|
|
21754
22056
|
}
|
|
@@ -22110,7 +22412,7 @@ var init_evolve = __esm({
|
|
|
22110
22412
|
|
|
22111
22413
|
// src/setup.ts
|
|
22112
22414
|
var setup_exports = {};
|
|
22113
|
-
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";
|
|
22114
22416
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22115
22417
|
import { createInterface as createInterface7 } from "readline";
|
|
22116
22418
|
import { join as join25 } from "path";
|
|
@@ -22188,10 +22490,10 @@ async function setup() {
|
|
|
22188
22490
|
}
|
|
22189
22491
|
console.log("");
|
|
22190
22492
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
22191
|
-
if (!
|
|
22493
|
+
if (!existsSync46(dir)) mkdirSync12(dir, { recursive: true });
|
|
22192
22494
|
}
|
|
22193
22495
|
const env = {};
|
|
22194
|
-
const envSource =
|
|
22496
|
+
const envSource = existsSync46(ENV_PATH) ? ENV_PATH : existsSync46(".env") ? ".env" : null;
|
|
22195
22497
|
if (envSource) {
|
|
22196
22498
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
22197
22499
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -22202,8 +22504,8 @@ async function setup() {
|
|
|
22202
22504
|
}
|
|
22203
22505
|
}
|
|
22204
22506
|
const cwdDb = join25(process.cwd(), "cc-claw.db");
|
|
22205
|
-
if (
|
|
22206
|
-
const { size } =
|
|
22507
|
+
if (existsSync46(cwdDb) && !existsSync46(DB_PATH)) {
|
|
22508
|
+
const { size } = statSync8(cwdDb);
|
|
22207
22509
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
22208
22510
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
22209
22511
|
if (migrate) {
|
|
@@ -22622,7 +22924,7 @@ function registerCronCommands(cmd) {
|
|
|
22622
22924
|
const { cronList: cronList2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22623
22925
|
await cronList2(program.opts());
|
|
22624
22926
|
});
|
|
22625
|
-
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) => {
|
|
22626
22928
|
const { cronCreate: cronCreate2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22627
22929
|
await cronCreate2(program.opts(), opts);
|
|
22628
22930
|
});
|
|
@@ -22642,7 +22944,7 @@ function registerCronCommands(cmd) {
|
|
|
22642
22944
|
const { cronAction: cronAction2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22643
22945
|
await cronAction2(program.opts(), "run", id);
|
|
22644
22946
|
});
|
|
22645
|
-
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) => {
|
|
22646
22948
|
const { cronEdit: cronEdit2 } = await Promise.resolve().then(() => (init_cron2(), cron_exports2));
|
|
22647
22949
|
await cronEdit2(program.opts(), id, opts);
|
|
22648
22950
|
});
|