cc-claw 0.12.2 → 0.12.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 +389 -179
- 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.12.
|
|
75
|
+
VERSION = true ? "0.12.3" : (() => {
|
|
76
76
|
try {
|
|
77
77
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
78
78
|
} catch {
|
|
@@ -153,6 +153,9 @@ function migrateAgentColumns(db3) {
|
|
|
153
153
|
if (!colNames.has("name")) db3.exec("ALTER TABLE agents ADD COLUMN name TEXT");
|
|
154
154
|
if (!colNames.has("description")) db3.exec("ALTER TABLE agents ADD COLUMN description TEXT");
|
|
155
155
|
if (!colNames.has("persona")) db3.exec("ALTER TABLE agents ADD COLUMN persona TEXT");
|
|
156
|
+
if (!colNames.has("stderr")) db3.exec("ALTER TABLE agents ADD COLUMN stderr TEXT");
|
|
157
|
+
if (!colNames.has("durationMs")) db3.exec("ALTER TABLE agents ADD COLUMN durationMs INTEGER");
|
|
158
|
+
if (!colNames.has("signal")) db3.exec("ALTER TABLE agents ADD COLUMN signal TEXT");
|
|
156
159
|
}
|
|
157
160
|
function initAgentTables(db3) {
|
|
158
161
|
db3.exec(`
|
|
@@ -329,10 +332,21 @@ function updateAgentOutput(db3, id) {
|
|
|
329
332
|
function updateAgentResult(db3, id, opts) {
|
|
330
333
|
db3.prepare(`
|
|
331
334
|
UPDATE agents SET exitCode = ?, resultSummary = ?, tokenInput = ?, tokenOutput = ?,
|
|
335
|
+
stderr = ?, durationMs = ?, signal = ?,
|
|
332
336
|
status = CASE WHEN ? = 0 THEN 'completed' ELSE 'failed' END,
|
|
333
337
|
completedAt = datetime('now')
|
|
334
338
|
WHERE id = ?
|
|
335
|
-
`).run(
|
|
339
|
+
`).run(
|
|
340
|
+
opts.exitCode,
|
|
341
|
+
opts.resultSummary ?? null,
|
|
342
|
+
opts.tokenInput ?? 0,
|
|
343
|
+
opts.tokenOutput ?? 0,
|
|
344
|
+
opts.stderr ?? null,
|
|
345
|
+
opts.durationMs ?? null,
|
|
346
|
+
opts.signal ?? null,
|
|
347
|
+
opts.exitCode,
|
|
348
|
+
id
|
|
349
|
+
);
|
|
336
350
|
}
|
|
337
351
|
function updateAgentMcpsAdded(db3, id, mcps2) {
|
|
338
352
|
db3.prepare("UPDATE agents SET mcpsAdded = ? WHERE id = ?").run(JSON.stringify(mcps2), id);
|
|
@@ -3463,13 +3477,25 @@ var init_claude = __esm({
|
|
|
3463
3477
|
import { existsSync as existsSync3 } from "fs";
|
|
3464
3478
|
import { execSync as execSync2 } from "child_process";
|
|
3465
3479
|
import { join as join5 } from "path";
|
|
3466
|
-
|
|
3480
|
+
function stripThinkingContent(text) {
|
|
3481
|
+
let result = text;
|
|
3482
|
+
for (const pattern of THINKING_PATTERNS) {
|
|
3483
|
+
result = result.replace(pattern, "");
|
|
3484
|
+
}
|
|
3485
|
+
return result.trim();
|
|
3486
|
+
}
|
|
3487
|
+
var THINKING_PATTERNS, GeminiAdapter;
|
|
3467
3488
|
var init_gemini = __esm({
|
|
3468
3489
|
"src/backends/gemini.ts"() {
|
|
3469
3490
|
"use strict";
|
|
3470
3491
|
init_store5();
|
|
3471
3492
|
init_env();
|
|
3472
3493
|
init_paths();
|
|
3494
|
+
THINKING_PATTERNS = [
|
|
3495
|
+
/<think>[\s\S]*?<\/think>/gi,
|
|
3496
|
+
/<thinking>[\s\S]*?<\/thinking>/gi,
|
|
3497
|
+
/\[Thought:\s*true\][\s\S]*?(?:\[\/Thought\]|\[Thought:\s*false\])/gi
|
|
3498
|
+
];
|
|
3473
3499
|
GeminiAdapter = class {
|
|
3474
3500
|
id = "gemini";
|
|
3475
3501
|
displayName = "Gemini";
|
|
@@ -3579,8 +3605,12 @@ var init_gemini = __esm({
|
|
|
3579
3605
|
if (line.type === "init") {
|
|
3580
3606
|
events.push({ type: "init", sessionId: line.session_id });
|
|
3581
3607
|
} else if (line.type === "message" && line.role === "assistant") {
|
|
3582
|
-
if (line.
|
|
3583
|
-
|
|
3608
|
+
if (line.thought === true) {
|
|
3609
|
+
} else if (line.content) {
|
|
3610
|
+
const cleaned = stripThinkingContent(line.content);
|
|
3611
|
+
if (cleaned) {
|
|
3612
|
+
events.push({ type: "text", text: cleaned });
|
|
3613
|
+
}
|
|
3584
3614
|
}
|
|
3585
3615
|
} else if (line.type === "tool_use") {
|
|
3586
3616
|
events.push({
|
|
@@ -5434,6 +5464,7 @@ function spawnAgentProcess(runner, opts, callbacks) {
|
|
|
5434
5464
|
const rl2 = createInterface2({ input: child.stdout });
|
|
5435
5465
|
rl2.on("line", (line) => {
|
|
5436
5466
|
try {
|
|
5467
|
+
callbacks.onRawLine?.(line);
|
|
5437
5468
|
const raw = JSON.parse(line);
|
|
5438
5469
|
const events = runner.parseLine(raw);
|
|
5439
5470
|
for (const event of events) {
|
|
@@ -5788,6 +5819,103 @@ var init_loader2 = __esm({
|
|
|
5788
5819
|
}
|
|
5789
5820
|
});
|
|
5790
5821
|
|
|
5822
|
+
// src/agents/agent-log.ts
|
|
5823
|
+
import { writeFileSync as writeFileSync3, readdirSync as readdirSync5, statSync as statSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
5824
|
+
import { join as join10 } from "path";
|
|
5825
|
+
function truncate(text, maxBytes) {
|
|
5826
|
+
if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
|
|
5827
|
+
let lo = 0, hi = text.length;
|
|
5828
|
+
while (lo < hi) {
|
|
5829
|
+
const mid = lo + hi + 1 >>> 1;
|
|
5830
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf-8") <= maxBytes) lo = mid;
|
|
5831
|
+
else hi = mid - 1;
|
|
5832
|
+
}
|
|
5833
|
+
const truncated = text.slice(0, lo);
|
|
5834
|
+
const droppedBytes = Buffer.byteLength(text, "utf-8") - Buffer.byteLength(truncated, "utf-8");
|
|
5835
|
+
return truncated + `
|
|
5836
|
+
[...truncated ${droppedBytes} bytes...]`;
|
|
5837
|
+
}
|
|
5838
|
+
function writeAgentLog(data) {
|
|
5839
|
+
const logPath = join10(AGENTS_PATH, `${data.agentId}.log`);
|
|
5840
|
+
const exitDisplay = data.exitCodeForced ? `${data.exitCode} (forced \u2014 no output from original exit code 0)` : String(data.exitCode ?? "null");
|
|
5841
|
+
const stderrContent = truncate(data.stderr || "(empty)", MAX_STDERR_BYTES);
|
|
5842
|
+
const stdoutContent = truncate(data.rawStdoutLines.join("\n") || "(empty)", MAX_STDOUT_BYTES);
|
|
5843
|
+
const lines = [
|
|
5844
|
+
"=== Agent Execution Log ===",
|
|
5845
|
+
`Agent ID: ${data.agentId}`,
|
|
5846
|
+
`Runner: ${data.runner}`,
|
|
5847
|
+
`Model: ${data.model}`,
|
|
5848
|
+
`Task: ${data.task.slice(0, 200)}${data.task.length > 200 ? "..." : ""}`,
|
|
5849
|
+
`Started: ${data.startedAt.toISOString()}`,
|
|
5850
|
+
`Duration: ${data.durationMs}ms`,
|
|
5851
|
+
`Exit Code: ${exitDisplay}`,
|
|
5852
|
+
`Signal: ${data.signal ?? "null"}`,
|
|
5853
|
+
`Tokens: ${data.tokenInput} in / ${data.tokenOutput} out`,
|
|
5854
|
+
"",
|
|
5855
|
+
"--- STDERR ---",
|
|
5856
|
+
stderrContent,
|
|
5857
|
+
"",
|
|
5858
|
+
"--- STDOUT (raw NDJSON lines) ---",
|
|
5859
|
+
stdoutContent,
|
|
5860
|
+
""
|
|
5861
|
+
];
|
|
5862
|
+
try {
|
|
5863
|
+
mkdirSync3(AGENTS_PATH, { recursive: true });
|
|
5864
|
+
writeFileSync3(logPath, lines.join("\n"), "utf-8");
|
|
5865
|
+
} catch (err) {
|
|
5866
|
+
log(`[agent-log] Failed to write log for ${data.agentId}: ${err}`);
|
|
5867
|
+
}
|
|
5868
|
+
return logPath;
|
|
5869
|
+
}
|
|
5870
|
+
function pruneAgentLogs() {
|
|
5871
|
+
try {
|
|
5872
|
+
mkdirSync3(AGENTS_PATH, { recursive: true });
|
|
5873
|
+
const files = readdirSync5(AGENTS_PATH).filter((f) => f.endsWith(".log")).map((f) => {
|
|
5874
|
+
const fullPath = join10(AGENTS_PATH, f);
|
|
5875
|
+
const stat2 = statSync3(fullPath);
|
|
5876
|
+
return { path: fullPath, mtime: stat2.mtimeMs, size: stat2.size };
|
|
5877
|
+
});
|
|
5878
|
+
const now = Date.now();
|
|
5879
|
+
const remaining = files.filter((f) => {
|
|
5880
|
+
if (now - f.mtime > MAX_AGE_MS) {
|
|
5881
|
+
try {
|
|
5882
|
+
unlinkSync4(f.path);
|
|
5883
|
+
} catch {
|
|
5884
|
+
}
|
|
5885
|
+
return false;
|
|
5886
|
+
}
|
|
5887
|
+
return true;
|
|
5888
|
+
});
|
|
5889
|
+
remaining.sort((a, b) => a.mtime - b.mtime);
|
|
5890
|
+
let totalSize = remaining.reduce((sum, f) => sum + f.size, 0);
|
|
5891
|
+
for (const f of remaining) {
|
|
5892
|
+
if (totalSize <= MAX_DIR_BYTES) break;
|
|
5893
|
+
try {
|
|
5894
|
+
unlinkSync4(f.path);
|
|
5895
|
+
totalSize -= f.size;
|
|
5896
|
+
} catch {
|
|
5897
|
+
}
|
|
5898
|
+
}
|
|
5899
|
+
if (files.length > remaining.length) {
|
|
5900
|
+
log(`[agent-log] Pruned ${files.length - remaining.length} old log file(s)`);
|
|
5901
|
+
}
|
|
5902
|
+
} catch (err) {
|
|
5903
|
+
log(`[agent-log] Prune error: ${err}`);
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
var MAX_STDERR_BYTES, MAX_STDOUT_BYTES, MAX_AGE_MS, MAX_DIR_BYTES;
|
|
5907
|
+
var init_agent_log = __esm({
|
|
5908
|
+
"src/agents/agent-log.ts"() {
|
|
5909
|
+
"use strict";
|
|
5910
|
+
init_paths();
|
|
5911
|
+
init_log();
|
|
5912
|
+
MAX_STDERR_BYTES = 50 * 1024;
|
|
5913
|
+
MAX_STDOUT_BYTES = 100 * 1024;
|
|
5914
|
+
MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
5915
|
+
MAX_DIR_BYTES = 50 * 1024 * 1024;
|
|
5916
|
+
}
|
|
5917
|
+
});
|
|
5918
|
+
|
|
5791
5919
|
// src/agents/orchestrator.ts
|
|
5792
5920
|
import { existsSync as existsSync10 } from "fs";
|
|
5793
5921
|
async function withRunnerLock(runnerId, fn) {
|
|
@@ -5857,6 +5985,19 @@ async function spawnSubAgent(chatId, opts) {
|
|
|
5857
5985
|
const orchestrationId = getOrCreateOrchestration(chatId);
|
|
5858
5986
|
const runner = getRunner(opts.runner);
|
|
5859
5987
|
if (!runner) throw new Error(`Unknown runner: ${opts.runner}`);
|
|
5988
|
+
if (opts.model) {
|
|
5989
|
+
try {
|
|
5990
|
+
const { getAdapter: getAdapter2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
5991
|
+
const adapter = getAdapter2(opts.runner);
|
|
5992
|
+
if (adapter.availableModels && !adapter.availableModels[opts.model]) {
|
|
5993
|
+
const validModels = Object.keys(adapter.availableModels).join(", ");
|
|
5994
|
+
throw new Error(`Unknown model "${opts.model}" for ${opts.runner}. Available: ${validModels}`);
|
|
5995
|
+
}
|
|
5996
|
+
} catch (err) {
|
|
5997
|
+
if (err instanceof Error && err.message.startsWith("Unknown model")) throw err;
|
|
5998
|
+
warn(`[orchestrator] Could not validate model "${opts.model}" for ${opts.runner}: ${err}`);
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
5860
6001
|
const agentId = createAgent(db3, {
|
|
5861
6002
|
orchestrationId,
|
|
5862
6003
|
runnerId: opts.runner,
|
|
@@ -5979,7 +6120,9 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
5979
6120
|
}
|
|
5980
6121
|
updateAgentStatus(db3, agentId, "starting");
|
|
5981
6122
|
const stderrChunks = [];
|
|
6123
|
+
const rawStdoutLines = [];
|
|
5982
6124
|
let gotResult = false;
|
|
6125
|
+
const startedAt = Date.now();
|
|
5983
6126
|
const child = spawnAgentProcess(runner, {
|
|
5984
6127
|
task: opts.task,
|
|
5985
6128
|
cwd: opts.cwd,
|
|
@@ -5996,9 +6139,20 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
5996
6139
|
onText: () => {
|
|
5997
6140
|
updateAgentOutput(db3, agentId);
|
|
5998
6141
|
},
|
|
6142
|
+
onRawLine: (line) => rawStdoutLines.push(line),
|
|
5999
6143
|
onResult: (text, usage2) => {
|
|
6000
6144
|
gotResult = true;
|
|
6001
|
-
|
|
6145
|
+
const durationMs = Date.now() - startedAt;
|
|
6146
|
+
const stderr = Buffer.concat(stderrChunks).toString().trim();
|
|
6147
|
+
handleAgentComplete(agentId, chatId, text, usage2, mcpsAdded, {
|
|
6148
|
+
stderr,
|
|
6149
|
+
durationMs,
|
|
6150
|
+
rawStdoutLines,
|
|
6151
|
+
startedAt: new Date(startedAt),
|
|
6152
|
+
runner: opts.runner,
|
|
6153
|
+
model: opts.model ?? "default",
|
|
6154
|
+
task: opts.task
|
|
6155
|
+
});
|
|
6002
6156
|
},
|
|
6003
6157
|
onError: (err) => {
|
|
6004
6158
|
const detail = diagnoseSpawnError(err, exePath, opts.cwd);
|
|
@@ -6049,18 +6203,46 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
6049
6203
|
{ runner: opts.runner, task: opts.task, model: opts.model },
|
|
6050
6204
|
agentId
|
|
6051
6205
|
);
|
|
6052
|
-
child.on("close", (code) => {
|
|
6206
|
+
child.on("close", (code, signal) => {
|
|
6053
6207
|
if (gotResult) return;
|
|
6054
6208
|
const agent = getAgent(db3, agentId);
|
|
6055
6209
|
if (!agent || agent.status === "completed" || agent.status === "failed" || agent.status === "cancelled") return;
|
|
6056
6210
|
const stderr = Buffer.concat(stderrChunks).toString().trim();
|
|
6057
6211
|
if (stderr) warn(`[orchestrator] Agent ${agentId.slice(0, 8)} stderr: ${stderr.slice(0, 500)}`);
|
|
6058
|
-
const
|
|
6059
|
-
const
|
|
6060
|
-
|
|
6212
|
+
const durationMs = Date.now() - startedAt;
|
|
6213
|
+
const signalStr = signal ?? null;
|
|
6214
|
+
let exitCode = code ?? 1;
|
|
6215
|
+
let exitCodeForced = false;
|
|
6216
|
+
if (exitCode === 0) {
|
|
6217
|
+
exitCode = 1;
|
|
6218
|
+
exitCodeForced = true;
|
|
6219
|
+
warn(`[orchestrator] Agent ${agentId.slice(0, 8)}: exit code 0 with no output \u2014 forced to 1 (likely auth/model issue)`);
|
|
6220
|
+
}
|
|
6221
|
+
const errMsg = exitCodeForced ? `CLI exited cleanly but produced no output (${durationMs}ms) \u2014 likely auth failure or invalid model${stderr ? `: ${stderr.slice(0, 200)}` : ""}` : `CLI exited with code ${exitCode}${stderr ? `: ${stderr.slice(0, 200)}` : ""}`;
|
|
6222
|
+
updateAgentResult(db3, agentId, {
|
|
6223
|
+
exitCode,
|
|
6224
|
+
stderr: stderr || void 0,
|
|
6225
|
+
durationMs,
|
|
6226
|
+
signal: signalStr ?? void 0
|
|
6227
|
+
});
|
|
6061
6228
|
clearTimeout(timeoutTimers.get(agentId));
|
|
6062
6229
|
timeoutTimers.delete(agentId);
|
|
6063
6230
|
activeProcesses.delete(agentId);
|
|
6231
|
+
writeAgentLog({
|
|
6232
|
+
agentId,
|
|
6233
|
+
runner: opts.runner,
|
|
6234
|
+
model: opts.model ?? "default",
|
|
6235
|
+
task: opts.task,
|
|
6236
|
+
startedAt: new Date(startedAt),
|
|
6237
|
+
durationMs,
|
|
6238
|
+
exitCode,
|
|
6239
|
+
exitCodeForced,
|
|
6240
|
+
signal: signalStr,
|
|
6241
|
+
tokenInput: 0,
|
|
6242
|
+
tokenOutput: 0,
|
|
6243
|
+
stderr,
|
|
6244
|
+
rawStdoutLines
|
|
6245
|
+
});
|
|
6064
6246
|
const crashedAgent = getAgent(db3, agentId);
|
|
6065
6247
|
if (crashedAgent) {
|
|
6066
6248
|
const mcpsCrashed = crashedAgent.mcpsAdded ? JSON.parse(crashedAgent.mcpsAdded) : [];
|
|
@@ -6086,13 +6268,13 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
6086
6268
|
toAgentId: "main",
|
|
6087
6269
|
fromAgentId: agentId,
|
|
6088
6270
|
messageType: "task_result",
|
|
6089
|
-
content:
|
|
6271
|
+
content: `Failed: ${errMsg}`
|
|
6090
6272
|
});
|
|
6091
6273
|
notifyWithActivity(
|
|
6092
6274
|
chatId,
|
|
6093
|
-
`Agent ${agentId.slice(0, 8)}
|
|
6094
|
-
|
|
6095
|
-
{ exitCode, stderr: stderr?.slice(0,
|
|
6275
|
+
`Agent ${agentId.slice(0, 8)} failed (code ${exitCode}, ${durationMs}ms)${stderr ? ` \u2014 ${stderr.slice(0, 100)}` : ""}`,
|
|
6276
|
+
"agent_failed",
|
|
6277
|
+
{ exitCode, exitCodeForced, durationMs, signal: signalStr, stderr: stderr?.slice(0, 500) },
|
|
6096
6278
|
agentId
|
|
6097
6279
|
);
|
|
6098
6280
|
const activeAgents = listActiveAgents(db3);
|
|
@@ -6125,7 +6307,7 @@ function diagnoseSpawnError(err, exePath, cwd) {
|
|
|
6125
6307
|
}
|
|
6126
6308
|
return err.message;
|
|
6127
6309
|
}
|
|
6128
|
-
async function handleAgentComplete(agentId, chatId, resultText, usage2, mcpsAdded) {
|
|
6310
|
+
async function handleAgentComplete(agentId, chatId, resultText, usage2, mcpsAdded, diagnostics) {
|
|
6129
6311
|
const db3 = getDb();
|
|
6130
6312
|
const agent = getAgent(db3, agentId);
|
|
6131
6313
|
if (!agent) return;
|
|
@@ -6136,8 +6318,26 @@ async function handleAgentComplete(agentId, chatId, resultText, usage2, mcpsAdde
|
|
|
6136
6318
|
exitCode: 0,
|
|
6137
6319
|
resultSummary: resultText.slice(0, 1e4),
|
|
6138
6320
|
tokenInput: usage2?.input ?? 0,
|
|
6139
|
-
tokenOutput: usage2?.output ?? 0
|
|
6321
|
+
tokenOutput: usage2?.output ?? 0,
|
|
6322
|
+
stderr: diagnostics?.stderr || void 0,
|
|
6323
|
+
durationMs: diagnostics?.durationMs
|
|
6140
6324
|
});
|
|
6325
|
+
if (diagnostics) {
|
|
6326
|
+
writeAgentLog({
|
|
6327
|
+
agentId,
|
|
6328
|
+
runner: diagnostics.runner,
|
|
6329
|
+
model: diagnostics.model,
|
|
6330
|
+
task: diagnostics.task,
|
|
6331
|
+
startedAt: diagnostics.startedAt,
|
|
6332
|
+
durationMs: diagnostics.durationMs,
|
|
6333
|
+
exitCode: 0,
|
|
6334
|
+
signal: null,
|
|
6335
|
+
tokenInput: usage2?.input ?? 0,
|
|
6336
|
+
tokenOutput: usage2?.output ?? 0,
|
|
6337
|
+
stderr: diagnostics.stderr,
|
|
6338
|
+
rawStdoutLines: diagnostics.rawStdoutLines
|
|
6339
|
+
});
|
|
6340
|
+
}
|
|
6141
6341
|
if (usage2) {
|
|
6142
6342
|
const runner = getRunner(agent.runnerId);
|
|
6143
6343
|
if (runner) {
|
|
@@ -6193,7 +6393,15 @@ async function handleAgentComplete(agentId, chatId, resultText, usage2, mcpsAdde
|
|
|
6193
6393
|
chatId,
|
|
6194
6394
|
`Agent ${agentId.slice(0, 8)} completed \u2192 ${usage2?.input ?? 0} in / ${usage2?.output ?? 0} out tokens`,
|
|
6195
6395
|
"agent_completed",
|
|
6196
|
-
{
|
|
6396
|
+
{
|
|
6397
|
+
runner: agent.runnerId,
|
|
6398
|
+
task: agent.task,
|
|
6399
|
+
tokenInput: usage2?.input,
|
|
6400
|
+
tokenOutput: usage2?.output,
|
|
6401
|
+
resultPreview: resultText.slice(0, 200),
|
|
6402
|
+
durationMs: diagnostics?.durationMs,
|
|
6403
|
+
stderr: diagnostics?.stderr?.slice(0, 500) || void 0
|
|
6404
|
+
},
|
|
6197
6405
|
agentId
|
|
6198
6406
|
);
|
|
6199
6407
|
const activeAgents = listActiveAgents(db3);
|
|
@@ -6319,6 +6527,7 @@ function shutdownOrchestrator() {
|
|
|
6319
6527
|
}
|
|
6320
6528
|
function initOrchestrator() {
|
|
6321
6529
|
cleanupOrphanedMcpConfigs();
|
|
6530
|
+
pruneAgentLogs();
|
|
6322
6531
|
const db3 = getDb();
|
|
6323
6532
|
const staleCount = cleanupStaleAgents(db3);
|
|
6324
6533
|
if (staleCount > 0) {
|
|
@@ -6341,6 +6550,7 @@ var init_orchestrator = __esm({
|
|
|
6341
6550
|
init_log();
|
|
6342
6551
|
init_store3();
|
|
6343
6552
|
init_loader2();
|
|
6553
|
+
init_agent_log();
|
|
6344
6554
|
activeProcesses = /* @__PURE__ */ new Map();
|
|
6345
6555
|
timeoutTimers = /* @__PURE__ */ new Map();
|
|
6346
6556
|
runnerLocks = /* @__PURE__ */ new Map();
|
|
@@ -6734,19 +6944,19 @@ __export(analyze_exports, {
|
|
|
6734
6944
|
});
|
|
6735
6945
|
import { spawn as spawn4 } from "child_process";
|
|
6736
6946
|
import { createInterface as createInterface3 } from "readline";
|
|
6737
|
-
import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as
|
|
6738
|
-
import { join as
|
|
6947
|
+
import { readFileSync as readFileSync6, existsSync as existsSync11, readdirSync as readdirSync6, statSync as statSync4 } from "fs";
|
|
6948
|
+
import { join as join11 } from "path";
|
|
6739
6949
|
import { homedir as homedir4 } from "os";
|
|
6740
6950
|
function discoverReflectionTargets() {
|
|
6741
|
-
const ccClawHome =
|
|
6951
|
+
const ccClawHome = join11(homedir4(), ".cc-claw");
|
|
6742
6952
|
const targets = [];
|
|
6743
6953
|
try {
|
|
6744
|
-
const skillsDir =
|
|
6954
|
+
const skillsDir = join11(ccClawHome, "workspace", "skills");
|
|
6745
6955
|
if (existsSync11(skillsDir)) {
|
|
6746
|
-
for (const entry of
|
|
6747
|
-
const entryPath =
|
|
6748
|
-
if (!
|
|
6749
|
-
const skillFile =
|
|
6956
|
+
for (const entry of readdirSync6(skillsDir)) {
|
|
6957
|
+
const entryPath = join11(skillsDir, entry);
|
|
6958
|
+
if (!statSync4(entryPath).isDirectory()) continue;
|
|
6959
|
+
const skillFile = join11(entryPath, "SKILL.md");
|
|
6750
6960
|
if (!existsSync11(skillFile)) continue;
|
|
6751
6961
|
let desc = "skill";
|
|
6752
6962
|
try {
|
|
@@ -6761,9 +6971,9 @@ function discoverReflectionTargets() {
|
|
|
6761
6971
|
} catch {
|
|
6762
6972
|
}
|
|
6763
6973
|
try {
|
|
6764
|
-
const contextDir =
|
|
6974
|
+
const contextDir = join11(ccClawHome, "workspace", "context");
|
|
6765
6975
|
if (existsSync11(contextDir)) {
|
|
6766
|
-
for (const entry of
|
|
6976
|
+
for (const entry of readdirSync6(contextDir)) {
|
|
6767
6977
|
if (!entry.endsWith(".md")) continue;
|
|
6768
6978
|
const name = entry.replace(/\.md$/, "");
|
|
6769
6979
|
targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
|
|
@@ -6944,7 +7154,7 @@ function resolveReflectionAdapter(chatId) {
|
|
|
6944
7154
|
}
|
|
6945
7155
|
function readIdentityFile(filename) {
|
|
6946
7156
|
try {
|
|
6947
|
-
return readFileSync6(
|
|
7157
|
+
return readFileSync6(join11(IDENTITY_PATH, filename), "utf-8");
|
|
6948
7158
|
} catch {
|
|
6949
7159
|
return "";
|
|
6950
7160
|
}
|
|
@@ -7180,8 +7390,8 @@ __export(apply_exports, {
|
|
|
7180
7390
|
isTargetAllowed: () => isTargetAllowed,
|
|
7181
7391
|
rollbackInsight: () => rollbackInsight
|
|
7182
7392
|
});
|
|
7183
|
-
import { readFileSync as readFileSync7, writeFileSync as
|
|
7184
|
-
import { join as
|
|
7393
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync12, mkdirSync as mkdirSync4, readdirSync as readdirSync7, unlinkSync as unlinkSync5 } from "fs";
|
|
7394
|
+
import { join as join12, dirname as dirname2 } from "path";
|
|
7185
7395
|
function isTargetAllowed(relativePath) {
|
|
7186
7396
|
if (relativePath.includes("..")) return false;
|
|
7187
7397
|
if (!relativePath.endsWith(".md")) return false;
|
|
@@ -7235,11 +7445,11 @@ function pruneBackups(absolutePath) {
|
|
|
7235
7445
|
const dir = dirname2(absolutePath);
|
|
7236
7446
|
const baseName = absolutePath.split("/").pop() ?? "";
|
|
7237
7447
|
try {
|
|
7238
|
-
const backups =
|
|
7448
|
+
const backups = readdirSync7(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join12(dir, f));
|
|
7239
7449
|
while (backups.length > MAX_BACKUPS_PER_FILE) {
|
|
7240
7450
|
const oldest = backups.shift();
|
|
7241
7451
|
try {
|
|
7242
|
-
|
|
7452
|
+
unlinkSync5(oldest);
|
|
7243
7453
|
} catch {
|
|
7244
7454
|
}
|
|
7245
7455
|
}
|
|
@@ -7261,7 +7471,7 @@ async function applyInsight(insightId) {
|
|
|
7261
7471
|
if (!isTargetAllowed(insight.targetFile)) {
|
|
7262
7472
|
return { success: false, message: `Target file "${insight.targetFile}" is not in the allowed list` };
|
|
7263
7473
|
}
|
|
7264
|
-
const absolutePath =
|
|
7474
|
+
const absolutePath = join12(CC_CLAW_HOME, insight.targetFile);
|
|
7265
7475
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
7266
7476
|
if (existsSync12(absolutePath)) {
|
|
7267
7477
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
@@ -7295,14 +7505,14 @@ async function applyInsight(insightId) {
|
|
|
7295
7505
|
try {
|
|
7296
7506
|
const parentDir = dirname2(absolutePath);
|
|
7297
7507
|
if (!existsSync12(parentDir)) {
|
|
7298
|
-
|
|
7508
|
+
mkdirSync4(parentDir, { recursive: true });
|
|
7299
7509
|
}
|
|
7300
7510
|
if (original) {
|
|
7301
|
-
|
|
7511
|
+
writeFileSync4(backupPath, original, "utf-8");
|
|
7302
7512
|
pruneBackups(absolutePath);
|
|
7303
7513
|
}
|
|
7304
7514
|
const newContent = applyDiff(original, insight.proposedDiff, insight.proposedAction);
|
|
7305
|
-
|
|
7515
|
+
writeFileSync4(absolutePath, newContent, "utf-8");
|
|
7306
7516
|
const rollbackData = JSON.stringify({ original, backupPath, appliedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
7307
7517
|
updateInsightRollback(db3, insightId, rollbackData);
|
|
7308
7518
|
updateInsightStatus(db3, insightId, "applied");
|
|
@@ -7330,7 +7540,7 @@ async function applyInsight(insightId) {
|
|
|
7330
7540
|
warn(`[reflection/apply] Failed to apply insight #${insightId}: ${msg}`);
|
|
7331
7541
|
try {
|
|
7332
7542
|
if (original) {
|
|
7333
|
-
|
|
7543
|
+
writeFileSync4(absolutePath, original, "utf-8");
|
|
7334
7544
|
}
|
|
7335
7545
|
} catch {
|
|
7336
7546
|
}
|
|
@@ -7358,9 +7568,9 @@ async function rollbackInsight(insightId) {
|
|
|
7358
7568
|
} catch {
|
|
7359
7569
|
return { success: false, message: `Insight #${insightId} has malformed rollback data` };
|
|
7360
7570
|
}
|
|
7361
|
-
const absolutePath =
|
|
7571
|
+
const absolutePath = join12(CC_CLAW_HOME, insight.targetFile);
|
|
7362
7572
|
try {
|
|
7363
|
-
|
|
7573
|
+
writeFileSync4(absolutePath, rollback.original, "utf-8");
|
|
7364
7574
|
updateInsightStatus(db3, insightId, "rolled_back");
|
|
7365
7575
|
syncNativeCliFiles();
|
|
7366
7576
|
const chatId = insight.chatId ?? "global";
|
|
@@ -7391,8 +7601,8 @@ function calculateDrift(chatId) {
|
|
|
7391
7601
|
if (!row || !row.baselineSoulMd && !row.baselineUserMd) {
|
|
7392
7602
|
return null;
|
|
7393
7603
|
}
|
|
7394
|
-
const soulPath =
|
|
7395
|
-
const userPath =
|
|
7604
|
+
const soulPath = join12(CC_CLAW_HOME, "identity/SOUL.md");
|
|
7605
|
+
const userPath = join12(CC_CLAW_HOME, "identity/USER.md");
|
|
7396
7606
|
const soulDrift = computeLineDrift(row.baselineSoulMd, soulPath);
|
|
7397
7607
|
const userDrift = computeLineDrift(row.baselineUserMd, userPath);
|
|
7398
7608
|
return { soulDrift, userDrift };
|
|
@@ -7453,7 +7663,7 @@ __export(server_exports, {
|
|
|
7453
7663
|
});
|
|
7454
7664
|
import { createServer } from "http";
|
|
7455
7665
|
import { randomBytes } from "crypto";
|
|
7456
|
-
import { writeFileSync as
|
|
7666
|
+
import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync13 } from "fs";
|
|
7457
7667
|
function createSubAgentToken(agentId) {
|
|
7458
7668
|
const token = `sub:${agentId.slice(0, 8)}:${randomBytes(16).toString("hex")}`;
|
|
7459
7669
|
subAgentTokens.set(token, agentId);
|
|
@@ -8222,11 +8432,11 @@ data: ${JSON.stringify(data)}
|
|
|
8222
8432
|
const body = JSON.parse(await readBody(req));
|
|
8223
8433
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
8224
8434
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
8225
|
-
const { join:
|
|
8435
|
+
const { join: join27 } = await import("path");
|
|
8226
8436
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
8227
8437
|
const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
|
|
8228
|
-
const soulPath =
|
|
8229
|
-
const userPath =
|
|
8438
|
+
const soulPath = join27(home, "identity/SOUL.md");
|
|
8439
|
+
const userPath = join27(home, "identity/USER.md");
|
|
8230
8440
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
8231
8441
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
8232
8442
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -8289,9 +8499,9 @@ data: ${JSON.stringify(data)}
|
|
|
8289
8499
|
});
|
|
8290
8500
|
server.listen(PORT, "127.0.0.1");
|
|
8291
8501
|
try {
|
|
8292
|
-
|
|
8502
|
+
mkdirSync5(DATA_PATH, { recursive: true });
|
|
8293
8503
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
8294
|
-
|
|
8504
|
+
writeFileSync5(tokenPath, DASHBOARD_TOKEN, { mode: 384 });
|
|
8295
8505
|
} catch (err) {
|
|
8296
8506
|
log(`[api] Warning: could not write api-token file: ${errorMessage(err)}`);
|
|
8297
8507
|
}
|
|
@@ -9984,7 +10194,7 @@ var init_cron = __esm({
|
|
|
9984
10194
|
});
|
|
9985
10195
|
|
|
9986
10196
|
// src/agents/runners/wrap-backend.ts
|
|
9987
|
-
import { join as
|
|
10197
|
+
import { join as join13 } from "path";
|
|
9988
10198
|
function buildMcpCommands(backendId) {
|
|
9989
10199
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
9990
10200
|
return {
|
|
@@ -10078,7 +10288,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
10078
10288
|
const configPath = writeMcpConfigFile(server);
|
|
10079
10289
|
return ["--mcp-config", configPath];
|
|
10080
10290
|
},
|
|
10081
|
-
getSkillPath: () =>
|
|
10291
|
+
getSkillPath: () => join13(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
10082
10292
|
};
|
|
10083
10293
|
}
|
|
10084
10294
|
var BACKEND_CAPABILITIES;
|
|
@@ -10129,8 +10339,8 @@ var init_wrap_backend = __esm({
|
|
|
10129
10339
|
});
|
|
10130
10340
|
|
|
10131
10341
|
// src/agents/runners/config-loader.ts
|
|
10132
|
-
import { readFileSync as readFileSync8, readdirSync as
|
|
10133
|
-
import { join as
|
|
10342
|
+
import { readFileSync as readFileSync8, readdirSync as readdirSync8, existsSync as existsSync14, mkdirSync as mkdirSync6, watchFile, unwatchFile } from "fs";
|
|
10343
|
+
import { join as join14 } from "path";
|
|
10134
10344
|
import { execFileSync } from "child_process";
|
|
10135
10345
|
function resolveExecutable(config2) {
|
|
10136
10346
|
if (existsSync14(config2.executable)) return config2.executable;
|
|
@@ -10266,7 +10476,7 @@ function configToRunner(config2) {
|
|
|
10266
10476
|
prepareMcpInjection() {
|
|
10267
10477
|
return [];
|
|
10268
10478
|
},
|
|
10269
|
-
getSkillPath: () =>
|
|
10479
|
+
getSkillPath: () => join14(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
10270
10480
|
};
|
|
10271
10481
|
}
|
|
10272
10482
|
function loadRunnerConfig(filePath) {
|
|
@@ -10280,13 +10490,13 @@ function loadRunnerConfig(filePath) {
|
|
|
10280
10490
|
}
|
|
10281
10491
|
function loadAllRunnerConfigs() {
|
|
10282
10492
|
if (!existsSync14(RUNNERS_PATH)) {
|
|
10283
|
-
|
|
10493
|
+
mkdirSync6(RUNNERS_PATH, { recursive: true });
|
|
10284
10494
|
return [];
|
|
10285
10495
|
}
|
|
10286
|
-
const files =
|
|
10496
|
+
const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
10287
10497
|
const configs = [];
|
|
10288
10498
|
for (const file of files) {
|
|
10289
|
-
const config2 = loadRunnerConfig(
|
|
10499
|
+
const config2 = loadRunnerConfig(join14(RUNNERS_PATH, file));
|
|
10290
10500
|
if (config2) configs.push(config2);
|
|
10291
10501
|
}
|
|
10292
10502
|
return configs;
|
|
@@ -10314,9 +10524,9 @@ function watchRunnerConfigs(onChange) {
|
|
|
10314
10524
|
watchedFiles.delete(prev);
|
|
10315
10525
|
}
|
|
10316
10526
|
}
|
|
10317
|
-
const files =
|
|
10527
|
+
const files = readdirSync8(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
10318
10528
|
for (const file of files) {
|
|
10319
|
-
const fullPath =
|
|
10529
|
+
const fullPath = join14(RUNNERS_PATH, file);
|
|
10320
10530
|
if (watchedFiles.has(fullPath)) continue;
|
|
10321
10531
|
watchedFiles.add(fullPath);
|
|
10322
10532
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -11024,7 +11234,7 @@ __export(discover_exports, {
|
|
|
11024
11234
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
11025
11235
|
import { createHash } from "crypto";
|
|
11026
11236
|
import { homedir as homedir5 } from "os";
|
|
11027
|
-
import { join as
|
|
11237
|
+
import { join as join15 } from "path";
|
|
11028
11238
|
function invalidateSkillCache() {
|
|
11029
11239
|
cachedSkills = null;
|
|
11030
11240
|
cacheTimestamp = 0;
|
|
@@ -11042,7 +11252,7 @@ async function discoverAllSkills() {
|
|
|
11042
11252
|
const rawSkills = [];
|
|
11043
11253
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
11044
11254
|
for (const backendId of getAllBackendIds()) {
|
|
11045
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [
|
|
11255
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join15(homedir5(), `.${backendId}`, "skills")];
|
|
11046
11256
|
for (const dir of dirs) {
|
|
11047
11257
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
11048
11258
|
}
|
|
@@ -11070,7 +11280,7 @@ async function scanSkillDir(skillsDir, source) {
|
|
|
11070
11280
|
let content;
|
|
11071
11281
|
let resolvedPath;
|
|
11072
11282
|
for (const candidate of SKILL_FILE_CANDIDATES) {
|
|
11073
|
-
const p =
|
|
11283
|
+
const p = join15(skillsDir, entry.name, candidate);
|
|
11074
11284
|
try {
|
|
11075
11285
|
content = await readFile2(p, "utf-8");
|
|
11076
11286
|
resolvedPath = p;
|
|
@@ -11173,15 +11383,15 @@ var init_discover = __esm({
|
|
|
11173
11383
|
init_backends();
|
|
11174
11384
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
11175
11385
|
BACKEND_SKILL_DIRS = {
|
|
11176
|
-
claude: [
|
|
11177
|
-
gemini: [
|
|
11386
|
+
claude: [join15(homedir5(), ".claude", "skills")],
|
|
11387
|
+
gemini: [join15(homedir5(), ".gemini", "skills")],
|
|
11178
11388
|
codex: [
|
|
11179
|
-
|
|
11180
|
-
|
|
11389
|
+
join15(homedir5(), ".agents", "skills"),
|
|
11390
|
+
join15(homedir5(), ".codex", "skills")
|
|
11181
11391
|
],
|
|
11182
11392
|
cursor: [
|
|
11183
|
-
|
|
11184
|
-
|
|
11393
|
+
join15(homedir5(), ".cursor", "skills"),
|
|
11394
|
+
join15(homedir5(), ".cursor", "skills-cursor")
|
|
11185
11395
|
]
|
|
11186
11396
|
};
|
|
11187
11397
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -11198,7 +11408,7 @@ __export(install_exports, {
|
|
|
11198
11408
|
});
|
|
11199
11409
|
import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
|
|
11200
11410
|
import { existsSync as existsSync15 } from "fs";
|
|
11201
|
-
import { join as
|
|
11411
|
+
import { join as join16, basename } from "path";
|
|
11202
11412
|
import { execSync as execSync6 } from "child_process";
|
|
11203
11413
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
11204
11414
|
let repoUrl;
|
|
@@ -11209,23 +11419,23 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
11209
11419
|
}
|
|
11210
11420
|
repoUrl = parsed.cloneUrl;
|
|
11211
11421
|
subPath = parsed.subPath;
|
|
11212
|
-
const tmpDir =
|
|
11422
|
+
const tmpDir = join16("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
11213
11423
|
try {
|
|
11214
11424
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
11215
11425
|
execSync6(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
11216
11426
|
stdio: "pipe",
|
|
11217
11427
|
timeout: 3e4
|
|
11218
11428
|
});
|
|
11219
|
-
if (!existsSync15(
|
|
11429
|
+
if (!existsSync15(join16(tmpDir, ".git"))) {
|
|
11220
11430
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
11221
11431
|
}
|
|
11222
|
-
const searchRoot = subPath ?
|
|
11432
|
+
const searchRoot = subPath ? join16(tmpDir, subPath) : tmpDir;
|
|
11223
11433
|
const skillDir = await findSkillDir(searchRoot);
|
|
11224
11434
|
if (!skillDir) {
|
|
11225
11435
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
11226
11436
|
}
|
|
11227
11437
|
const skillFolderName = basename(skillDir);
|
|
11228
|
-
const destDir =
|
|
11438
|
+
const destDir = join16(SKILLS_PATH, skillFolderName);
|
|
11229
11439
|
if (existsSync15(destDir)) {
|
|
11230
11440
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
11231
11441
|
}
|
|
@@ -11233,12 +11443,12 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
11233
11443
|
await cp(skillDir, destDir, { recursive: true });
|
|
11234
11444
|
let skillName = skillFolderName;
|
|
11235
11445
|
try {
|
|
11236
|
-
const content = await readFile3(
|
|
11446
|
+
const content = await readFile3(join16(destDir, "SKILL.md"), "utf-8");
|
|
11237
11447
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
11238
11448
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
11239
11449
|
} catch {
|
|
11240
11450
|
try {
|
|
11241
|
-
const content = await readFile3(
|
|
11451
|
+
const content = await readFile3(join16(destDir, "skill.md"), "utf-8");
|
|
11242
11452
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
11243
11453
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
11244
11454
|
} catch {
|
|
@@ -11273,15 +11483,15 @@ function parseGitHubUrl(input) {
|
|
|
11273
11483
|
async function findSkillDir(root) {
|
|
11274
11484
|
const candidates = ["SKILL.md", "skill.md"];
|
|
11275
11485
|
for (const c of candidates) {
|
|
11276
|
-
if (existsSync15(
|
|
11486
|
+
if (existsSync15(join16(root, c))) return root;
|
|
11277
11487
|
}
|
|
11278
11488
|
try {
|
|
11279
11489
|
const entries = await readdir2(root, { withFileTypes: true });
|
|
11280
11490
|
for (const entry of entries) {
|
|
11281
11491
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
11282
11492
|
for (const c of candidates) {
|
|
11283
|
-
if (existsSync15(
|
|
11284
|
-
return
|
|
11493
|
+
if (existsSync15(join16(root, entry.name, c))) {
|
|
11494
|
+
return join16(root, entry.name);
|
|
11285
11495
|
}
|
|
11286
11496
|
}
|
|
11287
11497
|
}
|
|
@@ -11293,15 +11503,15 @@ async function findSkillDir(root) {
|
|
|
11293
11503
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
11294
11504
|
let subEntries;
|
|
11295
11505
|
try {
|
|
11296
|
-
subEntries = await readdir2(
|
|
11506
|
+
subEntries = await readdir2(join16(root, entry.name), { withFileTypes: true });
|
|
11297
11507
|
} catch {
|
|
11298
11508
|
continue;
|
|
11299
11509
|
}
|
|
11300
11510
|
for (const sub of subEntries) {
|
|
11301
11511
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
11302
11512
|
for (const c of candidates) {
|
|
11303
|
-
if (existsSync15(
|
|
11304
|
-
return
|
|
11513
|
+
if (existsSync15(join16(root, entry.name, sub.name, c))) {
|
|
11514
|
+
return join16(root, entry.name, sub.name);
|
|
11305
11515
|
}
|
|
11306
11516
|
}
|
|
11307
11517
|
}
|
|
@@ -11319,8 +11529,8 @@ var init_install = __esm({
|
|
|
11319
11529
|
});
|
|
11320
11530
|
|
|
11321
11531
|
// src/bootstrap/profile.ts
|
|
11322
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
11323
|
-
import { join as
|
|
11532
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, existsSync as existsSync16 } from "fs";
|
|
11533
|
+
import { join as join17 } from "path";
|
|
11324
11534
|
function hasActiveProfile(chatId) {
|
|
11325
11535
|
return activeProfiles.has(chatId);
|
|
11326
11536
|
}
|
|
@@ -11423,7 +11633,7 @@ async function finalizeProfile(chatId, state, channel) {
|
|
|
11423
11633
|
"<!-- Add any additional preferences below this line -->",
|
|
11424
11634
|
""
|
|
11425
11635
|
].join("\n");
|
|
11426
|
-
|
|
11636
|
+
writeFileSync6(USER_PATH2, content, "utf-8");
|
|
11427
11637
|
activeProfiles.delete(chatId);
|
|
11428
11638
|
log(`[profile] User profile saved for chat ${chatId}`);
|
|
11429
11639
|
await channel.sendText(
|
|
@@ -11456,7 +11666,7 @@ function appendToUserProfile(key, value) {
|
|
|
11456
11666
|
const updated = content.trimEnd() + `
|
|
11457
11667
|
${line}
|
|
11458
11668
|
`;
|
|
11459
|
-
|
|
11669
|
+
writeFileSync6(USER_PATH2, updated, "utf-8");
|
|
11460
11670
|
log(`[profile] Appended preference: ${key}=${value}`);
|
|
11461
11671
|
}
|
|
11462
11672
|
var USER_PATH2, activeProfiles;
|
|
@@ -11465,14 +11675,14 @@ var init_profile = __esm({
|
|
|
11465
11675
|
"use strict";
|
|
11466
11676
|
init_paths();
|
|
11467
11677
|
init_log();
|
|
11468
|
-
USER_PATH2 =
|
|
11678
|
+
USER_PATH2 = join17(IDENTITY_PATH, "USER.md");
|
|
11469
11679
|
activeProfiles = /* @__PURE__ */ new Map();
|
|
11470
11680
|
}
|
|
11471
11681
|
});
|
|
11472
11682
|
|
|
11473
11683
|
// src/bootstrap/heartbeat.ts
|
|
11474
11684
|
import { readFileSync as readFileSync10, existsSync as existsSync17 } from "fs";
|
|
11475
|
-
import { join as
|
|
11685
|
+
import { join as join18 } from "path";
|
|
11476
11686
|
function initHeartbeat(channelReg) {
|
|
11477
11687
|
registry2 = channelReg;
|
|
11478
11688
|
}
|
|
@@ -11658,7 +11868,7 @@ var init_heartbeat = __esm({
|
|
|
11658
11868
|
init_backends();
|
|
11659
11869
|
init_health2();
|
|
11660
11870
|
init_log();
|
|
11661
|
-
HEARTBEAT_MD_PATH =
|
|
11871
|
+
HEARTBEAT_MD_PATH = join18(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
11662
11872
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
11663
11873
|
registry2 = null;
|
|
11664
11874
|
activeTimers2 = /* @__PURE__ */ new Map();
|
|
@@ -11841,9 +12051,9 @@ var init_classify = __esm({
|
|
|
11841
12051
|
});
|
|
11842
12052
|
|
|
11843
12053
|
// src/media/image-gen.ts
|
|
11844
|
-
import { mkdirSync as
|
|
12054
|
+
import { mkdirSync as mkdirSync7, existsSync as existsSync18 } from "fs";
|
|
11845
12055
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
11846
|
-
import { join as
|
|
12056
|
+
import { join as join19 } from "path";
|
|
11847
12057
|
async function generateImage(prompt) {
|
|
11848
12058
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
11849
12059
|
if (!apiKey) {
|
|
@@ -11891,11 +12101,11 @@ async function generateImage(prompt) {
|
|
|
11891
12101
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
11892
12102
|
}
|
|
11893
12103
|
if (!existsSync18(IMAGE_OUTPUT_DIR)) {
|
|
11894
|
-
|
|
12104
|
+
mkdirSync7(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
11895
12105
|
}
|
|
11896
12106
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
11897
12107
|
const filename = `img_${Date.now()}.${ext}`;
|
|
11898
|
-
const filePath =
|
|
12108
|
+
const filePath = join19(IMAGE_OUTPUT_DIR, filename);
|
|
11899
12109
|
const buffer = Buffer.from(imageData, "base64");
|
|
11900
12110
|
await writeFile2(filePath, buffer);
|
|
11901
12111
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
@@ -11910,8 +12120,8 @@ var init_image_gen = __esm({
|
|
|
11910
12120
|
"use strict";
|
|
11911
12121
|
init_log();
|
|
11912
12122
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
11913
|
-
IMAGE_OUTPUT_DIR =
|
|
11914
|
-
process.env.CC_CLAW_HOME ??
|
|
12123
|
+
IMAGE_OUTPUT_DIR = join19(
|
|
12124
|
+
process.env.CC_CLAW_HOME ?? join19(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
11915
12125
|
"data",
|
|
11916
12126
|
"images"
|
|
11917
12127
|
);
|
|
@@ -13150,7 +13360,7 @@ var init_pagination = __esm({
|
|
|
13150
13360
|
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2, mkdir as mkdir2, readdir as readdir3, stat } from "fs/promises";
|
|
13151
13361
|
import { existsSync as existsSync19 } from "fs";
|
|
13152
13362
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
13153
|
-
import { resolve as resolvePath, join as
|
|
13363
|
+
import { resolve as resolvePath, join as join20 } from "path";
|
|
13154
13364
|
import { homedir as homedir6 } from "os";
|
|
13155
13365
|
function parseMcpListOutput(output2) {
|
|
13156
13366
|
const results = [];
|
|
@@ -13393,7 +13603,7 @@ function getMediaRetentionMs() {
|
|
|
13393
13603
|
async function saveMedia(buffer, prefix, ext) {
|
|
13394
13604
|
await mkdir2(MEDIA_INCOMING_PATH, { recursive: true });
|
|
13395
13605
|
const filename = `${prefix}-${Date.now()}.${ext}`;
|
|
13396
|
-
const fullPath =
|
|
13606
|
+
const fullPath = join20(MEDIA_INCOMING_PATH, filename);
|
|
13397
13607
|
await writeFile3(fullPath, buffer);
|
|
13398
13608
|
return fullPath;
|
|
13399
13609
|
}
|
|
@@ -13407,7 +13617,7 @@ async function cleanupOldMedia() {
|
|
|
13407
13617
|
let removed = 0;
|
|
13408
13618
|
for (const file of files) {
|
|
13409
13619
|
try {
|
|
13410
|
-
const filePath =
|
|
13620
|
+
const filePath = join20(MEDIA_INCOMING_PATH, file);
|
|
13411
13621
|
const s = await stat(filePath);
|
|
13412
13622
|
if (now - s.mtimeMs > retentionMs) {
|
|
13413
13623
|
await unlink2(filePath);
|
|
@@ -16968,14 +17178,14 @@ Result: ${task.result.slice(0, 500)}` : ""
|
|
|
16968
17178
|
{ label: "USER.md", path: "identity/USER.md" }
|
|
16969
17179
|
];
|
|
16970
17180
|
const skillDirs = [
|
|
16971
|
-
|
|
17181
|
+
join20(homedir6(), ".cc-claw", "workspace", "skills")
|
|
16972
17182
|
];
|
|
16973
17183
|
try {
|
|
16974
|
-
const { readdirSync:
|
|
17184
|
+
const { readdirSync: readdirSync9, statSync: statSync10 } = await import("fs");
|
|
16975
17185
|
for (const dir of skillDirs) {
|
|
16976
17186
|
if (!existsSync19(dir)) continue;
|
|
16977
|
-
for (const entry of
|
|
16978
|
-
if (
|
|
17187
|
+
for (const entry of readdirSync9(dir)) {
|
|
17188
|
+
if (statSync10(join20(dir, entry)).isDirectory()) {
|
|
16979
17189
|
targets.push({ label: `skills/${entry}`, path: `workspace/skills/${entry}/SKILL.md` });
|
|
16980
17190
|
}
|
|
16981
17191
|
}
|
|
@@ -17128,10 +17338,10 @@ Pick a different file for this change. Identity files (SOUL/USER) shape personal
|
|
|
17128
17338
|
const current = getReflectionStatus2(getDb2(), chatId);
|
|
17129
17339
|
if (current === "frozen") {
|
|
17130
17340
|
const { readFileSync: readFileSync21, existsSync: existsSync47 } = await import("fs");
|
|
17131
|
-
const { join:
|
|
17341
|
+
const { join: join27 } = await import("path");
|
|
17132
17342
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
17133
|
-
const soulPath =
|
|
17134
|
-
const userPath =
|
|
17343
|
+
const soulPath = join27(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
17344
|
+
const userPath = join27(CC_CLAW_HOME3, "identity/USER.md");
|
|
17135
17345
|
const soul = existsSync47(soulPath) ? readFileSync21(soulPath, "utf-8") : "";
|
|
17136
17346
|
const user = existsSync47(userPath) ? readFileSync21(userPath, "utf-8") : "";
|
|
17137
17347
|
setReflectionStatus2(getDb2(), chatId, "active", soul, user);
|
|
@@ -17834,7 +18044,7 @@ var init_router = __esm({
|
|
|
17834
18044
|
]
|
|
17835
18045
|
};
|
|
17836
18046
|
USAGE_WINDOW_MAP = { "24h": "daily", "7d": "weekly" };
|
|
17837
|
-
MEDIA_INCOMING_PATH =
|
|
18047
|
+
MEDIA_INCOMING_PATH = join20(MEDIA_PATH, "incoming");
|
|
17838
18048
|
TONE_PATTERNS = [
|
|
17839
18049
|
// Humor / laughter
|
|
17840
18050
|
{ pattern: /\b(lol|lmao|rofl|haha|hehe|😂|🤣|funny|hilarious|joke)\b/i, emoji: "\u{1F923}" },
|
|
@@ -17971,7 +18181,7 @@ var init_router = __esm({
|
|
|
17971
18181
|
// src/skills/bootstrap.ts
|
|
17972
18182
|
import { existsSync as existsSync20 } from "fs";
|
|
17973
18183
|
import { readdir as readdir4, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
|
|
17974
|
-
import { join as
|
|
18184
|
+
import { join as join21, dirname as dirname3 } from "path";
|
|
17975
18185
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17976
18186
|
async function copyAgentManifestSkills() {
|
|
17977
18187
|
if (!existsSync20(PKG_SKILLS)) return;
|
|
@@ -17979,8 +18189,8 @@ async function copyAgentManifestSkills() {
|
|
|
17979
18189
|
const entries = await readdir4(PKG_SKILLS, { withFileTypes: true });
|
|
17980
18190
|
for (const entry of entries) {
|
|
17981
18191
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
17982
|
-
const src =
|
|
17983
|
-
const dest =
|
|
18192
|
+
const src = join21(PKG_SKILLS, entry.name);
|
|
18193
|
+
const dest = join21(SKILLS_PATH, entry.name);
|
|
17984
18194
|
if (existsSync20(dest)) continue;
|
|
17985
18195
|
await copyFile(src, dest);
|
|
17986
18196
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
@@ -17991,7 +18201,7 @@ async function copyAgentManifestSkills() {
|
|
|
17991
18201
|
}
|
|
17992
18202
|
async function bootstrapSkills() {
|
|
17993
18203
|
await copyAgentManifestSkills();
|
|
17994
|
-
const usmDir =
|
|
18204
|
+
const usmDir = join21(SKILLS_PATH, USM_DIR_NAME);
|
|
17995
18205
|
if (existsSync20(usmDir)) return;
|
|
17996
18206
|
try {
|
|
17997
18207
|
const entries = await readdir4(SKILLS_PATH);
|
|
@@ -18014,7 +18224,7 @@ async function bootstrapSkills() {
|
|
|
18014
18224
|
}
|
|
18015
18225
|
}
|
|
18016
18226
|
async function patchUsmForCcClaw(usmDir) {
|
|
18017
|
-
const skillPath =
|
|
18227
|
+
const skillPath = join21(usmDir, "SKILL.md");
|
|
18018
18228
|
if (!existsSync20(skillPath)) return;
|
|
18019
18229
|
try {
|
|
18020
18230
|
let content = await readFile6(skillPath, "utf-8");
|
|
@@ -18060,8 +18270,8 @@ var init_bootstrap = __esm({
|
|
|
18060
18270
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
18061
18271
|
USM_DIR_NAME = "universal-skills-manager";
|
|
18062
18272
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
18063
|
-
PKG_ROOT =
|
|
18064
|
-
PKG_SKILLS =
|
|
18273
|
+
PKG_ROOT = join21(dirname3(fileURLToPath2(import.meta.url)), "..", "..");
|
|
18274
|
+
PKG_SKILLS = join21(PKG_ROOT, "skills");
|
|
18065
18275
|
}
|
|
18066
18276
|
});
|
|
18067
18277
|
|
|
@@ -18275,8 +18485,8 @@ __export(ai_skill_exports, {
|
|
|
18275
18485
|
generateAiSkill: () => generateAiSkill,
|
|
18276
18486
|
installAiSkill: () => installAiSkill
|
|
18277
18487
|
});
|
|
18278
|
-
import { existsSync as existsSync21, writeFileSync as
|
|
18279
|
-
import { join as
|
|
18488
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "fs";
|
|
18489
|
+
import { join as join22 } from "path";
|
|
18280
18490
|
import { homedir as homedir7 } from "os";
|
|
18281
18491
|
function generateAiSkill() {
|
|
18282
18492
|
const version = VERSION;
|
|
@@ -18677,11 +18887,11 @@ function installAiSkill() {
|
|
|
18677
18887
|
const failed = [];
|
|
18678
18888
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
18679
18889
|
for (const dir of dirs) {
|
|
18680
|
-
const skillDir =
|
|
18681
|
-
const skillPath =
|
|
18890
|
+
const skillDir = join22(dir, "cc-claw-cli");
|
|
18891
|
+
const skillPath = join22(skillDir, "SKILL.md");
|
|
18682
18892
|
try {
|
|
18683
|
-
|
|
18684
|
-
|
|
18893
|
+
mkdirSync8(skillDir, { recursive: true });
|
|
18894
|
+
writeFileSync7(skillPath, skill, "utf-8");
|
|
18685
18895
|
installed.push(skillPath);
|
|
18686
18896
|
} catch {
|
|
18687
18897
|
failed.push(skillPath);
|
|
@@ -18697,11 +18907,11 @@ var init_ai_skill = __esm({
|
|
|
18697
18907
|
init_paths();
|
|
18698
18908
|
init_version();
|
|
18699
18909
|
BACKEND_SKILL_DIRS2 = {
|
|
18700
|
-
"cc-claw": [
|
|
18701
|
-
claude: [
|
|
18702
|
-
gemini: [
|
|
18703
|
-
codex: [
|
|
18704
|
-
cursor: [
|
|
18910
|
+
"cc-claw": [join22(homedir7(), ".cc-claw", "workspace", "skills")],
|
|
18911
|
+
claude: [join22(homedir7(), ".claude", "skills")],
|
|
18912
|
+
gemini: [join22(homedir7(), ".gemini", "skills")],
|
|
18913
|
+
codex: [join22(homedir7(), ".agents", "skills")],
|
|
18914
|
+
cursor: [join22(homedir7(), ".cursor", "skills"), join22(homedir7(), ".cursor", "skills-cursor")]
|
|
18705
18915
|
};
|
|
18706
18916
|
}
|
|
18707
18917
|
});
|
|
@@ -18711,18 +18921,18 @@ var index_exports = {};
|
|
|
18711
18921
|
__export(index_exports, {
|
|
18712
18922
|
main: () => main
|
|
18713
18923
|
});
|
|
18714
|
-
import { mkdirSync as
|
|
18715
|
-
import { join as
|
|
18924
|
+
import { mkdirSync as mkdirSync9, existsSync as existsSync22, renameSync, statSync as statSync5, readFileSync as readFileSync12 } from "fs";
|
|
18925
|
+
import { join as join23 } from "path";
|
|
18716
18926
|
import dotenv from "dotenv";
|
|
18717
18927
|
function migrateLayout() {
|
|
18718
18928
|
const moves = [
|
|
18719
|
-
[
|
|
18720
|
-
[
|
|
18721
|
-
[
|
|
18722
|
-
[
|
|
18723
|
-
[
|
|
18724
|
-
[
|
|
18725
|
-
[
|
|
18929
|
+
[join23(CC_CLAW_HOME, "cc-claw.db"), join23(DATA_PATH, "cc-claw.db")],
|
|
18930
|
+
[join23(CC_CLAW_HOME, "cc-claw.db-shm"), join23(DATA_PATH, "cc-claw.db-shm")],
|
|
18931
|
+
[join23(CC_CLAW_HOME, "cc-claw.db-wal"), join23(DATA_PATH, "cc-claw.db-wal")],
|
|
18932
|
+
[join23(CC_CLAW_HOME, "cc-claw.log"), join23(LOGS_PATH, "cc-claw.log")],
|
|
18933
|
+
[join23(CC_CLAW_HOME, "cc-claw.log.1"), join23(LOGS_PATH, "cc-claw.log.1")],
|
|
18934
|
+
[join23(CC_CLAW_HOME, "cc-claw.error.log"), join23(LOGS_PATH, "cc-claw.error.log")],
|
|
18935
|
+
[join23(CC_CLAW_HOME, "cc-claw.error.log.1"), join23(LOGS_PATH, "cc-claw.error.log.1")]
|
|
18726
18936
|
];
|
|
18727
18937
|
for (const [from, to] of moves) {
|
|
18728
18938
|
if (existsSync22(from) && !existsSync22(to)) {
|
|
@@ -18736,7 +18946,7 @@ function migrateLayout() {
|
|
|
18736
18946
|
function rotateLogs() {
|
|
18737
18947
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
18738
18948
|
try {
|
|
18739
|
-
const { size } =
|
|
18949
|
+
const { size } = statSync5(file);
|
|
18740
18950
|
if (size > LOG_MAX_BYTES) {
|
|
18741
18951
|
const archivePath = `${file}.1`;
|
|
18742
18952
|
try {
|
|
@@ -18859,11 +19069,11 @@ async function main() {
|
|
|
18859
19069
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
18860
19070
|
try {
|
|
18861
19071
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
18862
|
-
const { writeFileSync:
|
|
18863
|
-
const { join:
|
|
18864
|
-
const skillDir =
|
|
18865
|
-
|
|
18866
|
-
|
|
19072
|
+
const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync14 } = await import("fs");
|
|
19073
|
+
const { join: join27 } = await import("path");
|
|
19074
|
+
const skillDir = join27(SKILLS_PATH, "cc-claw-cli");
|
|
19075
|
+
mkdirSync14(skillDir, { recursive: true });
|
|
19076
|
+
writeFileSync11(join27(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
18867
19077
|
log("[cc-claw] AI skill updated");
|
|
18868
19078
|
} catch {
|
|
18869
19079
|
}
|
|
@@ -18934,7 +19144,7 @@ var init_index = __esm({
|
|
|
18934
19144
|
init_bootstrap2();
|
|
18935
19145
|
init_health3();
|
|
18936
19146
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
18937
|
-
if (!existsSync22(dir))
|
|
19147
|
+
if (!existsSync22(dir)) mkdirSync9(dir, { recursive: true });
|
|
18938
19148
|
}
|
|
18939
19149
|
migrateLayout();
|
|
18940
19150
|
if (existsSync22(ENV_PATH)) {
|
|
@@ -19058,10 +19268,10 @@ __export(service_exports, {
|
|
|
19058
19268
|
serviceStatus: () => serviceStatus,
|
|
19059
19269
|
uninstallService: () => uninstallService
|
|
19060
19270
|
});
|
|
19061
|
-
import { existsSync as existsSync24, mkdirSync as
|
|
19271
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
|
|
19062
19272
|
import { execFileSync as execFileSync2, execSync as execSync7 } from "child_process";
|
|
19063
19273
|
import { homedir as homedir8, platform } from "os";
|
|
19064
|
-
import { join as
|
|
19274
|
+
import { join as join24, dirname as dirname4 } from "path";
|
|
19065
19275
|
function resolveExecutable2(name) {
|
|
19066
19276
|
try {
|
|
19067
19277
|
return execFileSync2("which", [name], { encoding: "utf-8" }).trim();
|
|
@@ -19074,14 +19284,14 @@ function getPathDirs() {
|
|
|
19074
19284
|
const home = homedir8();
|
|
19075
19285
|
const dirs = /* @__PURE__ */ new Set([
|
|
19076
19286
|
nodeBin,
|
|
19077
|
-
|
|
19287
|
+
join24(home, ".local", "bin"),
|
|
19078
19288
|
"/usr/local/bin",
|
|
19079
19289
|
"/usr/bin",
|
|
19080
19290
|
"/bin"
|
|
19081
19291
|
]);
|
|
19082
19292
|
try {
|
|
19083
19293
|
const prefix = execSync7("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
19084
|
-
if (prefix) dirs.add(
|
|
19294
|
+
if (prefix) dirs.add(join24(prefix, "bin"));
|
|
19085
19295
|
} catch {
|
|
19086
19296
|
}
|
|
19087
19297
|
return [...dirs].join(":");
|
|
@@ -19133,15 +19343,15 @@ function generatePlist() {
|
|
|
19133
19343
|
}
|
|
19134
19344
|
function installMacOS() {
|
|
19135
19345
|
const agentsDir = dirname4(PLIST_PATH);
|
|
19136
|
-
if (!existsSync24(agentsDir))
|
|
19137
|
-
if (!existsSync24(LOGS_PATH))
|
|
19346
|
+
if (!existsSync24(agentsDir)) mkdirSync10(agentsDir, { recursive: true });
|
|
19347
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync10(LOGS_PATH, { recursive: true });
|
|
19138
19348
|
if (existsSync24(PLIST_PATH)) {
|
|
19139
19349
|
try {
|
|
19140
19350
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
19141
19351
|
} catch {
|
|
19142
19352
|
}
|
|
19143
19353
|
}
|
|
19144
|
-
|
|
19354
|
+
writeFileSync8(PLIST_PATH, generatePlist());
|
|
19145
19355
|
console.log(` Installed: ${PLIST_PATH}`);
|
|
19146
19356
|
execFileSync2("launchctl", ["load", PLIST_PATH]);
|
|
19147
19357
|
console.log(" Service loaded and starting.");
|
|
@@ -19155,7 +19365,7 @@ function uninstallMacOS() {
|
|
|
19155
19365
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
19156
19366
|
} catch {
|
|
19157
19367
|
}
|
|
19158
|
-
|
|
19368
|
+
unlinkSync6(PLIST_PATH);
|
|
19159
19369
|
console.log(" Service uninstalled.");
|
|
19160
19370
|
}
|
|
19161
19371
|
function formatUptime(seconds) {
|
|
@@ -19221,9 +19431,9 @@ WantedBy=default.target
|
|
|
19221
19431
|
`;
|
|
19222
19432
|
}
|
|
19223
19433
|
function installLinux() {
|
|
19224
|
-
if (!existsSync24(SYSTEMD_DIR))
|
|
19225
|
-
if (!existsSync24(LOGS_PATH))
|
|
19226
|
-
|
|
19434
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync10(SYSTEMD_DIR, { recursive: true });
|
|
19435
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync10(LOGS_PATH, { recursive: true });
|
|
19436
|
+
writeFileSync8(UNIT_PATH, generateUnit());
|
|
19227
19437
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
19228
19438
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
19229
19439
|
execFileSync2("systemctl", ["--user", "enable", "cc-claw"]);
|
|
@@ -19243,7 +19453,7 @@ function uninstallLinux() {
|
|
|
19243
19453
|
execFileSync2("systemctl", ["--user", "disable", "cc-claw"]);
|
|
19244
19454
|
} catch {
|
|
19245
19455
|
}
|
|
19246
|
-
|
|
19456
|
+
unlinkSync6(UNIT_PATH);
|
|
19247
19457
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
19248
19458
|
console.log(" Service uninstalled.");
|
|
19249
19459
|
}
|
|
@@ -19256,7 +19466,7 @@ function statusLinux() {
|
|
|
19256
19466
|
}
|
|
19257
19467
|
}
|
|
19258
19468
|
function installService() {
|
|
19259
|
-
if (!existsSync24(
|
|
19469
|
+
if (!existsSync24(join24(CC_CLAW_HOME, ".env"))) {
|
|
19260
19470
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
19261
19471
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
19262
19472
|
process.exitCode = 1;
|
|
@@ -19285,9 +19495,9 @@ var init_service = __esm({
|
|
|
19285
19495
|
"use strict";
|
|
19286
19496
|
init_paths();
|
|
19287
19497
|
PLIST_LABEL = "com.cc-claw";
|
|
19288
|
-
PLIST_PATH =
|
|
19289
|
-
SYSTEMD_DIR =
|
|
19290
|
-
UNIT_PATH =
|
|
19498
|
+
PLIST_PATH = join24(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
19499
|
+
SYSTEMD_DIR = join24(homedir8(), ".config", "systemd", "user");
|
|
19500
|
+
UNIT_PATH = join24(SYSTEMD_DIR, "cc-claw.service");
|
|
19291
19501
|
}
|
|
19292
19502
|
});
|
|
19293
19503
|
|
|
@@ -19484,7 +19694,7 @@ var status_exports = {};
|
|
|
19484
19694
|
__export(status_exports, {
|
|
19485
19695
|
statusCommand: () => statusCommand
|
|
19486
19696
|
});
|
|
19487
|
-
import { existsSync as existsSync25, statSync as
|
|
19697
|
+
import { existsSync as existsSync25, statSync as statSync6 } from "fs";
|
|
19488
19698
|
async function statusCommand(globalOpts, localOpts) {
|
|
19489
19699
|
try {
|
|
19490
19700
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19524,7 +19734,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
19524
19734
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
19525
19735
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
19526
19736
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
19527
|
-
const dbStat = existsSync25(DB_PATH) ?
|
|
19737
|
+
const dbStat = existsSync25(DB_PATH) ? statSync6(DB_PATH) : null;
|
|
19528
19738
|
let daemonRunning = false;
|
|
19529
19739
|
let daemonInfo = {};
|
|
19530
19740
|
if (localOpts.deep) {
|
|
@@ -19615,12 +19825,12 @@ var doctor_exports = {};
|
|
|
19615
19825
|
__export(doctor_exports, {
|
|
19616
19826
|
doctorCommand: () => doctorCommand
|
|
19617
19827
|
});
|
|
19618
|
-
import { existsSync as existsSync26, statSync as
|
|
19828
|
+
import { existsSync as existsSync26, statSync as statSync7, accessSync, constants } from "fs";
|
|
19619
19829
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
19620
19830
|
async function doctorCommand(globalOpts, localOpts) {
|
|
19621
19831
|
const checks = [];
|
|
19622
19832
|
if (existsSync26(DB_PATH)) {
|
|
19623
|
-
const size =
|
|
19833
|
+
const size = statSync7(DB_PATH).size;
|
|
19624
19834
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
19625
19835
|
try {
|
|
19626
19836
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -19910,8 +20120,8 @@ __export(gemini_exports, {
|
|
|
19910
20120
|
geminiReorder: () => geminiReorder,
|
|
19911
20121
|
geminiRotation: () => geminiRotation
|
|
19912
20122
|
});
|
|
19913
|
-
import { existsSync as existsSync28, mkdirSync as
|
|
19914
|
-
import { join as
|
|
20123
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync11, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
20124
|
+
import { join as join25 } from "path";
|
|
19915
20125
|
import { createInterface as createInterface5 } from "readline";
|
|
19916
20126
|
function requireDb() {
|
|
19917
20127
|
if (!existsSync28(DB_PATH)) {
|
|
@@ -19939,7 +20149,7 @@ async function resolveSlotId(idOrLabel) {
|
|
|
19939
20149
|
function resolveOAuthEmail(configHome) {
|
|
19940
20150
|
if (!configHome) return null;
|
|
19941
20151
|
try {
|
|
19942
|
-
const accountsPath =
|
|
20152
|
+
const accountsPath = join25(configHome, ".gemini", "google_accounts.json");
|
|
19943
20153
|
if (!existsSync28(accountsPath)) return null;
|
|
19944
20154
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
19945
20155
|
return accounts.active || null;
|
|
@@ -20023,14 +20233,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
20023
20233
|
}
|
|
20024
20234
|
async function geminiAddAccount(globalOpts, opts) {
|
|
20025
20235
|
await requireWriteDb();
|
|
20026
|
-
const slotsDir =
|
|
20027
|
-
if (!existsSync28(slotsDir))
|
|
20236
|
+
const slotsDir = join25(CC_CLAW_HOME, "gemini-slots");
|
|
20237
|
+
if (!existsSync28(slotsDir)) mkdirSync11(slotsDir, { recursive: true });
|
|
20028
20238
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
20029
20239
|
const tempId = Date.now();
|
|
20030
|
-
const slotDir =
|
|
20031
|
-
|
|
20032
|
-
|
|
20033
|
-
|
|
20240
|
+
const slotDir = join25(slotsDir, `slot-${tempId}`);
|
|
20241
|
+
mkdirSync11(slotDir, { recursive: true, mode: 448 });
|
|
20242
|
+
mkdirSync11(join25(slotDir, ".gemini"), { recursive: true });
|
|
20243
|
+
writeFileSync9(join25(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
20034
20244
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
20035
20245
|
}, null, 2));
|
|
20036
20246
|
console.log("");
|
|
@@ -20047,7 +20257,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
20047
20257
|
});
|
|
20048
20258
|
} catch {
|
|
20049
20259
|
}
|
|
20050
|
-
const oauthPath =
|
|
20260
|
+
const oauthPath = join25(slotDir, ".gemini", "oauth_creds.json");
|
|
20051
20261
|
if (!existsSync28(oauthPath)) {
|
|
20052
20262
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
20053
20263
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
@@ -20056,7 +20266,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
20056
20266
|
}
|
|
20057
20267
|
let accountEmail = "unknown";
|
|
20058
20268
|
try {
|
|
20059
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
20269
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join25(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
20060
20270
|
accountEmail = accounts.active || accountEmail;
|
|
20061
20271
|
} catch {
|
|
20062
20272
|
}
|
|
@@ -20873,7 +21083,7 @@ __export(db_exports, {
|
|
|
20873
21083
|
dbPath: () => dbPath,
|
|
20874
21084
|
dbStats: () => dbStats
|
|
20875
21085
|
});
|
|
20876
|
-
import { existsSync as existsSync34, statSync as
|
|
21086
|
+
import { existsSync as existsSync34, statSync as statSync8, copyFileSync as copyFileSync2, mkdirSync as mkdirSync12 } from "fs";
|
|
20877
21087
|
import { dirname as dirname5 } from "path";
|
|
20878
21088
|
async function dbStats(globalOpts) {
|
|
20879
21089
|
if (!existsSync34(DB_PATH)) {
|
|
@@ -20882,9 +21092,9 @@ async function dbStats(globalOpts) {
|
|
|
20882
21092
|
}
|
|
20883
21093
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
20884
21094
|
const readDb = openDatabaseReadOnly2();
|
|
20885
|
-
const mainSize =
|
|
21095
|
+
const mainSize = statSync8(DB_PATH).size;
|
|
20886
21096
|
const walPath = DB_PATH + "-wal";
|
|
20887
|
-
const walSize = existsSync34(walPath) ?
|
|
21097
|
+
const walSize = existsSync34(walPath) ? statSync8(walPath).size : 0;
|
|
20888
21098
|
const tableNames = readDb.prepare(
|
|
20889
21099
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
20890
21100
|
).all();
|
|
@@ -20924,11 +21134,11 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
20924
21134
|
}
|
|
20925
21135
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
20926
21136
|
try {
|
|
20927
|
-
|
|
21137
|
+
mkdirSync12(dirname5(dest), { recursive: true });
|
|
20928
21138
|
copyFileSync2(DB_PATH, dest);
|
|
20929
21139
|
const walPath = DB_PATH + "-wal";
|
|
20930
21140
|
if (existsSync34(walPath)) copyFileSync2(walPath, dest + "-wal");
|
|
20931
|
-
output({ path: dest, sizeBytes:
|
|
21141
|
+
output({ path: dest, sizeBytes: statSync8(dest).size }, (d) => {
|
|
20932
21142
|
const b = d;
|
|
20933
21143
|
return `
|
|
20934
21144
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -22755,10 +22965,10 @@ var init_evolve = __esm({
|
|
|
22755
22965
|
|
|
22756
22966
|
// src/setup.ts
|
|
22757
22967
|
var setup_exports = {};
|
|
22758
|
-
import { existsSync as existsSync46, writeFileSync as
|
|
22968
|
+
import { existsSync as existsSync46, writeFileSync as writeFileSync10, readFileSync as readFileSync20, copyFileSync as copyFileSync3, mkdirSync as mkdirSync13, statSync as statSync9 } from "fs";
|
|
22759
22969
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22760
22970
|
import { createInterface as createInterface7 } from "readline";
|
|
22761
|
-
import { join as
|
|
22971
|
+
import { join as join26 } from "path";
|
|
22762
22972
|
function divider2() {
|
|
22763
22973
|
console.log(dim("\u2500".repeat(55)));
|
|
22764
22974
|
}
|
|
@@ -22833,7 +23043,7 @@ async function setup() {
|
|
|
22833
23043
|
}
|
|
22834
23044
|
console.log("");
|
|
22835
23045
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
22836
|
-
if (!existsSync46(dir))
|
|
23046
|
+
if (!existsSync46(dir)) mkdirSync13(dir, { recursive: true });
|
|
22837
23047
|
}
|
|
22838
23048
|
const env = {};
|
|
22839
23049
|
const envSource = existsSync46(ENV_PATH) ? ENV_PATH : existsSync46(".env") ? ".env" : null;
|
|
@@ -22846,9 +23056,9 @@ async function setup() {
|
|
|
22846
23056
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
22847
23057
|
}
|
|
22848
23058
|
}
|
|
22849
|
-
const cwdDb =
|
|
23059
|
+
const cwdDb = join26(process.cwd(), "cc-claw.db");
|
|
22850
23060
|
if (existsSync46(cwdDb) && !existsSync46(DB_PATH)) {
|
|
22851
|
-
const { size } =
|
|
23061
|
+
const { size } = statSync9(cwdDb);
|
|
22852
23062
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
22853
23063
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
22854
23064
|
if (migrate) {
|
|
@@ -23064,7 +23274,7 @@ async function setup() {
|
|
|
23064
23274
|
envLines.push("", "# Video Analysis", `GEMINI_API_KEY=${env.GEMINI_API_KEY}`);
|
|
23065
23275
|
}
|
|
23066
23276
|
const envContent = envLines.join("\n") + "\n";
|
|
23067
|
-
|
|
23277
|
+
writeFileSync10(ENV_PATH, envContent, { mode: 384 });
|
|
23068
23278
|
console.log(green(` Config saved to ${ENV_PATH} (permissions: owner-only)`));
|
|
23069
23279
|
header(6, TOTAL_STEPS, "Run on Startup (Daemon)");
|
|
23070
23280
|
console.log(" CC-Claw can run automatically in the background, starting");
|
package/package.json
CHANGED