cc-claw 0.22.5 → 0.22.7
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 +555 -455
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var VERSION;
|
|
|
33
33
|
var init_version = __esm({
|
|
34
34
|
"src/version.ts"() {
|
|
35
35
|
"use strict";
|
|
36
|
-
VERSION = true ? "0.22.
|
|
36
|
+
VERSION = true ? "0.22.7" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -4317,10 +4317,80 @@ var init_resolve_executable = __esm({
|
|
|
4317
4317
|
});
|
|
4318
4318
|
|
|
4319
4319
|
// src/backends/claude.ts
|
|
4320
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
4321
|
-
import { spawnSync as spawnSync2 } from "child_process";
|
|
4320
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
4321
|
+
import { execFileSync, spawnSync as spawnSync2 } from "child_process";
|
|
4322
4322
|
import { join as join4 } from "path";
|
|
4323
|
-
|
|
4323
|
+
function readOAuthCredentials(credsPath) {
|
|
4324
|
+
try {
|
|
4325
|
+
if (!existsSync3(credsPath)) return null;
|
|
4326
|
+
const creds = JSON.parse(readFileSync2(credsPath, "utf-8"));
|
|
4327
|
+
return creds?.claudeAiOauth ?? null;
|
|
4328
|
+
} catch {
|
|
4329
|
+
return null;
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
function refreshOAuthToken(credsPath, refreshToken) {
|
|
4333
|
+
const lastAttempt = lastRefreshAttempt.get(credsPath) ?? 0;
|
|
4334
|
+
if (Date.now() - lastAttempt < REFRESH_COOLDOWN_MS) {
|
|
4335
|
+
return null;
|
|
4336
|
+
}
|
|
4337
|
+
lastRefreshAttempt.set(credsPath, Date.now());
|
|
4338
|
+
try {
|
|
4339
|
+
const payload = JSON.stringify({
|
|
4340
|
+
grant_type: "refresh_token",
|
|
4341
|
+
refresh_token: refreshToken,
|
|
4342
|
+
client_id: OAUTH_CLIENT_ID
|
|
4343
|
+
});
|
|
4344
|
+
const result = execFileSync("curl", [
|
|
4345
|
+
"-s",
|
|
4346
|
+
"-X",
|
|
4347
|
+
"POST",
|
|
4348
|
+
OAUTH_TOKEN_ENDPOINT,
|
|
4349
|
+
"-H",
|
|
4350
|
+
"Content-Type: application/json",
|
|
4351
|
+
"-d",
|
|
4352
|
+
payload,
|
|
4353
|
+
"--max-time",
|
|
4354
|
+
"10"
|
|
4355
|
+
], { encoding: "utf-8", timeout: 15e3 });
|
|
4356
|
+
const response = JSON.parse(result);
|
|
4357
|
+
if (!response.access_token) {
|
|
4358
|
+
warn(`[claude-oauth] Refresh failed: ${JSON.stringify(response.error ?? response)}`);
|
|
4359
|
+
return null;
|
|
4360
|
+
}
|
|
4361
|
+
const creds = JSON.parse(readFileSync2(credsPath, "utf-8"));
|
|
4362
|
+
creds.claudeAiOauth.accessToken = response.access_token;
|
|
4363
|
+
if (response.refresh_token) {
|
|
4364
|
+
creds.claudeAiOauth.refreshToken = response.refresh_token;
|
|
4365
|
+
}
|
|
4366
|
+
if (response.expires_in) {
|
|
4367
|
+
creds.claudeAiOauth.expiresAt = Date.now() + response.expires_in * 1e3;
|
|
4368
|
+
}
|
|
4369
|
+
writeFileSync(credsPath, JSON.stringify(creds, null, 2), "utf-8");
|
|
4370
|
+
log(`[claude-oauth] Token refreshed for ${credsPath} (expires in ${Math.round((response.expires_in ?? 0) / 3600)}h)`);
|
|
4371
|
+
return response.access_token;
|
|
4372
|
+
} catch (err) {
|
|
4373
|
+
warn(`[claude-oauth] Refresh failed: ${err instanceof Error ? err.message : err}`);
|
|
4374
|
+
return null;
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
4377
|
+
function getValidOAuthToken(configHome) {
|
|
4378
|
+
const credsPath = join4(configHome, ".claude", ".credentials.json");
|
|
4379
|
+
const oauth = readOAuthCredentials(credsPath);
|
|
4380
|
+
if (!oauth) return null;
|
|
4381
|
+
const { accessToken, refreshToken, expiresAt } = oauth;
|
|
4382
|
+
if (!accessToken) return null;
|
|
4383
|
+
if (refreshToken && expiresAt) {
|
|
4384
|
+
const remaining = expiresAt - Date.now();
|
|
4385
|
+
if (remaining < REFRESH_THRESHOLD_MS) {
|
|
4386
|
+
log(`[claude-oauth] Token ${remaining > 0 ? `expires in ${Math.round(remaining / 6e4)}m` : "expired"} \u2014 refreshing`);
|
|
4387
|
+
const fresh = refreshOAuthToken(credsPath, refreshToken);
|
|
4388
|
+
if (fresh) return fresh;
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
return accessToken;
|
|
4392
|
+
}
|
|
4393
|
+
var OAUTH_TOKEN_ENDPOINT, OAUTH_CLIENT_ID, REFRESH_THRESHOLD_MS, REFRESH_COOLDOWN_MS, lastRefreshAttempt, ADAPTIVE_MODELS, ClaudeAdapter;
|
|
4324
4394
|
var init_claude = __esm({
|
|
4325
4395
|
"src/backends/claude.ts"() {
|
|
4326
4396
|
"use strict";
|
|
@@ -4329,6 +4399,11 @@ var init_claude = __esm({
|
|
|
4329
4399
|
init_resolve_executable();
|
|
4330
4400
|
init_paths();
|
|
4331
4401
|
init_log();
|
|
4402
|
+
OAUTH_TOKEN_ENDPOINT = "https://console.anthropic.com/v1/oauth/token";
|
|
4403
|
+
OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
4404
|
+
REFRESH_THRESHOLD_MS = 60 * 60 * 1e3;
|
|
4405
|
+
REFRESH_COOLDOWN_MS = 5 * 60 * 1e3;
|
|
4406
|
+
lastRefreshAttempt = /* @__PURE__ */ new Map();
|
|
4332
4407
|
ADAPTIVE_MODELS = /* @__PURE__ */ new Set(["claude-opus-4-6", "claude-sonnet-4-6", "claude-opus-4-6[1m]", "claude-sonnet-4-6[1m]"]);
|
|
4333
4408
|
ClaudeAdapter = class {
|
|
4334
4409
|
id = "claude";
|
|
@@ -4443,13 +4518,8 @@ var init_claude = __esm({
|
|
|
4443
4518
|
} else if (slot.slotType === "oauth" && slot.configHome) {
|
|
4444
4519
|
env.HOME = slot.configHome;
|
|
4445
4520
|
delete env.ANTHROPIC_API_KEY;
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
const creds = JSON.parse(readFileSync2(credsPath, "utf-8"));
|
|
4449
|
-
const token = creds?.claudeAiOauth?.accessToken;
|
|
4450
|
-
if (token) env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
4451
|
-
} catch {
|
|
4452
|
-
}
|
|
4521
|
+
const token = getValidOAuthToken(slot.configHome);
|
|
4522
|
+
if (token) env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
4453
4523
|
}
|
|
4454
4524
|
return env;
|
|
4455
4525
|
}
|
|
@@ -7624,7 +7694,7 @@ __export(init_exports, {
|
|
|
7624
7694
|
});
|
|
7625
7695
|
import {
|
|
7626
7696
|
existsSync as existsSync8,
|
|
7627
|
-
writeFileSync,
|
|
7697
|
+
writeFileSync as writeFileSync2,
|
|
7628
7698
|
mkdirSync as mkdirSync3,
|
|
7629
7699
|
readFileSync as readFileSync4,
|
|
7630
7700
|
copyFileSync as copyFileSync2,
|
|
@@ -7665,7 +7735,7 @@ function bootstrapWorkspaceFiles() {
|
|
|
7665
7735
|
log("[bootstrap] Removed legacy workspace/GEMINI.md (replaced by identity/CC-CLAW.md)");
|
|
7666
7736
|
}
|
|
7667
7737
|
if (!existsSync8(SOUL_PATH)) {
|
|
7668
|
-
|
|
7738
|
+
writeFileSync2(SOUL_PATH, DEFAULT_SOUL, "utf-8");
|
|
7669
7739
|
log("[bootstrap] Created default SOUL.md");
|
|
7670
7740
|
}
|
|
7671
7741
|
if (!existsSync8(USER_PATH)) {
|
|
@@ -7675,7 +7745,7 @@ function bootstrapWorkspaceFiles() {
|
|
|
7675
7745
|
} catch {
|
|
7676
7746
|
}
|
|
7677
7747
|
const userContent = DEFAULT_USER.replace("- **Timezone**: UTC", `- **Timezone**: ${tz}`);
|
|
7678
|
-
|
|
7748
|
+
writeFileSync2(USER_PATH, userContent, "utf-8");
|
|
7679
7749
|
log(`[bootstrap] Created default USER.md (timezone: ${tz})`);
|
|
7680
7750
|
}
|
|
7681
7751
|
if (!existsSync8(CONTEXT_DIR)) {
|
|
@@ -7688,7 +7758,7 @@ function bootstrapWorkspaceFiles() {
|
|
|
7688
7758
|
}
|
|
7689
7759
|
const expertisePath = join8(CONTEXT_DIR, "cc-claw-expertise.md");
|
|
7690
7760
|
if (!existsSync8(expertisePath)) {
|
|
7691
|
-
|
|
7761
|
+
writeFileSync2(expertisePath, DEFAULT_EXPERTISE, "utf-8");
|
|
7692
7762
|
log("[bootstrap] Created default context/cc-claw-expertise.md");
|
|
7693
7763
|
}
|
|
7694
7764
|
const IGNORE_CONTENT = [
|
|
@@ -7704,12 +7774,12 @@ function bootstrapWorkspaceFiles() {
|
|
|
7704
7774
|
].join("\n");
|
|
7705
7775
|
const gitignorePath = join8(WORKSPACE_PATH, ".gitignore");
|
|
7706
7776
|
if (!existsSync8(gitignorePath)) {
|
|
7707
|
-
|
|
7777
|
+
writeFileSync2(gitignorePath, IGNORE_CONTENT, "utf-8");
|
|
7708
7778
|
log("[bootstrap] Created .gitignore (workspace allowlist)");
|
|
7709
7779
|
}
|
|
7710
7780
|
const geminiignorePath = join8(WORKSPACE_PATH, ".geminiignore");
|
|
7711
7781
|
if (!existsSync8(geminiignorePath)) {
|
|
7712
|
-
|
|
7782
|
+
writeFileSync2(geminiignorePath, IGNORE_CONTENT, "utf-8");
|
|
7713
7783
|
log("[bootstrap] Created .geminiignore (workspace allowlist)");
|
|
7714
7784
|
}
|
|
7715
7785
|
syncNativeCliFiles();
|
|
@@ -7737,11 +7807,11 @@ function syncNativeCliFiles() {
|
|
|
7737
7807
|
const geminiContent = buildGeminiTemplate(soul, user);
|
|
7738
7808
|
const codexContent = buildCodexTemplate(soul, user);
|
|
7739
7809
|
const cursorContent = buildCursorTemplate(soul, user);
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7810
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW-claude.md"), claudeContent, "utf-8");
|
|
7811
|
+
writeFileSync2(join8(WORKSPACE_PATH, "GEMINI.md"), geminiContent, "utf-8");
|
|
7812
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW-codex.md"), codexContent, "utf-8");
|
|
7813
|
+
writeFileSync2(join8(WORKSPACE_PATH, "AGENTS.md"), codexContent, "utf-8");
|
|
7814
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW-cursor.md"), cursorContent, "utf-8");
|
|
7745
7815
|
const fallbackContent = [
|
|
7746
7816
|
"# CC-Claw System Instructions",
|
|
7747
7817
|
"",
|
|
@@ -7759,11 +7829,11 @@ function syncNativeCliFiles() {
|
|
|
7759
7829
|
user,
|
|
7760
7830
|
""
|
|
7761
7831
|
].join("\n");
|
|
7762
|
-
|
|
7832
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW.md"), fallbackContent, "utf-8");
|
|
7763
7833
|
const claudeTaskContent = buildClaudeTaskTemplate();
|
|
7764
7834
|
const codexTaskContent = buildCodexTaskTemplate();
|
|
7765
|
-
|
|
7766
|
-
|
|
7835
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW-claude-task.md"), claudeTaskContent, "utf-8");
|
|
7836
|
+
writeFileSync2(join8(IDENTITY_PATH, "CC-CLAW-codex-task.md"), codexTaskContent, "utf-8");
|
|
7767
7837
|
log("[bootstrap] Synced identity files: CC-CLAW-claude.md, GEMINI.md, CC-CLAW-codex.md, CC-CLAW-cursor.md, CC-CLAW.md (fallback), CC-CLAW-claude-task.md, CC-CLAW-codex-task.md");
|
|
7768
7838
|
}
|
|
7769
7839
|
var SOUL_PATH, USER_PATH, CONTEXT_DIR, LEGACY_SOUL_PATH, LEGACY_USER_PATH, LEGACY_CLAUDE_MD, LEGACY_GEMINI_MD;
|
|
@@ -8643,7 +8713,7 @@ var init_quota = __esm({
|
|
|
8643
8713
|
|
|
8644
8714
|
// src/dashboard/middleware.ts
|
|
8645
8715
|
import { randomBytes } from "crypto";
|
|
8646
|
-
import { writeFileSync as
|
|
8716
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
8647
8717
|
function getDashboardToken() {
|
|
8648
8718
|
return DASHBOARD_TOKEN;
|
|
8649
8719
|
}
|
|
@@ -8651,7 +8721,7 @@ function persistToken() {
|
|
|
8651
8721
|
try {
|
|
8652
8722
|
mkdirSync4(DATA_PATH, { recursive: true });
|
|
8653
8723
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
8654
|
-
|
|
8724
|
+
writeFileSync3(tokenPath, DASHBOARD_TOKEN, { mode: 384 });
|
|
8655
8725
|
} catch (err) {
|
|
8656
8726
|
log(`[api] Warning: could not write api-token file: ${errorMessage(err)}`);
|
|
8657
8727
|
}
|
|
@@ -9642,9 +9712,9 @@ function resolveSkillForTask(skillName) {
|
|
|
9642
9712
|
for (const candidate of SKILL_FILE_CANDIDATES3) {
|
|
9643
9713
|
const skillPath = join10(SKILLS_PATH, skillName, candidate);
|
|
9644
9714
|
try {
|
|
9645
|
-
const { readFileSync:
|
|
9646
|
-
if (!
|
|
9647
|
-
const raw =
|
|
9715
|
+
const { readFileSync: readFileSync33, existsSync: existsSync62 } = __require("fs");
|
|
9716
|
+
if (!existsSync62(skillPath)) continue;
|
|
9717
|
+
const raw = readFileSync33(skillPath, "utf-8");
|
|
9648
9718
|
const fm = parseFrontmatter(raw, skillName, "cc-claw");
|
|
9649
9719
|
if (fm.status !== "approved") {
|
|
9650
9720
|
log(`[skills] Skill "${skillName}" has status "${fm.status}" \u2014 only approved skills can be used as task worker identity`);
|
|
@@ -9948,8 +10018,10 @@ var init_cost = __esm({
|
|
|
9948
10018
|
|
|
9949
10019
|
// src/mcps/propagate.ts
|
|
9950
10020
|
import { execFile } from "child_process";
|
|
10021
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync11 } from "fs";
|
|
9951
10022
|
import { promisify } from "util";
|
|
9952
10023
|
import { homedir as homedir4 } from "os";
|
|
10024
|
+
import { join as join12 } from "path";
|
|
9953
10025
|
async function discoverExistingMcps(runner) {
|
|
9954
10026
|
try {
|
|
9955
10027
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -10021,10 +10093,33 @@ function defToConfig(def) {
|
|
|
10021
10093
|
return null;
|
|
10022
10094
|
}
|
|
10023
10095
|
}
|
|
10096
|
+
function injectMcpToCursorConfig(config2) {
|
|
10097
|
+
const configPath = join12(homedir4(), ".cursor", "mcp.json");
|
|
10098
|
+
let existing = {};
|
|
10099
|
+
try {
|
|
10100
|
+
if (existsSync11(configPath)) {
|
|
10101
|
+
existing = JSON.parse(readFileSync7(configPath, "utf-8"));
|
|
10102
|
+
}
|
|
10103
|
+
} catch {
|
|
10104
|
+
}
|
|
10105
|
+
const servers = existing.mcpServers ?? {};
|
|
10106
|
+
if (servers[config2.name]) return false;
|
|
10107
|
+
const entry = {};
|
|
10108
|
+
if (config2.command) entry.command = config2.command;
|
|
10109
|
+
if (config2.args?.length) entry.args = config2.args;
|
|
10110
|
+
if (config2.url) entry.url = config2.url;
|
|
10111
|
+
if (config2.env) entry.env = config2.env;
|
|
10112
|
+
servers[config2.name] = entry;
|
|
10113
|
+
existing.mcpServers = servers;
|
|
10114
|
+
writeFileSync4(configPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
10115
|
+
log(`[mcp] Wrote ${config2.name} to ${configPath}`);
|
|
10116
|
+
return true;
|
|
10117
|
+
}
|
|
10024
10118
|
async function injectMcps(runner, mcpNames, db3, scope) {
|
|
10025
10119
|
const added = [];
|
|
10026
10120
|
const exe = runner.getExecutablePath();
|
|
10027
10121
|
const runnerId = runner.id;
|
|
10122
|
+
const isCursor = runnerId === "cursor";
|
|
10028
10123
|
const results = await Promise.allSettled(
|
|
10029
10124
|
mcpNames.map(async (name) => {
|
|
10030
10125
|
const def = getMcpServer(db3, name);
|
|
@@ -10032,6 +10127,11 @@ async function injectMcps(runner, mcpNames, db3, scope) {
|
|
|
10032
10127
|
try {
|
|
10033
10128
|
const config2 = defToConfig(def);
|
|
10034
10129
|
if (!config2) return null;
|
|
10130
|
+
if (isCursor) {
|
|
10131
|
+
const wrote = injectMcpToCursorConfig(config2);
|
|
10132
|
+
if (wrote) addPropagation(db3, name, runnerId, scope);
|
|
10133
|
+
return wrote ? name : null;
|
|
10134
|
+
}
|
|
10035
10135
|
const addCmd = runner.getMcpAddCommand(config2);
|
|
10036
10136
|
const args = addCmd.slice(1);
|
|
10037
10137
|
await execFileAsync(exe, args, { encoding: "utf-8" });
|
|
@@ -10077,14 +10177,14 @@ var init_propagate = __esm({
|
|
|
10077
10177
|
});
|
|
10078
10178
|
|
|
10079
10179
|
// src/agents/mcp-config.ts
|
|
10080
|
-
import { mkdirSync as mkdirSync5, writeFileSync as
|
|
10081
|
-
import { join as
|
|
10180
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, existsSync as existsSync12, readdirSync as readdirSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
10181
|
+
import { join as join13, dirname as dirname2 } from "path";
|
|
10082
10182
|
import { fileURLToPath } from "url";
|
|
10083
10183
|
function generateOrchestratorMcpConfig(opts) {
|
|
10084
10184
|
const port = opts.port ?? process.env.DASHBOARD_PORT ?? "3141";
|
|
10085
|
-
const distPath =
|
|
10086
|
-
const tsxPath =
|
|
10087
|
-
const useTs = !
|
|
10185
|
+
const distPath = join13(__dirname, "agents", "mcp-server.js");
|
|
10186
|
+
const tsxPath = join13(__dirname, "..", "src", "agents", "mcp-server.ts");
|
|
10187
|
+
const useTs = !existsSync12(distPath);
|
|
10088
10188
|
return {
|
|
10089
10189
|
name: opts.agentId === "main" ? "cc-claw" : `cc-claw-${opts.agentId.slice(0, 8)}`,
|
|
10090
10190
|
transport: "stdio",
|
|
@@ -10109,20 +10209,20 @@ function writeMcpConfigFile(config2) {
|
|
|
10109
10209
|
}
|
|
10110
10210
|
};
|
|
10111
10211
|
const safeName = config2.name.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
10112
|
-
const configPath =
|
|
10212
|
+
const configPath = join13(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
10113
10213
|
const configJson = JSON.stringify(jsonConfig, null, 2);
|
|
10114
10214
|
if (configJson !== lastWrittenConfig.get(configPath)) {
|
|
10115
|
-
if (!
|
|
10215
|
+
if (!existsSync12(MCP_CONFIG_DIR)) {
|
|
10116
10216
|
mkdirSync5(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
|
|
10117
10217
|
}
|
|
10118
|
-
|
|
10218
|
+
writeFileSync5(configPath, configJson, { mode: 384 });
|
|
10119
10219
|
lastWrittenConfig.set(configPath, configJson);
|
|
10120
10220
|
}
|
|
10121
10221
|
return configPath;
|
|
10122
10222
|
}
|
|
10123
10223
|
function deleteMcpConfigFile(mcpName) {
|
|
10124
10224
|
const safeName = mcpName.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
10125
|
-
const configPath =
|
|
10225
|
+
const configPath = join13(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
10126
10226
|
lastWrittenConfig.delete(configPath);
|
|
10127
10227
|
try {
|
|
10128
10228
|
unlinkSync3(configPath);
|
|
@@ -10131,12 +10231,12 @@ function deleteMcpConfigFile(mcpName) {
|
|
|
10131
10231
|
}
|
|
10132
10232
|
function cleanupOrphanedMcpConfigs() {
|
|
10133
10233
|
try {
|
|
10134
|
-
if (!
|
|
10234
|
+
if (!existsSync12(MCP_CONFIG_DIR)) return;
|
|
10135
10235
|
const files = readdirSync4(MCP_CONFIG_DIR);
|
|
10136
10236
|
for (const file of files) {
|
|
10137
10237
|
if (file.startsWith("mcp-cc-claw-") && file.endsWith(".json")) {
|
|
10138
10238
|
try {
|
|
10139
|
-
unlinkSync3(
|
|
10239
|
+
unlinkSync3(join13(MCP_CONFIG_DIR, file));
|
|
10140
10240
|
} catch {
|
|
10141
10241
|
}
|
|
10142
10242
|
}
|
|
@@ -10151,7 +10251,7 @@ var init_mcp_config = __esm({
|
|
|
10151
10251
|
init_paths();
|
|
10152
10252
|
__filename = fileURLToPath(import.meta.url);
|
|
10153
10253
|
__dirname = dirname2(__filename);
|
|
10154
|
-
MCP_CONFIG_DIR =
|
|
10254
|
+
MCP_CONFIG_DIR = join13(CC_CLAW_HOME, "mcp-configs");
|
|
10155
10255
|
lastWrittenConfig = /* @__PURE__ */ new Map();
|
|
10156
10256
|
}
|
|
10157
10257
|
});
|
|
@@ -10162,8 +10262,8 @@ __export(loader_exports, {
|
|
|
10162
10262
|
getTemplate: () => getTemplate,
|
|
10163
10263
|
listTemplates: () => listTemplates
|
|
10164
10264
|
});
|
|
10165
|
-
import { readdirSync as readdirSync5, readFileSync as
|
|
10166
|
-
import { join as
|
|
10265
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync8 } from "fs";
|
|
10266
|
+
import { join as join14 } from "path";
|
|
10167
10267
|
function parseFrontmatter2(content) {
|
|
10168
10268
|
const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/m);
|
|
10169
10269
|
if (!match || match.index !== 0) return { meta: {}, body: content.trim() };
|
|
@@ -10201,9 +10301,9 @@ function scanTemplates() {
|
|
|
10201
10301
|
return;
|
|
10202
10302
|
}
|
|
10203
10303
|
for (const file of files) {
|
|
10204
|
-
const filePath =
|
|
10304
|
+
const filePath = join14(AGENTS_PATH, file);
|
|
10205
10305
|
try {
|
|
10206
|
-
const raw =
|
|
10306
|
+
const raw = readFileSync8(filePath, "utf-8");
|
|
10207
10307
|
const { meta, body } = parseFrontmatter2(raw);
|
|
10208
10308
|
const name = meta.name ?? file.replace(/\.md$/, "");
|
|
10209
10309
|
const template = {
|
|
@@ -10250,8 +10350,8 @@ var init_loader2 = __esm({
|
|
|
10250
10350
|
});
|
|
10251
10351
|
|
|
10252
10352
|
// src/agents/agent-log.ts
|
|
10253
|
-
import { writeFileSync as
|
|
10254
|
-
import { join as
|
|
10353
|
+
import { writeFileSync as writeFileSync6, readdirSync as readdirSync6, statSync as statSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
10354
|
+
import { join as join15 } from "path";
|
|
10255
10355
|
function truncate(text, maxBytes) {
|
|
10256
10356
|
if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
|
|
10257
10357
|
let lo = 0, hi = text.length;
|
|
@@ -10266,7 +10366,7 @@ function truncate(text, maxBytes) {
|
|
|
10266
10366
|
[...truncated ${droppedBytes} bytes...]`;
|
|
10267
10367
|
}
|
|
10268
10368
|
function writeAgentLog(data) {
|
|
10269
|
-
const logPath =
|
|
10369
|
+
const logPath = join15(AGENTS_PATH, `${data.agentId}.log`);
|
|
10270
10370
|
const exitDisplay = data.exitCodeForced ? `${data.exitCode} (forced \u2014 no output from original exit code 0)` : String(data.exitCode ?? "null");
|
|
10271
10371
|
const stderrContent = truncate(data.stderr || "(empty)", MAX_STDERR_BYTES);
|
|
10272
10372
|
const stdoutContent = truncate(data.rawStdoutLines.join("\n") || "(empty)", MAX_STDOUT_BYTES);
|
|
@@ -10291,7 +10391,7 @@ function writeAgentLog(data) {
|
|
|
10291
10391
|
];
|
|
10292
10392
|
try {
|
|
10293
10393
|
mkdirSync6(AGENTS_PATH, { recursive: true });
|
|
10294
|
-
|
|
10394
|
+
writeFileSync6(logPath, lines.join("\n"), "utf-8");
|
|
10295
10395
|
} catch (err) {
|
|
10296
10396
|
log(`[agent-log] Failed to write log for ${data.agentId}: ${err}`);
|
|
10297
10397
|
}
|
|
@@ -10301,7 +10401,7 @@ function pruneAgentLogs() {
|
|
|
10301
10401
|
try {
|
|
10302
10402
|
mkdirSync6(AGENTS_PATH, { recursive: true });
|
|
10303
10403
|
const files = readdirSync6(AGENTS_PATH).filter((f) => f.endsWith(".log")).map((f) => {
|
|
10304
|
-
const fullPath =
|
|
10404
|
+
const fullPath = join15(AGENTS_PATH, f);
|
|
10305
10405
|
const stat4 = statSync3(fullPath);
|
|
10306
10406
|
return { path: fullPath, mtime: stat4.mtimeMs, size: stat4.size };
|
|
10307
10407
|
});
|
|
@@ -10360,7 +10460,7 @@ __export(orchestrator_exports, {
|
|
|
10360
10460
|
shutdownOrchestrator: () => shutdownOrchestrator,
|
|
10361
10461
|
spawnSubAgent: () => spawnSubAgent
|
|
10362
10462
|
});
|
|
10363
|
-
import { existsSync as
|
|
10463
|
+
import { existsSync as existsSync13 } from "fs";
|
|
10364
10464
|
async function withRunnerLock(runnerId, fn) {
|
|
10365
10465
|
const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
|
|
10366
10466
|
const next = prev.then(fn, () => fn());
|
|
@@ -10478,7 +10578,7 @@ async function spawnSubAgent(chatId, opts) {
|
|
|
10478
10578
|
async function startAgent(agentId, chatId, opts) {
|
|
10479
10579
|
const db3 = getDb();
|
|
10480
10580
|
const runner = getRunner(opts.runner);
|
|
10481
|
-
if (opts.cwd && !
|
|
10581
|
+
if (opts.cwd && !existsSync13(opts.cwd)) {
|
|
10482
10582
|
const msg = `Directory not found: ${opts.cwd}`;
|
|
10483
10583
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
10484
10584
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -10500,7 +10600,7 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
10500
10600
|
return;
|
|
10501
10601
|
}
|
|
10502
10602
|
const exePath = runner.getExecutablePath();
|
|
10503
|
-
if (exePath.startsWith("/") && !
|
|
10603
|
+
if (exePath.startsWith("/") && !existsSync13(exePath)) {
|
|
10504
10604
|
const msg = `Executable not found: ${exePath}`;
|
|
10505
10605
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
10506
10606
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -10774,10 +10874,10 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
10774
10874
|
function diagnoseSpawnError(err, exePath, cwd) {
|
|
10775
10875
|
const nodeErr = err;
|
|
10776
10876
|
if (nodeErr.code === "ENOENT") {
|
|
10777
|
-
if (cwd && !
|
|
10877
|
+
if (cwd && !existsSync13(cwd)) {
|
|
10778
10878
|
return `Directory not found: ${cwd}`;
|
|
10779
10879
|
}
|
|
10780
|
-
if (exePath.startsWith("/") && !
|
|
10880
|
+
if (exePath.startsWith("/") && !existsSync13(exePath)) {
|
|
10781
10881
|
return `Executable not found: ${exePath}`;
|
|
10782
10882
|
}
|
|
10783
10883
|
return `ENOENT spawning ${exePath} (cwd: ${cwd ?? "inherited"}) \u2014 check that both the binary and directory exist`;
|
|
@@ -11170,7 +11270,7 @@ var init_registry2 = __esm({
|
|
|
11170
11270
|
});
|
|
11171
11271
|
|
|
11172
11272
|
// src/dashboard/routes/orchestrator.ts
|
|
11173
|
-
import { existsSync as
|
|
11273
|
+
import { existsSync as existsSync14 } from "fs";
|
|
11174
11274
|
var handleSpawn, handleCancel, handleCancelAll, handleCreateTask, handleUpdateTask, handleSendMessage, handleReadInbox, handleSetState, handleGetState, handleListState, handleBroadcast, handleListRunners, handleListMcps, handleListTemplates, handleCheckAgent;
|
|
11175
11275
|
var init_orchestrator2 = __esm({
|
|
11176
11276
|
"src/dashboard/routes/orchestrator.ts"() {
|
|
@@ -11186,7 +11286,7 @@ var init_orchestrator2 = __esm({
|
|
|
11186
11286
|
handleSpawn = async (req, res) => {
|
|
11187
11287
|
try {
|
|
11188
11288
|
const body = JSON.parse(await readBody(req));
|
|
11189
|
-
if (body.cwd && !
|
|
11289
|
+
if (body.cwd && !existsSync14(body.cwd)) {
|
|
11190
11290
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
11191
11291
|
}
|
|
11192
11292
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -12444,8 +12544,8 @@ __export(analyze_exports, {
|
|
|
12444
12544
|
});
|
|
12445
12545
|
import { spawn as spawn4 } from "child_process";
|
|
12446
12546
|
import { createInterface as createInterface3 } from "readline";
|
|
12447
|
-
import { readFileSync as
|
|
12448
|
-
import { join as
|
|
12547
|
+
import { readFileSync as readFileSync9, existsSync as existsSync15, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
12548
|
+
import { join as join16 } from "path";
|
|
12449
12549
|
import { homedir as homedir5 } from "os";
|
|
12450
12550
|
function applySignalDecay(confidence, createdAt) {
|
|
12451
12551
|
const ageMs = Date.now() - (/* @__PURE__ */ new Date(createdAt + (createdAt.endsWith("Z") ? "" : "Z"))).getTime();
|
|
@@ -12454,19 +12554,19 @@ function applySignalDecay(confidence, createdAt) {
|
|
|
12454
12554
|
return decayed >= SIGNAL_DECAY_MIN_CONFIDENCE ? Math.round(decayed * 100) / 100 : 0;
|
|
12455
12555
|
}
|
|
12456
12556
|
function discoverReflectionTargets() {
|
|
12457
|
-
const ccClawHome =
|
|
12557
|
+
const ccClawHome = join16(homedir5(), ".cc-claw");
|
|
12458
12558
|
const targets = [];
|
|
12459
12559
|
try {
|
|
12460
|
-
const skillsDir =
|
|
12461
|
-
if (
|
|
12560
|
+
const skillsDir = join16(ccClawHome, "workspace", "skills");
|
|
12561
|
+
if (existsSync15(skillsDir)) {
|
|
12462
12562
|
for (const entry of readdirSync7(skillsDir)) {
|
|
12463
|
-
const entryPath =
|
|
12563
|
+
const entryPath = join16(skillsDir, entry);
|
|
12464
12564
|
if (!statSync4(entryPath).isDirectory()) continue;
|
|
12465
|
-
const skillFile =
|
|
12466
|
-
if (!
|
|
12565
|
+
const skillFile = join16(entryPath, "SKILL.md");
|
|
12566
|
+
if (!existsSync15(skillFile)) continue;
|
|
12467
12567
|
let desc = "skill";
|
|
12468
12568
|
try {
|
|
12469
|
-
const content =
|
|
12569
|
+
const content = readFileSync9(skillFile, "utf-8");
|
|
12470
12570
|
const descMatch = content.match(/description:\s*["']?([^"'\n]+)/);
|
|
12471
12571
|
if (descMatch) desc = descMatch[1].trim().slice(0, 80);
|
|
12472
12572
|
} catch {
|
|
@@ -12477,8 +12577,8 @@ function discoverReflectionTargets() {
|
|
|
12477
12577
|
} catch {
|
|
12478
12578
|
}
|
|
12479
12579
|
try {
|
|
12480
|
-
const contextDir =
|
|
12481
|
-
if (
|
|
12580
|
+
const contextDir = join16(ccClawHome, "workspace", "context");
|
|
12581
|
+
if (existsSync15(contextDir)) {
|
|
12482
12582
|
for (const entry of readdirSync7(contextDir)) {
|
|
12483
12583
|
if (!entry.endsWith(".md")) continue;
|
|
12484
12584
|
const name = entry.replace(/\.md$/, "");
|
|
@@ -12675,7 +12775,7 @@ function resolveReflectionAdapter(chatId) {
|
|
|
12675
12775
|
}
|
|
12676
12776
|
function readIdentityFile(filename) {
|
|
12677
12777
|
try {
|
|
12678
|
-
return
|
|
12778
|
+
return readFileSync9(join16(IDENTITY_PATH, filename), "utf-8");
|
|
12679
12779
|
} catch {
|
|
12680
12780
|
return "";
|
|
12681
12781
|
}
|
|
@@ -12819,7 +12919,7 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
12819
12919
|
const availableTargets = discoverReflectionTargets();
|
|
12820
12920
|
const SKILL_CONTENT_CAP = 15e3;
|
|
12821
12921
|
const skillContents = [];
|
|
12822
|
-
const ccClawHome =
|
|
12922
|
+
const ccClawHome = join16(homedir5(), ".cc-claw");
|
|
12823
12923
|
const signalCorpus = signals.map((s) => s.trigger).join(" ").toLowerCase();
|
|
12824
12924
|
const convCorpus = (conversations ?? "").toLowerCase();
|
|
12825
12925
|
const searchCorpus = signalCorpus + " " + convCorpus;
|
|
@@ -12832,9 +12932,9 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
12832
12932
|
const isRelevant = searchCorpus.includes(skillNameNorm) || searchCorpus.includes(skillName.toLowerCase()) || descNorm.split(/\s+/).some((word) => word.length > 4 && searchCorpus.includes(word));
|
|
12833
12933
|
if (!isRelevant) continue;
|
|
12834
12934
|
try {
|
|
12835
|
-
const fullPath =
|
|
12836
|
-
if (
|
|
12837
|
-
const content =
|
|
12935
|
+
const fullPath = join16(ccClawHome, target.path);
|
|
12936
|
+
if (existsSync15(fullPath)) {
|
|
12937
|
+
const content = readFileSync9(fullPath, "utf-8");
|
|
12838
12938
|
if (totalSkillChars + content.length > SKILL_CONTENT_CAP) break;
|
|
12839
12939
|
skillContents.push({ path: target.path, content });
|
|
12840
12940
|
totalSkillChars += content.length;
|
|
@@ -13214,8 +13314,8 @@ __export(apply_exports, {
|
|
|
13214
13314
|
isTargetAllowed: () => isTargetAllowed,
|
|
13215
13315
|
rollbackInsight: () => rollbackInsight
|
|
13216
13316
|
});
|
|
13217
|
-
import { readFileSync as
|
|
13218
|
-
import { join as
|
|
13317
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync7, existsSync as existsSync16, mkdirSync as mkdirSync7, readdirSync as readdirSync8, unlinkSync as unlinkSync5 } from "fs";
|
|
13318
|
+
import { join as join17, dirname as dirname3 } from "path";
|
|
13219
13319
|
function isTargetAllowed(relativePath) {
|
|
13220
13320
|
if (relativePath.includes("..")) return false;
|
|
13221
13321
|
if (!relativePath.endsWith(".md")) return false;
|
|
@@ -13269,7 +13369,7 @@ function pruneBackups(absolutePath) {
|
|
|
13269
13369
|
const dir = dirname3(absolutePath);
|
|
13270
13370
|
const baseName = absolutePath.split("/").pop() ?? "";
|
|
13271
13371
|
try {
|
|
13272
|
-
const backups = readdirSync8(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) =>
|
|
13372
|
+
const backups = readdirSync8(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join17(dir, f));
|
|
13273
13373
|
while (backups.length > MAX_BACKUPS_PER_FILE) {
|
|
13274
13374
|
const oldest = backups.shift();
|
|
13275
13375
|
try {
|
|
@@ -13295,10 +13395,10 @@ async function applyInsight(insightId) {
|
|
|
13295
13395
|
if (!isTargetAllowed(insight.targetFile)) {
|
|
13296
13396
|
return { success: false, message: `Target file "${insight.targetFile}" is not in the allowed list` };
|
|
13297
13397
|
}
|
|
13298
|
-
const absolutePath =
|
|
13398
|
+
const absolutePath = join17(CC_CLAW_HOME, insight.targetFile);
|
|
13299
13399
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
13300
|
-
if (
|
|
13301
|
-
const currentContent =
|
|
13400
|
+
if (existsSync16(absolutePath)) {
|
|
13401
|
+
const currentContent = readFileSync10(absolutePath, "utf-8");
|
|
13302
13402
|
const lineCount = currentContent.split("\n").length;
|
|
13303
13403
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
13304
13404
|
return {
|
|
@@ -13319,8 +13419,8 @@ async function applyInsight(insightId) {
|
|
|
13319
13419
|
};
|
|
13320
13420
|
}
|
|
13321
13421
|
let original = "";
|
|
13322
|
-
if (
|
|
13323
|
-
original =
|
|
13422
|
+
if (existsSync16(absolutePath)) {
|
|
13423
|
+
original = readFileSync10(absolutePath, "utf-8");
|
|
13324
13424
|
} else if (insight.proposedAction !== "create") {
|
|
13325
13425
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
13326
13426
|
}
|
|
@@ -13328,11 +13428,11 @@ async function applyInsight(insightId) {
|
|
|
13328
13428
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
13329
13429
|
try {
|
|
13330
13430
|
const parentDir = dirname3(absolutePath);
|
|
13331
|
-
if (!
|
|
13431
|
+
if (!existsSync16(parentDir)) {
|
|
13332
13432
|
mkdirSync7(parentDir, { recursive: true });
|
|
13333
13433
|
}
|
|
13334
13434
|
if (original) {
|
|
13335
|
-
|
|
13435
|
+
writeFileSync7(backupPath, original, "utf-8");
|
|
13336
13436
|
pruneBackups(absolutePath);
|
|
13337
13437
|
}
|
|
13338
13438
|
let newContent;
|
|
@@ -13360,7 +13460,7 @@ async function applyInsight(insightId) {
|
|
|
13360
13460
|
} else {
|
|
13361
13461
|
newContent = applyDiff(original, insight.proposedDiff, insight.proposedAction);
|
|
13362
13462
|
}
|
|
13363
|
-
|
|
13463
|
+
writeFileSync7(absolutePath, newContent, "utf-8");
|
|
13364
13464
|
const rollbackData = JSON.stringify({ original, backupPath, appliedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
13365
13465
|
updateInsightRollback(db3, insightId, rollbackData);
|
|
13366
13466
|
updateInsightStatus(db3, insightId, "applied");
|
|
@@ -13388,7 +13488,7 @@ async function applyInsight(insightId) {
|
|
|
13388
13488
|
warn(`[reflection/apply] Failed to apply insight #${insightId}: ${msg}`);
|
|
13389
13489
|
try {
|
|
13390
13490
|
if (original) {
|
|
13391
|
-
|
|
13491
|
+
writeFileSync7(absolutePath, original, "utf-8");
|
|
13392
13492
|
}
|
|
13393
13493
|
} catch {
|
|
13394
13494
|
}
|
|
@@ -13416,9 +13516,9 @@ async function rollbackInsight(insightId) {
|
|
|
13416
13516
|
} catch {
|
|
13417
13517
|
return { success: false, message: `Insight #${insightId} has malformed rollback data` };
|
|
13418
13518
|
}
|
|
13419
|
-
const absolutePath =
|
|
13519
|
+
const absolutePath = join17(CC_CLAW_HOME, insight.targetFile);
|
|
13420
13520
|
try {
|
|
13421
|
-
|
|
13521
|
+
writeFileSync7(absolutePath, rollback.original, "utf-8");
|
|
13422
13522
|
updateInsightStatus(db3, insightId, "rolled_back");
|
|
13423
13523
|
syncNativeCliFiles();
|
|
13424
13524
|
const chatId = insight.chatId ?? "global";
|
|
@@ -13449,8 +13549,8 @@ function calculateDrift(chatId) {
|
|
|
13449
13549
|
if (!row || !row.baselineSoulMd && !row.baselineUserMd) {
|
|
13450
13550
|
return null;
|
|
13451
13551
|
}
|
|
13452
|
-
const soulPath =
|
|
13453
|
-
const userPath =
|
|
13552
|
+
const soulPath = join17(CC_CLAW_HOME, "identity/SOUL.md");
|
|
13553
|
+
const userPath = join17(CC_CLAW_HOME, "identity/USER.md");
|
|
13454
13554
|
const soulDrift = computeLineDrift(row.baselineSoulMd, soulPath);
|
|
13455
13555
|
const userDrift = computeLineDrift(row.baselineUserMd, userPath);
|
|
13456
13556
|
return { soulDrift, userDrift };
|
|
@@ -13459,8 +13559,8 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
13459
13559
|
if (!baseline) return 0;
|
|
13460
13560
|
let current = "";
|
|
13461
13561
|
try {
|
|
13462
|
-
if (
|
|
13463
|
-
current =
|
|
13562
|
+
if (existsSync16(absolutePath)) {
|
|
13563
|
+
current = readFileSync10(absolutePath, "utf-8");
|
|
13464
13564
|
}
|
|
13465
13565
|
} catch {
|
|
13466
13566
|
return 1;
|
|
@@ -13559,12 +13659,12 @@ var init_evolve = __esm({
|
|
|
13559
13659
|
const body = JSON.parse(await readBody(req));
|
|
13560
13660
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
13561
13661
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
13562
|
-
const { join:
|
|
13662
|
+
const { join: join41 } = await import("path");
|
|
13563
13663
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
13564
13664
|
const chatId = resolveChatId(body);
|
|
13565
13665
|
if (!chatId) return jsonResponse(res, { error: "No chatId provided and ALLOWED_CHAT_ID is not set" }, 400);
|
|
13566
|
-
const soulPath =
|
|
13567
|
-
const userPath =
|
|
13666
|
+
const soulPath = join41(home, "identity/SOUL.md");
|
|
13667
|
+
const userPath = join41(home, "identity/USER.md");
|
|
13568
13668
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
13569
13669
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
13570
13670
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -13617,9 +13717,9 @@ var init_evolve = __esm({
|
|
|
13617
13717
|
});
|
|
13618
13718
|
|
|
13619
13719
|
// src/dashboard/routes/files.ts
|
|
13620
|
-
import { createWriteStream, existsSync as
|
|
13720
|
+
import { createWriteStream, existsSync as existsSync17 } from "fs";
|
|
13621
13721
|
import { readdir as readdir2, stat, unlink, mkdir } from "fs/promises";
|
|
13622
|
-
import { join as
|
|
13722
|
+
import { join as join18, extname } from "path";
|
|
13623
13723
|
function getUploadHtml(token, host) {
|
|
13624
13724
|
return `<!DOCTYPE html>
|
|
13625
13725
|
<html lang="en">
|
|
@@ -13800,7 +13900,7 @@ async function handleFileList(req, res) {
|
|
|
13800
13900
|
const files = [];
|
|
13801
13901
|
for (const name of entries) {
|
|
13802
13902
|
try {
|
|
13803
|
-
const s = await stat(
|
|
13903
|
+
const s = await stat(join18(INCOMING_PATH, name));
|
|
13804
13904
|
if (!s.isFile()) continue;
|
|
13805
13905
|
files.push({
|
|
13806
13906
|
name,
|
|
@@ -13824,8 +13924,8 @@ async function handleFileServe(req, res, url) {
|
|
|
13824
13924
|
res.end("Invalid filename");
|
|
13825
13925
|
return;
|
|
13826
13926
|
}
|
|
13827
|
-
const filePath =
|
|
13828
|
-
if (!
|
|
13927
|
+
const filePath = join18(INCOMING_PATH, filename);
|
|
13928
|
+
if (!existsSync17(filePath)) {
|
|
13829
13929
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
13830
13930
|
res.end("File not found");
|
|
13831
13931
|
return;
|
|
@@ -13900,7 +14000,7 @@ function parseMultipartUpload(req, boundary) {
|
|
|
13900
14000
|
const originalName = nameMatch[1].replace(/[^\w.-]/g, "_");
|
|
13901
14001
|
const ext = extname(originalName) || ".bin";
|
|
13902
14002
|
const filename = `upload-${Date.now()}${ext}`;
|
|
13903
|
-
const filePath =
|
|
14003
|
+
const filePath = join18(INCOMING_PATH, filename);
|
|
13904
14004
|
cleanupPath = filePath;
|
|
13905
14005
|
const fileStart = headerEnd + 4;
|
|
13906
14006
|
const closingBoundary = Buffer.from(`\r
|
|
@@ -13936,7 +14036,7 @@ var init_files = __esm({
|
|
|
13936
14036
|
init_paths();
|
|
13937
14037
|
init_middleware();
|
|
13938
14038
|
init_log();
|
|
13939
|
-
INCOMING_PATH =
|
|
14039
|
+
INCOMING_PATH = join18(MEDIA_PATH, "incoming");
|
|
13940
14040
|
MAX_UPLOAD_BYTES = 200 * 1024 * 1024;
|
|
13941
14041
|
BLOCKED_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
13942
14042
|
".exe",
|
|
@@ -16017,11 +16117,11 @@ var init_telegram_throttle = __esm({
|
|
|
16017
16117
|
});
|
|
16018
16118
|
|
|
16019
16119
|
// src/health/checks.ts
|
|
16020
|
-
import { existsSync as
|
|
16021
|
-
import { execFileSync, execSync as execSync3 } from "child_process";
|
|
16120
|
+
import { existsSync as existsSync18, statSync as statSync5, readFileSync as readFileSync11 } from "fs";
|
|
16121
|
+
import { execFileSync as execFileSync2, execSync as execSync3 } from "child_process";
|
|
16022
16122
|
function getRecentErrors() {
|
|
16023
|
-
if (!
|
|
16024
|
-
const logContent =
|
|
16123
|
+
if (!existsSync18(ERROR_LOG_PATH)) return null;
|
|
16124
|
+
const logContent = readFileSync11(ERROR_LOG_PATH, "utf-8");
|
|
16025
16125
|
const allLines = logContent.split("\n").filter(Boolean).slice(-500);
|
|
16026
16126
|
const last24h = Date.now() - 864e5;
|
|
16027
16127
|
const lines = allLines.filter((line) => {
|
|
@@ -16042,7 +16142,7 @@ function getRecentErrors() {
|
|
|
16042
16142
|
}
|
|
16043
16143
|
function checkDatabase() {
|
|
16044
16144
|
const checks = [];
|
|
16045
|
-
if (
|
|
16145
|
+
if (existsSync18(DB_PATH)) {
|
|
16046
16146
|
const size = statSync5(DB_PATH).size;
|
|
16047
16147
|
checks.push({ name: "Database", status: "ok", message: `${(size / 1024).toFixed(0)}KB` });
|
|
16048
16148
|
} else {
|
|
@@ -16098,7 +16198,7 @@ function checkBackendCLIs() {
|
|
|
16098
16198
|
let installed = 0;
|
|
16099
16199
|
for (const [label2, binary] of Object.entries(CLI_BINARIES)) {
|
|
16100
16200
|
try {
|
|
16101
|
-
const path =
|
|
16201
|
+
const path = execFileSync2("which", [binary], { encoding: "utf-8", timeout: 5e3 }).trim();
|
|
16102
16202
|
if (path) {
|
|
16103
16203
|
checks.push({ name: `${label2} CLI`, status: "ok", message: path });
|
|
16104
16204
|
installed++;
|
|
@@ -16250,8 +16350,8 @@ __export(heartbeat_exports, {
|
|
|
16250
16350
|
stopHeartbeatForChat: () => stopHeartbeatForChat,
|
|
16251
16351
|
updateHeartbeatConfig: () => updateHeartbeatConfig
|
|
16252
16352
|
});
|
|
16253
|
-
import { readFileSync as
|
|
16254
|
-
import { join as
|
|
16353
|
+
import { readFileSync as readFileSync12, existsSync as existsSync19 } from "fs";
|
|
16354
|
+
import { join as join19 } from "path";
|
|
16255
16355
|
function findHeartbeatJob() {
|
|
16256
16356
|
try {
|
|
16257
16357
|
const { getDb: getDb2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
@@ -16382,9 +16482,9 @@ ${healthText}`);
|
|
|
16382
16482
|
sections.push(`[Active Watches \u2014 execute these checks using your tools]
|
|
16383
16483
|
${watchLines.join("\n")}`);
|
|
16384
16484
|
}
|
|
16385
|
-
if (
|
|
16485
|
+
if (existsSync19(HEARTBEAT_MD_PATH)) {
|
|
16386
16486
|
try {
|
|
16387
|
-
const custom =
|
|
16487
|
+
const custom = readFileSync12(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
16388
16488
|
if (custom) {
|
|
16389
16489
|
sections.push(`[Custom checks from HEARTBEAT.md]
|
|
16390
16490
|
${custom}`);
|
|
@@ -16444,7 +16544,7 @@ var init_heartbeat2 = __esm({
|
|
|
16444
16544
|
init_store5();
|
|
16445
16545
|
init_checks();
|
|
16446
16546
|
init_log();
|
|
16447
|
-
HEARTBEAT_MD_PATH =
|
|
16547
|
+
HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
16448
16548
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
16449
16549
|
HEARTBEAT_JOB_TYPE = "heartbeat";
|
|
16450
16550
|
DEFAULT_INTERVAL_MS = 30 * 60 * 1e3;
|
|
@@ -16453,8 +16553,8 @@ var init_heartbeat2 = __esm({
|
|
|
16453
16553
|
});
|
|
16454
16554
|
|
|
16455
16555
|
// src/bootstrap/profile.ts
|
|
16456
|
-
import { readFileSync as
|
|
16457
|
-
import { join as
|
|
16556
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync20 } from "fs";
|
|
16557
|
+
import { join as join20 } from "path";
|
|
16458
16558
|
function hasActiveProfile(chatId) {
|
|
16459
16559
|
return activeProfiles.has(chatId);
|
|
16460
16560
|
}
|
|
@@ -16557,7 +16657,7 @@ async function finalizeProfile(chatId, state, channel) {
|
|
|
16557
16657
|
"<!-- Add any additional preferences below this line -->",
|
|
16558
16658
|
""
|
|
16559
16659
|
].join("\n");
|
|
16560
|
-
|
|
16660
|
+
writeFileSync8(USER_PATH2, content, "utf-8");
|
|
16561
16661
|
activeProfiles.delete(chatId);
|
|
16562
16662
|
log(`[profile] User profile saved for chat ${chatId}`);
|
|
16563
16663
|
await channel.sendText(
|
|
@@ -16583,14 +16683,14 @@ function extractUserUpdates(text) {
|
|
|
16583
16683
|
return { cleanText, updates };
|
|
16584
16684
|
}
|
|
16585
16685
|
function appendToUserProfile(key, value) {
|
|
16586
|
-
if (!
|
|
16587
|
-
const content =
|
|
16686
|
+
if (!existsSync20(USER_PATH2)) return;
|
|
16687
|
+
const content = readFileSync13(USER_PATH2, "utf-8");
|
|
16588
16688
|
const line = `- **${key}**: ${value}`;
|
|
16589
16689
|
if (content.includes(line)) return;
|
|
16590
16690
|
const updated = content.trimEnd() + `
|
|
16591
16691
|
${line}
|
|
16592
16692
|
`;
|
|
16593
|
-
|
|
16693
|
+
writeFileSync8(USER_PATH2, updated, "utf-8");
|
|
16594
16694
|
log(`[profile] Appended preference: ${key}=${value}`);
|
|
16595
16695
|
}
|
|
16596
16696
|
var USER_PATH2, activeProfiles;
|
|
@@ -16599,7 +16699,7 @@ var init_profile = __esm({
|
|
|
16599
16699
|
"use strict";
|
|
16600
16700
|
init_paths();
|
|
16601
16701
|
init_log();
|
|
16602
|
-
USER_PATH2 =
|
|
16702
|
+
USER_PATH2 = join20(IDENTITY_PATH, "USER.md");
|
|
16603
16703
|
activeProfiles = /* @__PURE__ */ new Map();
|
|
16604
16704
|
}
|
|
16605
16705
|
});
|
|
@@ -18090,8 +18190,8 @@ __export(session_log_exports2, {
|
|
|
18090
18190
|
startSessionLogCleanupTimer: () => startSessionLogCleanupTimer,
|
|
18091
18191
|
tailSessionLog: () => tailSessionLog
|
|
18092
18192
|
});
|
|
18093
|
-
import { existsSync as
|
|
18094
|
-
import { join as
|
|
18193
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync8, appendFileSync, readdirSync as readdirSync9, unlinkSync as unlinkSync6, statSync as statSync6, createReadStream } from "fs";
|
|
18194
|
+
import { join as join21, basename } from "path";
|
|
18095
18195
|
import { createInterface as createInterface6 } from "readline";
|
|
18096
18196
|
function getRetentionDays() {
|
|
18097
18197
|
const env = process.env.SESSION_LOG_RETENTION_DAYS;
|
|
@@ -18103,13 +18203,13 @@ function getRetentionDays() {
|
|
|
18103
18203
|
}
|
|
18104
18204
|
function cleanupSessionLogs(retentionDays) {
|
|
18105
18205
|
const days = retentionDays ?? getRetentionDays();
|
|
18106
|
-
if (!
|
|
18206
|
+
if (!existsSync21(SESSION_LOGS_PATH)) return 0;
|
|
18107
18207
|
const cutoff = Date.now() - days * 24 * 60 * 60 * 1e3;
|
|
18108
18208
|
let cleaned = 0;
|
|
18109
18209
|
try {
|
|
18110
18210
|
for (const file of readdirSync9(SESSION_LOGS_PATH)) {
|
|
18111
18211
|
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
18112
|
-
const filePath =
|
|
18212
|
+
const filePath = join21(SESSION_LOGS_PATH, file);
|
|
18113
18213
|
try {
|
|
18114
18214
|
const { mtimeMs } = statSync6(filePath);
|
|
18115
18215
|
if (mtimeMs < cutoff) {
|
|
@@ -18135,11 +18235,11 @@ function startSessionLogCleanupTimer() {
|
|
|
18135
18235
|
return timer;
|
|
18136
18236
|
}
|
|
18137
18237
|
function listSessionLogs() {
|
|
18138
|
-
if (!
|
|
18238
|
+
if (!existsSync21(SESSION_LOGS_PATH)) return [];
|
|
18139
18239
|
const logs = [];
|
|
18140
18240
|
for (const file of readdirSync9(SESSION_LOGS_PATH)) {
|
|
18141
18241
|
if (!file.startsWith("session-") || !file.endsWith(".log")) continue;
|
|
18142
|
-
const filePath =
|
|
18242
|
+
const filePath = join21(SESSION_LOGS_PATH, file);
|
|
18143
18243
|
try {
|
|
18144
18244
|
const stat4 = statSync6(filePath);
|
|
18145
18245
|
const match = file.match(/^session-(.+?)-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})\.log$/);
|
|
@@ -18158,7 +18258,7 @@ function listSessionLogs() {
|
|
|
18158
18258
|
return logs;
|
|
18159
18259
|
}
|
|
18160
18260
|
async function* tailSessionLog(filePath, lines = 50) {
|
|
18161
|
-
if (!
|
|
18261
|
+
if (!existsSync21(filePath)) {
|
|
18162
18262
|
yield `File not found: ${filePath}`;
|
|
18163
18263
|
return;
|
|
18164
18264
|
}
|
|
@@ -18186,12 +18286,12 @@ var init_session_log2 = __esm({
|
|
|
18186
18286
|
constructor(chatId, backend2, model2) {
|
|
18187
18287
|
this.backend = backend2;
|
|
18188
18288
|
this.model = model2;
|
|
18189
|
-
if (!
|
|
18289
|
+
if (!existsSync21(SESSION_LOGS_PATH)) {
|
|
18190
18290
|
mkdirSync8(SESSION_LOGS_PATH, { recursive: true });
|
|
18191
18291
|
}
|
|
18192
18292
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
18193
18293
|
const sanitizedChatId = chatId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
18194
|
-
this.filePath =
|
|
18294
|
+
this.filePath = join21(SESSION_LOGS_PATH, `session-${sanitizedChatId}-${ts2}.log`);
|
|
18195
18295
|
const header2 = [
|
|
18196
18296
|
"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550",
|
|
18197
18297
|
`CC-Claw Agent Session \u2014 ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
@@ -18596,16 +18696,16 @@ var init_gate = __esm({
|
|
|
18596
18696
|
|
|
18597
18697
|
// src/voice/stt.ts
|
|
18598
18698
|
import crypto from "crypto";
|
|
18599
|
-
import { execFile as execFile2, execFileSync as
|
|
18699
|
+
import { execFile as execFile2, execFileSync as execFileSync3 } from "child_process";
|
|
18600
18700
|
import { readFile as readFile3, unlink as unlink2, mkdir as mkdir2, writeFile } from "fs/promises";
|
|
18601
|
-
import { existsSync as
|
|
18602
|
-
import { join as
|
|
18701
|
+
import { existsSync as existsSync22 } from "fs";
|
|
18702
|
+
import { join as join22 } from "path";
|
|
18603
18703
|
import { promisify as promisify2 } from "util";
|
|
18604
18704
|
function ensureFfmpeg() {
|
|
18605
18705
|
if (ffmpegAvailable === true) return;
|
|
18606
18706
|
if (ffmpegAvailable === false) throw new Error("ffmpeg is required for voice replies. Install it: brew install ffmpeg (macOS) or apt install ffmpeg (Linux)");
|
|
18607
18707
|
try {
|
|
18608
|
-
|
|
18708
|
+
execFileSync3("ffmpeg", ["-version"], { stdio: "ignore" });
|
|
18609
18709
|
ffmpegAvailable = true;
|
|
18610
18710
|
} catch {
|
|
18611
18711
|
ffmpegAvailable = false;
|
|
@@ -18672,11 +18772,11 @@ function setSttModel(chatId, model2) {
|
|
|
18672
18772
|
function isWhisperCliAvailable() {
|
|
18673
18773
|
if (whisperCliAvailableCache !== null) return whisperCliAvailableCache;
|
|
18674
18774
|
try {
|
|
18675
|
-
|
|
18775
|
+
execFileSync3("whisper-cli", ["--help"], { stdio: "ignore" });
|
|
18676
18776
|
whisperCliAvailableCache = true;
|
|
18677
18777
|
} catch {
|
|
18678
18778
|
try {
|
|
18679
|
-
|
|
18779
|
+
execFileSync3("whisper", ["--help"], { stdio: "ignore" });
|
|
18680
18780
|
whisperCliAvailableCache = true;
|
|
18681
18781
|
} catch {
|
|
18682
18782
|
whisperCliAvailableCache = false;
|
|
@@ -18686,22 +18786,22 @@ function isWhisperCliAvailable() {
|
|
|
18686
18786
|
}
|
|
18687
18787
|
function getWhisperBin() {
|
|
18688
18788
|
try {
|
|
18689
|
-
|
|
18789
|
+
execFileSync3("whisper-cli", ["--help"], { stdio: "ignore" });
|
|
18690
18790
|
return "whisper-cli";
|
|
18691
18791
|
} catch {
|
|
18692
18792
|
}
|
|
18693
18793
|
try {
|
|
18694
|
-
|
|
18794
|
+
execFileSync3("whisper", ["--help"], { stdio: "ignore" });
|
|
18695
18795
|
return "whisper";
|
|
18696
18796
|
} catch {
|
|
18697
18797
|
}
|
|
18698
18798
|
return null;
|
|
18699
18799
|
}
|
|
18700
18800
|
function whisperModelPath(model2) {
|
|
18701
|
-
return
|
|
18801
|
+
return join22(WHISPER_MODELS_PATH, `ggml-${model2}.bin`);
|
|
18702
18802
|
}
|
|
18703
18803
|
function isWhisperModelDownloaded(model2) {
|
|
18704
|
-
return
|
|
18804
|
+
return existsSync22(whisperModelPath(model2));
|
|
18705
18805
|
}
|
|
18706
18806
|
async function downloadWhisperModel(model2, onProgress) {
|
|
18707
18807
|
await mkdir2(WHISPER_MODELS_PATH, { recursive: true });
|
|
@@ -18733,7 +18833,7 @@ async function transcribeWithLocalWhisper(audioBuffer, model2, onProgress) {
|
|
|
18733
18833
|
const result = await execFileAsync2(bin, ["-m", modelFile, "-f", tmpWav, "-nt", "--output-txt", "-of", `/tmp/cc-claw-stt-${id}`]);
|
|
18734
18834
|
const txtFile = `/tmp/cc-claw-stt-${id}.txt`;
|
|
18735
18835
|
let transcript = "";
|
|
18736
|
-
if (
|
|
18836
|
+
if (existsSync22(txtFile)) {
|
|
18737
18837
|
transcript = (await readFile3(txtFile, "utf-8")).trim();
|
|
18738
18838
|
unlink2(txtFile).catch(() => {
|
|
18739
18839
|
});
|
|
@@ -18924,9 +19024,9 @@ var init_stt = __esm({
|
|
|
18924
19024
|
});
|
|
18925
19025
|
|
|
18926
19026
|
// src/media/image-gen.ts
|
|
18927
|
-
import { mkdirSync as mkdirSync9, existsSync as
|
|
19027
|
+
import { mkdirSync as mkdirSync9, existsSync as existsSync23, unlink as unlink3, readdir as readdir3, stat as stat2 } from "fs";
|
|
18928
19028
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
18929
|
-
import { join as
|
|
19029
|
+
import { join as join23 } from "path";
|
|
18930
19030
|
async function generateImage(prompt) {
|
|
18931
19031
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
18932
19032
|
if (!apiKey) {
|
|
@@ -18973,12 +19073,12 @@ async function generateImage(prompt) {
|
|
|
18973
19073
|
if (!imageData) {
|
|
18974
19074
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
18975
19075
|
}
|
|
18976
|
-
if (!
|
|
19076
|
+
if (!existsSync23(IMAGE_OUTPUT_DIR)) {
|
|
18977
19077
|
mkdirSync9(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
18978
19078
|
}
|
|
18979
19079
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
18980
19080
|
const filename = `img_${Date.now()}.${ext}`;
|
|
18981
|
-
const filePath =
|
|
19081
|
+
const filePath = join23(IMAGE_OUTPUT_DIR, filename);
|
|
18982
19082
|
const buffer = Buffer.from(imageData, "base64");
|
|
18983
19083
|
await writeFile2(filePath, buffer);
|
|
18984
19084
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
@@ -18996,7 +19096,7 @@ function cleanupGeneratedImage(filePath) {
|
|
|
18996
19096
|
function pruneImageCache() {
|
|
18997
19097
|
readdir3(IMAGE_OUTPUT_DIR, (err, files) => {
|
|
18998
19098
|
if (err || !files) return;
|
|
18999
|
-
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) =>
|
|
19099
|
+
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join23(IMAGE_OUTPUT_DIR, f));
|
|
19000
19100
|
if (imageFiles.length === 0) return;
|
|
19001
19101
|
const now = Date.now();
|
|
19002
19102
|
let statsPending = imageFiles.length;
|
|
@@ -19028,8 +19128,8 @@ var init_image_gen = __esm({
|
|
|
19028
19128
|
MAX_GENERATED_IMAGES = 20;
|
|
19029
19129
|
IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
19030
19130
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
19031
|
-
IMAGE_OUTPUT_DIR =
|
|
19032
|
-
process.env.CC_CLAW_HOME ??
|
|
19131
|
+
IMAGE_OUTPUT_DIR = join23(
|
|
19132
|
+
process.env.CC_CLAW_HOME ?? join23(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
19033
19133
|
"data",
|
|
19034
19134
|
"images"
|
|
19035
19135
|
);
|
|
@@ -19467,7 +19567,7 @@ var init_video = __esm({
|
|
|
19467
19567
|
});
|
|
19468
19568
|
|
|
19469
19569
|
// src/router/media.ts
|
|
19470
|
-
import { join as
|
|
19570
|
+
import { join as join24 } from "path";
|
|
19471
19571
|
import { mkdir as mkdir3, writeFile as writeFile3, readdir as readdir4, stat as stat3, unlink as unlink4 } from "fs/promises";
|
|
19472
19572
|
function getMediaRetentionMs() {
|
|
19473
19573
|
const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
|
|
@@ -19476,7 +19576,7 @@ function getMediaRetentionMs() {
|
|
|
19476
19576
|
async function saveMedia(buffer, prefix, ext) {
|
|
19477
19577
|
await mkdir3(MEDIA_INCOMING_PATH, { recursive: true });
|
|
19478
19578
|
const filename = `${prefix}-${Date.now()}.${ext}`;
|
|
19479
|
-
const fullPath =
|
|
19579
|
+
const fullPath = join24(MEDIA_INCOMING_PATH, filename);
|
|
19480
19580
|
await writeFile3(fullPath, buffer);
|
|
19481
19581
|
return fullPath;
|
|
19482
19582
|
}
|
|
@@ -19490,7 +19590,7 @@ async function cleanupOldMedia() {
|
|
|
19490
19590
|
let removed = 0;
|
|
19491
19591
|
for (const file of files) {
|
|
19492
19592
|
try {
|
|
19493
|
-
const filePath =
|
|
19593
|
+
const filePath = join24(MEDIA_INCOMING_PATH, file);
|
|
19494
19594
|
const s = await stat3(filePath);
|
|
19495
19595
|
if (now - s.mtimeMs > retentionMs) {
|
|
19496
19596
|
await unlink4(filePath);
|
|
@@ -19766,7 +19866,7 @@ var init_media = __esm({
|
|
|
19766
19866
|
init_helpers();
|
|
19767
19867
|
init_response();
|
|
19768
19868
|
init_live_status();
|
|
19769
|
-
MEDIA_INCOMING_PATH =
|
|
19869
|
+
MEDIA_INCOMING_PATH = join24(MEDIA_PATH, "incoming");
|
|
19770
19870
|
}
|
|
19771
19871
|
});
|
|
19772
19872
|
|
|
@@ -20080,8 +20180,8 @@ __export(install_exports, {
|
|
|
20080
20180
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
20081
20181
|
});
|
|
20082
20182
|
import { mkdir as mkdir4, readdir as readdir5, readFile as readFile5, cp } from "fs/promises";
|
|
20083
|
-
import { existsSync as
|
|
20084
|
-
import { join as
|
|
20183
|
+
import { existsSync as existsSync24 } from "fs";
|
|
20184
|
+
import { join as join25, basename as basename2 } from "path";
|
|
20085
20185
|
import { execSync as execSync4 } from "child_process";
|
|
20086
20186
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
20087
20187
|
let repoUrl;
|
|
@@ -20092,36 +20192,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
20092
20192
|
}
|
|
20093
20193
|
repoUrl = parsed.cloneUrl;
|
|
20094
20194
|
subPath = parsed.subPath;
|
|
20095
|
-
const tmpDir =
|
|
20195
|
+
const tmpDir = join25("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
20096
20196
|
try {
|
|
20097
20197
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
20098
20198
|
execSync4(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
20099
20199
|
stdio: "pipe",
|
|
20100
20200
|
timeout: 3e4
|
|
20101
20201
|
});
|
|
20102
|
-
if (!
|
|
20202
|
+
if (!existsSync24(join25(tmpDir, ".git"))) {
|
|
20103
20203
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
20104
20204
|
}
|
|
20105
|
-
const searchRoot = subPath ?
|
|
20205
|
+
const searchRoot = subPath ? join25(tmpDir, subPath) : tmpDir;
|
|
20106
20206
|
const skillDir = await findSkillDir(searchRoot);
|
|
20107
20207
|
if (!skillDir) {
|
|
20108
20208
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
20109
20209
|
}
|
|
20110
20210
|
const skillFolderName = basename2(skillDir);
|
|
20111
|
-
const destDir =
|
|
20112
|
-
if (
|
|
20211
|
+
const destDir = join25(SKILLS_PATH, skillFolderName);
|
|
20212
|
+
if (existsSync24(destDir)) {
|
|
20113
20213
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
20114
20214
|
}
|
|
20115
20215
|
await mkdir4(destDir, { recursive: true });
|
|
20116
20216
|
await cp(skillDir, destDir, { recursive: true });
|
|
20117
20217
|
let skillName = skillFolderName;
|
|
20118
20218
|
try {
|
|
20119
|
-
const content = await readFile5(
|
|
20219
|
+
const content = await readFile5(join25(destDir, "SKILL.md"), "utf-8");
|
|
20120
20220
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
20121
20221
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
20122
20222
|
} catch {
|
|
20123
20223
|
try {
|
|
20124
|
-
const content = await readFile5(
|
|
20224
|
+
const content = await readFile5(join25(destDir, "skill.md"), "utf-8");
|
|
20125
20225
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
20126
20226
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
20127
20227
|
} catch {
|
|
@@ -20156,15 +20256,15 @@ function parseGitHubUrl(input) {
|
|
|
20156
20256
|
async function findSkillDir(root) {
|
|
20157
20257
|
const candidates = ["SKILL.md", "skill.md"];
|
|
20158
20258
|
for (const c of candidates) {
|
|
20159
|
-
if (
|
|
20259
|
+
if (existsSync24(join25(root, c))) return root;
|
|
20160
20260
|
}
|
|
20161
20261
|
try {
|
|
20162
20262
|
const entries = await readdir5(root, { withFileTypes: true });
|
|
20163
20263
|
for (const entry of entries) {
|
|
20164
20264
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
20165
20265
|
for (const c of candidates) {
|
|
20166
|
-
if (
|
|
20167
|
-
return
|
|
20266
|
+
if (existsSync24(join25(root, entry.name, c))) {
|
|
20267
|
+
return join25(root, entry.name);
|
|
20168
20268
|
}
|
|
20169
20269
|
}
|
|
20170
20270
|
}
|
|
@@ -20176,15 +20276,15 @@ async function findSkillDir(root) {
|
|
|
20176
20276
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
20177
20277
|
let subEntries;
|
|
20178
20278
|
try {
|
|
20179
|
-
subEntries = await readdir5(
|
|
20279
|
+
subEntries = await readdir5(join25(root, entry.name), { withFileTypes: true });
|
|
20180
20280
|
} catch {
|
|
20181
20281
|
continue;
|
|
20182
20282
|
}
|
|
20183
20283
|
for (const sub of subEntries) {
|
|
20184
20284
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
20185
20285
|
for (const c of candidates) {
|
|
20186
|
-
if (
|
|
20187
|
-
return
|
|
20286
|
+
if (existsSync24(join25(root, entry.name, sub.name, c))) {
|
|
20287
|
+
return join25(root, entry.name, sub.name);
|
|
20188
20288
|
}
|
|
20189
20289
|
}
|
|
20190
20290
|
}
|
|
@@ -21480,13 +21580,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
21480
21580
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
21481
21581
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
21482
21582
|
if (current === "frozen") {
|
|
21483
|
-
const { readFileSync:
|
|
21484
|
-
const { join:
|
|
21583
|
+
const { readFileSync: readFileSync33, existsSync: existsSync62 } = await import("fs");
|
|
21584
|
+
const { join: join41 } = await import("path");
|
|
21485
21585
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
21486
|
-
const soulPath =
|
|
21487
|
-
const userPath =
|
|
21488
|
-
const soul =
|
|
21489
|
-
const user =
|
|
21586
|
+
const soulPath = join41(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
21587
|
+
const userPath = join41(CC_CLAW_HOME3, "identity/USER.md");
|
|
21588
|
+
const soul = existsSync62(soulPath) ? readFileSync33(soulPath, "utf-8") : "";
|
|
21589
|
+
const user = existsSync62(userPath) ? readFileSync33(userPath, "utf-8") : "";
|
|
21490
21590
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
21491
21591
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
21492
21592
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -21563,11 +21663,11 @@ var init_evolve2 = __esm({
|
|
|
21563
21663
|
});
|
|
21564
21664
|
|
|
21565
21665
|
// src/optimizer/identity-audit.ts
|
|
21566
|
-
import { readFileSync as
|
|
21567
|
-
import { join as
|
|
21666
|
+
import { readFileSync as readFileSync14, existsSync as existsSync25, readdirSync as readdirSync10, statSync as statSync7 } from "fs";
|
|
21667
|
+
import { join as join26 } from "path";
|
|
21568
21668
|
function readIdentityFile2(filename) {
|
|
21569
21669
|
try {
|
|
21570
|
-
return
|
|
21670
|
+
return readFileSync14(join26(IDENTITY_PATH, filename), "utf-8");
|
|
21571
21671
|
} catch {
|
|
21572
21672
|
return "";
|
|
21573
21673
|
}
|
|
@@ -21582,13 +21682,13 @@ function getMtime(filepath) {
|
|
|
21582
21682
|
function findBackupFiles() {
|
|
21583
21683
|
const backups = [];
|
|
21584
21684
|
const dirs = [IDENTITY_PATH];
|
|
21585
|
-
const contextDir =
|
|
21586
|
-
if (
|
|
21685
|
+
const contextDir = join26(IDENTITY_PATH, "..", "workspace", "context");
|
|
21686
|
+
if (existsSync25(contextDir)) dirs.push(contextDir);
|
|
21587
21687
|
for (const dir of dirs) {
|
|
21588
21688
|
try {
|
|
21589
21689
|
for (const entry of readdirSync10(dir)) {
|
|
21590
21690
|
if (entry.endsWith(".bak") || /\.bak\.\d{4}-\d{2}-\d{2}/.test(entry)) {
|
|
21591
|
-
backups.push(
|
|
21691
|
+
backups.push(join26(dir, entry));
|
|
21592
21692
|
}
|
|
21593
21693
|
}
|
|
21594
21694
|
} catch {
|
|
@@ -21609,9 +21709,9 @@ function computeIdentityStats(pendingProposals, driftPercent) {
|
|
|
21609
21709
|
userChars,
|
|
21610
21710
|
ccClawChars,
|
|
21611
21711
|
boilerplateChars,
|
|
21612
|
-
soulMtime: getMtime(
|
|
21613
|
-
userMtime: getMtime(
|
|
21614
|
-
ccClawMtime: getMtime(
|
|
21712
|
+
soulMtime: getMtime(join26(IDENTITY_PATH, "SOUL.md")),
|
|
21713
|
+
userMtime: getMtime(join26(IDENTITY_PATH, "USER.md")),
|
|
21714
|
+
ccClawMtime: getMtime(join26(IDENTITY_PATH, "CC-CLAW.md")),
|
|
21615
21715
|
backupFiles: findBackupFiles(),
|
|
21616
21716
|
estimatedTokens: Math.ceil(ccClawChars / 4),
|
|
21617
21717
|
pendingEvolveProposals: pendingProposals,
|
|
@@ -21720,8 +21820,8 @@ var init_identity_audit = __esm({
|
|
|
21720
21820
|
});
|
|
21721
21821
|
|
|
21722
21822
|
// src/optimizer/skill-audit.ts
|
|
21723
|
-
import { readFileSync as
|
|
21724
|
-
import { join as
|
|
21823
|
+
import { readFileSync as readFileSync15, existsSync as existsSync26 } from "fs";
|
|
21824
|
+
import { join as join27, basename as basename3 } from "path";
|
|
21725
21825
|
function parseFrontmatter3(content) {
|
|
21726
21826
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
21727
21827
|
if (!fmMatch) return {};
|
|
@@ -21766,10 +21866,10 @@ function detectDependentSkills(content) {
|
|
|
21766
21866
|
return Array.from(deps);
|
|
21767
21867
|
}
|
|
21768
21868
|
function computeSkillStats(skillPath) {
|
|
21769
|
-
const content =
|
|
21869
|
+
const content = readFileSync15(skillPath, "utf-8");
|
|
21770
21870
|
const lines = content.split("\n");
|
|
21771
21871
|
return {
|
|
21772
|
-
skillName: basename3(skillPath, ".md") === "SKILL" ? basename3(
|
|
21872
|
+
skillName: basename3(skillPath, ".md") === "SKILL" ? basename3(join27(skillPath, "..")) : basename3(skillPath, ".md"),
|
|
21773
21873
|
skillPath,
|
|
21774
21874
|
lineCount: lines.length,
|
|
21775
21875
|
charCount: content.length,
|
|
@@ -21789,13 +21889,13 @@ function loadDependentSkillContents(depNames, ccClawSkillsDir) {
|
|
|
21789
21889
|
const results = [];
|
|
21790
21890
|
for (const name of depNames) {
|
|
21791
21891
|
const candidates = [
|
|
21792
|
-
|
|
21793
|
-
|
|
21892
|
+
join27(ccClawSkillsDir, name, "SKILL.md"),
|
|
21893
|
+
join27(ccClawSkillsDir, `${name}-skill`, "SKILL.md")
|
|
21794
21894
|
];
|
|
21795
21895
|
for (const candidate of candidates) {
|
|
21796
|
-
if (
|
|
21896
|
+
if (existsSync26(candidate)) {
|
|
21797
21897
|
try {
|
|
21798
|
-
const content =
|
|
21898
|
+
const content = readFileSync15(candidate, "utf-8");
|
|
21799
21899
|
results.push({
|
|
21800
21900
|
name,
|
|
21801
21901
|
content: content.length > 3e3 ? content.slice(0, 3e3) + "\n[...truncated]" : content
|
|
@@ -21939,8 +22039,8 @@ __export(analyze_exports2, {
|
|
|
21939
22039
|
});
|
|
21940
22040
|
import { spawn as spawn7 } from "child_process";
|
|
21941
22041
|
import { createInterface as createInterface7 } from "readline";
|
|
21942
|
-
import { readFileSync as
|
|
21943
|
-
import { join as
|
|
22042
|
+
import { readFileSync as readFileSync16, existsSync as existsSync27, readdirSync as readdirSync12 } from "fs";
|
|
22043
|
+
import { join as join28 } from "path";
|
|
21944
22044
|
import { homedir as homedir7 } from "os";
|
|
21945
22045
|
function parseOptimizeOutput(raw, validAreas) {
|
|
21946
22046
|
if (!raw || raw.includes("NO_FINDINGS")) return [];
|
|
@@ -22070,20 +22170,20 @@ function getModelDisplayInfo(chatId) {
|
|
|
22070
22170
|
}
|
|
22071
22171
|
function readIdentityFile3(filename) {
|
|
22072
22172
|
try {
|
|
22073
|
-
return
|
|
22173
|
+
return readFileSync16(join28(IDENTITY_PATH, filename), "utf-8");
|
|
22074
22174
|
} catch {
|
|
22075
22175
|
return "";
|
|
22076
22176
|
}
|
|
22077
22177
|
}
|
|
22078
22178
|
function loadContextFiles2() {
|
|
22079
|
-
const contextDir =
|
|
22179
|
+
const contextDir = join28(homedir7(), ".cc-claw", "workspace", "context");
|
|
22080
22180
|
const results = [];
|
|
22081
|
-
if (!
|
|
22181
|
+
if (!existsSync27(contextDir)) return results;
|
|
22082
22182
|
try {
|
|
22083
22183
|
for (const entry of readdirSync12(contextDir)) {
|
|
22084
22184
|
if (!entry.endsWith(".md")) continue;
|
|
22085
22185
|
try {
|
|
22086
|
-
const content =
|
|
22186
|
+
const content = readFileSync16(join28(contextDir, entry), "utf-8");
|
|
22087
22187
|
results.push({ name: entry, content });
|
|
22088
22188
|
} catch {
|
|
22089
22189
|
}
|
|
@@ -22134,8 +22234,8 @@ async function runSkillAudit(chatId, skillPath) {
|
|
|
22134
22234
|
const stats = computeSkillStats(skillPath);
|
|
22135
22235
|
log(`[optimizer] Running skill audit on ${stats.skillName} with ${adapter.id}:${model2}`);
|
|
22136
22236
|
const soulMd = readIdentityFile3("SOUL.md");
|
|
22137
|
-
const ccClawSkillsDir =
|
|
22138
|
-
const skillContent =
|
|
22237
|
+
const ccClawSkillsDir = join28(homedir7(), ".cc-claw", "workspace", "skills");
|
|
22238
|
+
const skillContent = readFileSync16(skillPath, "utf-8");
|
|
22139
22239
|
const prompt = buildSkillAuditPrompt(skillContent, stats, soulMd, ccClawSkillsDir);
|
|
22140
22240
|
const raw = await spawnAnalysis2(adapter, model2, prompt);
|
|
22141
22241
|
const findings = parseOptimizeOutput(raw, VALID_SKILL_AREAS);
|
|
@@ -22149,16 +22249,16 @@ async function runSkillAudit(chatId, skillPath) {
|
|
|
22149
22249
|
};
|
|
22150
22250
|
}
|
|
22151
22251
|
function listCcClawSkills() {
|
|
22152
|
-
const skillsDir =
|
|
22252
|
+
const skillsDir = join28(homedir7(), ".cc-claw", "workspace", "skills");
|
|
22153
22253
|
const entries = [];
|
|
22154
|
-
if (!
|
|
22254
|
+
if (!existsSync27(skillsDir)) return entries;
|
|
22155
22255
|
try {
|
|
22156
22256
|
for (const dir of readdirSync12(skillsDir)) {
|
|
22157
|
-
const skillFile =
|
|
22158
|
-
if (!
|
|
22257
|
+
const skillFile = join28(skillsDir, dir, "SKILL.md");
|
|
22258
|
+
if (!existsSync27(skillFile)) continue;
|
|
22159
22259
|
let description = "skill";
|
|
22160
22260
|
try {
|
|
22161
|
-
const content =
|
|
22261
|
+
const content = readFileSync16(skillFile, "utf-8");
|
|
22162
22262
|
const descMatch = content.match(/description:\s*>?\s*\n?\s*(.+)/);
|
|
22163
22263
|
if (descMatch) description = descMatch[1].trim().slice(0, 60);
|
|
22164
22264
|
} catch {
|
|
@@ -22485,8 +22585,8 @@ __export(optimize_exports, {
|
|
|
22485
22585
|
handleOptimizeCallback: () => handleOptimizeCallback,
|
|
22486
22586
|
handleOptimizeCommand: () => handleOptimizeCommand
|
|
22487
22587
|
});
|
|
22488
|
-
import { readFileSync as
|
|
22489
|
-
import { join as
|
|
22588
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync9, existsSync as existsSync28, readdirSync as readdirSync13, unlinkSync as unlinkSync7 } from "fs";
|
|
22589
|
+
import { join as join29, dirname as dirname4 } from "path";
|
|
22490
22590
|
import { homedir as homedir8 } from "os";
|
|
22491
22591
|
async function handleOptimizeCommand(chatId, channel, _args) {
|
|
22492
22592
|
const { getModelDisplayInfo: getModelDisplayInfo2 } = await Promise.resolve().then(() => (init_analyze2(), analyze_exports2));
|
|
@@ -22667,7 +22767,7 @@ async function runSkillAuditFlow(chatId, channel, skillName) {
|
|
|
22667
22767
|
} = await Promise.resolve().then(() => (init_ui2(), ui_exports));
|
|
22668
22768
|
const modelInfo = getModelDisplayInfo2(chatId);
|
|
22669
22769
|
if (!modelInfo) return;
|
|
22670
|
-
const skillPath =
|
|
22770
|
+
const skillPath = join29(homedir8(), ".cc-claw", "workspace", "skills", skillName, "SKILL.md");
|
|
22671
22771
|
const progressMsgId = typeof channel.sendTextReturningId === "function" ? await channel.sendTextReturningId(
|
|
22672
22772
|
chatId,
|
|
22673
22773
|
buildProgressMessage2(`skill: ${skillName}`, modelInfo.backend, modelInfo.model, modelInfo.thinkingLevel),
|
|
@@ -22756,15 +22856,15 @@ async function applyFinding(chatId, channel, index) {
|
|
|
22756
22856
|
await showFinding(chatId, channel, index + 1);
|
|
22757
22857
|
return;
|
|
22758
22858
|
}
|
|
22759
|
-
if (!
|
|
22859
|
+
if (!existsSync28(targetPath)) {
|
|
22760
22860
|
await channel.sendText(chatId, `Target file not found: ${targetPath}`, { parseMode: "plain" });
|
|
22761
22861
|
session2.skipped.push(index);
|
|
22762
22862
|
await showFinding(chatId, channel, index + 1);
|
|
22763
22863
|
return;
|
|
22764
22864
|
}
|
|
22765
|
-
const original =
|
|
22865
|
+
const original = readFileSync17(targetPath, "utf-8");
|
|
22766
22866
|
const backupPath = targetPath + `.bak.${Date.now()}`;
|
|
22767
|
-
|
|
22867
|
+
writeFileSync9(backupPath, original, "utf-8");
|
|
22768
22868
|
pruneBackups2(targetPath);
|
|
22769
22869
|
let newContent;
|
|
22770
22870
|
try {
|
|
@@ -22794,7 +22894,7 @@ async function applyFinding(chatId, channel, index) {
|
|
|
22794
22894
|
await showFinding(chatId, channel, index + 1);
|
|
22795
22895
|
return;
|
|
22796
22896
|
}
|
|
22797
|
-
|
|
22897
|
+
writeFileSync9(targetPath, newContent, "utf-8");
|
|
22798
22898
|
session2.applied.push(index);
|
|
22799
22899
|
if (targetPath.includes("identity/")) {
|
|
22800
22900
|
try {
|
|
@@ -22838,14 +22938,14 @@ async function finishReview(chatId, channel) {
|
|
|
22838
22938
|
activeSessions.delete(chatId);
|
|
22839
22939
|
}
|
|
22840
22940
|
function resolveTargetFile(location, auditTarget) {
|
|
22841
|
-
const ccClawHome =
|
|
22941
|
+
const ccClawHome = join29(homedir8(), ".cc-claw");
|
|
22842
22942
|
const filePart = location.split(":")[0]?.trim();
|
|
22843
22943
|
if (!filePart) return null;
|
|
22844
|
-
if (filePart === "SOUL.md") return
|
|
22845
|
-
if (filePart === "USER.md") return
|
|
22846
|
-
if (filePart === "CC-CLAW.md") return
|
|
22944
|
+
if (filePart === "SOUL.md") return join29(ccClawHome, "identity", "SOUL.md");
|
|
22945
|
+
if (filePart === "USER.md") return join29(ccClawHome, "identity", "USER.md");
|
|
22946
|
+
if (filePart === "CC-CLAW.md") return join29(ccClawHome, "identity", "CC-CLAW.md");
|
|
22847
22947
|
if (filePart === "SKILL.md" && auditTarget !== "identity") {
|
|
22848
|
-
return
|
|
22948
|
+
return join29(ccClawHome, "workspace", "skills", auditTarget, "SKILL.md");
|
|
22849
22949
|
}
|
|
22850
22950
|
return null;
|
|
22851
22951
|
}
|
|
@@ -22853,7 +22953,7 @@ function pruneBackups2(absolutePath) {
|
|
|
22853
22953
|
const dir = dirname4(absolutePath);
|
|
22854
22954
|
const baseName = absolutePath.split("/").pop() ?? "";
|
|
22855
22955
|
try {
|
|
22856
|
-
const backups = readdirSync13(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) =>
|
|
22956
|
+
const backups = readdirSync13(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join29(dir, f));
|
|
22857
22957
|
while (backups.length > 3) {
|
|
22858
22958
|
const oldest = backups.shift();
|
|
22859
22959
|
try {
|
|
@@ -23095,7 +23195,7 @@ __export(auto_create_exports, {
|
|
|
23095
23195
|
saveSkill: () => saveSkill,
|
|
23096
23196
|
storePendingDraft: () => storePendingDraft
|
|
23097
23197
|
});
|
|
23098
|
-
import { join as
|
|
23198
|
+
import { join as join30 } from "path";
|
|
23099
23199
|
import { writeFile as writeFile5, mkdir as mkdir5 } from "fs/promises";
|
|
23100
23200
|
function isSkillWorthy(signals) {
|
|
23101
23201
|
const { toolUseCount, tokenOutput, elapsedMs, userMessage } = signals;
|
|
@@ -23277,9 +23377,9 @@ async function saveSkill(name, content, opts = {}) {
|
|
|
23277
23377
|
warn(`[auto-skill] Quality warning for "${name}": ${w}`);
|
|
23278
23378
|
}
|
|
23279
23379
|
}
|
|
23280
|
-
const dir =
|
|
23380
|
+
const dir = join30(SKILLS_PATH, name);
|
|
23281
23381
|
await mkdir5(dir, { recursive: true });
|
|
23282
|
-
const filePath =
|
|
23382
|
+
const filePath = join30(dir, "SKILL.md");
|
|
23283
23383
|
await writeFile5(filePath, withFrontmatter, "utf-8");
|
|
23284
23384
|
invalidateSkillCache();
|
|
23285
23385
|
log(`[auto-skill] Saved skill "${name}" to ${filePath}`);
|
|
@@ -27096,7 +27196,7 @@ ${lines.join("\n")}`, { parseMode: "plain" });
|
|
|
27096
27196
|
try {
|
|
27097
27197
|
const { readFile: readFileFs } = await import("fs/promises");
|
|
27098
27198
|
const { mkdir: mkdir7, writeFile: writeFileFs } = await import("fs/promises");
|
|
27099
|
-
const { join:
|
|
27199
|
+
const { join: join41 } = await import("path");
|
|
27100
27200
|
const { SKILLS_PATH: SKILLS_PATH2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
27101
27201
|
const { updateFrontmatter: updateFrontmatter2, ensureThreeTierFrontmatter: ensureThreeTierFrontmatter2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
|
|
27102
27202
|
const { invalidateSkillCache: invalidateSkillCache2 } = await Promise.resolve().then(() => (init_discover(), discover_exports));
|
|
@@ -27104,9 +27204,9 @@ ${lines.join("\n")}`, { parseMode: "plain" });
|
|
|
27104
27204
|
let updated = ensureThreeTierFrontmatter2(raw, { name: skillName, source });
|
|
27105
27205
|
const targetStatus = doApprove ? "approved" : "imported";
|
|
27106
27206
|
updated = updateFrontmatter2(updated, { status: targetStatus });
|
|
27107
|
-
const targetDir =
|
|
27207
|
+
const targetDir = join41(SKILLS_PATH2, skillName);
|
|
27108
27208
|
await mkdir7(targetDir, { recursive: true });
|
|
27109
|
-
await writeFileFs(
|
|
27209
|
+
await writeFileFs(join41(targetDir, "SKILL.md"), updated, "utf-8");
|
|
27110
27210
|
invalidateSkillCache2();
|
|
27111
27211
|
if (doApprove) {
|
|
27112
27212
|
await channel.sendText(
|
|
@@ -27235,13 +27335,13 @@ ${formatValidationReport2(validation)}` : "\n\n\u2705 Quality checks passed.";
|
|
|
27235
27335
|
return;
|
|
27236
27336
|
}
|
|
27237
27337
|
try {
|
|
27238
|
-
const { readFileSync:
|
|
27338
|
+
const { readFileSync: readFileSync33, writeFileSync: writeFileSync16 } = await import("fs");
|
|
27239
27339
|
const { updateFrontmatter: updateFrontmatter2, ensureThreeTierFrontmatter: ensureThreeTierFrontmatter2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
|
|
27240
27340
|
const { invalidateSkillCache: invalidateSkillCache2 } = await Promise.resolve().then(() => (init_discover(), discover_exports));
|
|
27241
|
-
const raw =
|
|
27341
|
+
const raw = readFileSync33(skill.filePath, "utf-8");
|
|
27242
27342
|
let updated = ensureThreeTierFrontmatter2(raw, { name: skillName, source: "cc-claw" });
|
|
27243
27343
|
updated = updateFrontmatter2(updated, { status: "approved" });
|
|
27244
|
-
|
|
27344
|
+
writeFileSync16(skill.filePath, updated, "utf-8");
|
|
27245
27345
|
invalidateSkillCache2();
|
|
27246
27346
|
await channel.sendText(chatId, `\u2705 "${skillName}" approved.`, { parseMode: "plain" });
|
|
27247
27347
|
const refreshedSkills = await discoverAllSkills();
|
|
@@ -27288,17 +27388,17 @@ ${formatValidationReport2(validation)}` : "\n\n\u2705 Quality checks passed.";
|
|
|
27288
27388
|
return;
|
|
27289
27389
|
}
|
|
27290
27390
|
try {
|
|
27291
|
-
const { readFileSync:
|
|
27391
|
+
const { readFileSync: readFileSync33, writeFileSync: writeFileSync16 } = await import("fs");
|
|
27292
27392
|
const { updateFrontmatter: updateFrontmatter2, ensureThreeTierFrontmatter: ensureThreeTierFrontmatter2 } = await Promise.resolve().then(() => (init_frontmatter(), frontmatter_exports));
|
|
27293
27393
|
const { invalidateSkillCache: invalidateSkillCache2 } = await Promise.resolve().then(() => (init_discover(), discover_exports));
|
|
27294
27394
|
let approvedCount = 0;
|
|
27295
27395
|
const issues = [];
|
|
27296
27396
|
for (const skill of unapproved) {
|
|
27297
27397
|
try {
|
|
27298
|
-
const raw =
|
|
27398
|
+
const raw = readFileSync33(skill.filePath, "utf-8");
|
|
27299
27399
|
let updated = ensureThreeTierFrontmatter2(raw, { name: skill.name, source: "cc-claw" });
|
|
27300
27400
|
updated = updateFrontmatter2(updated, { status: "approved" });
|
|
27301
|
-
|
|
27401
|
+
writeFileSync16(skill.filePath, updated, "utf-8");
|
|
27302
27402
|
approvedCount++;
|
|
27303
27403
|
} catch (e) {
|
|
27304
27404
|
issues.push(`${skill.name}: ${e.message}`);
|
|
@@ -28896,7 +28996,7 @@ var init_cron = __esm({
|
|
|
28896
28996
|
});
|
|
28897
28997
|
|
|
28898
28998
|
// src/agents/runners/wrap-backend.ts
|
|
28899
|
-
import { join as
|
|
28999
|
+
import { join as join31 } from "path";
|
|
28900
29000
|
function buildMcpCommands(backendId) {
|
|
28901
29001
|
const exe = backendId === BACKEND.CURSOR ? "agent" : backendId;
|
|
28902
29002
|
return {
|
|
@@ -28992,7 +29092,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
28992
29092
|
const configPath = writeMcpConfigFile(server);
|
|
28993
29093
|
return ["--mcp-config", configPath];
|
|
28994
29094
|
},
|
|
28995
|
-
getSkillPath: () =>
|
|
29095
|
+
getSkillPath: () => join31(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
28996
29096
|
};
|
|
28997
29097
|
}
|
|
28998
29098
|
var BACKEND_CAPABILITIES;
|
|
@@ -29054,18 +29154,18 @@ var init_wrap_backend = __esm({
|
|
|
29054
29154
|
});
|
|
29055
29155
|
|
|
29056
29156
|
// src/agents/runners/config-loader.ts
|
|
29057
|
-
import { readFileSync as
|
|
29058
|
-
import { join as
|
|
29059
|
-
import { execFileSync as
|
|
29157
|
+
import { readFileSync as readFileSync18, readdirSync as readdirSync14, existsSync as existsSync29, mkdirSync as mkdirSync10, watchFile, unwatchFile } from "fs";
|
|
29158
|
+
import { join as join32 } from "path";
|
|
29159
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
29060
29160
|
function resolveExecutable2(config2) {
|
|
29061
|
-
if (
|
|
29161
|
+
if (existsSync29(config2.executable)) return config2.executable;
|
|
29062
29162
|
try {
|
|
29063
|
-
return
|
|
29163
|
+
return execFileSync4("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
29064
29164
|
} catch {
|
|
29065
29165
|
}
|
|
29066
29166
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
29067
29167
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
29068
|
-
if (
|
|
29168
|
+
if (existsSync29(resolved)) return resolved;
|
|
29069
29169
|
}
|
|
29070
29170
|
return config2.executable;
|
|
29071
29171
|
}
|
|
@@ -29191,12 +29291,12 @@ function configToRunner(config2) {
|
|
|
29191
29291
|
prepareMcpInjection() {
|
|
29192
29292
|
return [];
|
|
29193
29293
|
},
|
|
29194
|
-
getSkillPath: () =>
|
|
29294
|
+
getSkillPath: () => join32(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
29195
29295
|
};
|
|
29196
29296
|
}
|
|
29197
29297
|
function loadRunnerConfig(filePath) {
|
|
29198
29298
|
try {
|
|
29199
|
-
const content =
|
|
29299
|
+
const content = readFileSync18(filePath, "utf-8");
|
|
29200
29300
|
return JSON.parse(content);
|
|
29201
29301
|
} catch (err) {
|
|
29202
29302
|
warn(`[runners] Failed to load config ${filePath}: ${err}`);
|
|
@@ -29204,14 +29304,14 @@ function loadRunnerConfig(filePath) {
|
|
|
29204
29304
|
}
|
|
29205
29305
|
}
|
|
29206
29306
|
function loadAllRunnerConfigs() {
|
|
29207
|
-
if (!
|
|
29307
|
+
if (!existsSync29(RUNNERS_PATH)) {
|
|
29208
29308
|
mkdirSync10(RUNNERS_PATH, { recursive: true });
|
|
29209
29309
|
return [];
|
|
29210
29310
|
}
|
|
29211
29311
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
29212
29312
|
const configs = [];
|
|
29213
29313
|
for (const file of files) {
|
|
29214
|
-
const config2 = loadRunnerConfig(
|
|
29314
|
+
const config2 = loadRunnerConfig(join32(RUNNERS_PATH, file));
|
|
29215
29315
|
if (config2) configs.push(config2);
|
|
29216
29316
|
}
|
|
29217
29317
|
return configs;
|
|
@@ -29232,16 +29332,16 @@ function registerConfigRunners() {
|
|
|
29232
29332
|
return count;
|
|
29233
29333
|
}
|
|
29234
29334
|
function watchRunnerConfigs(onChange) {
|
|
29235
|
-
if (!
|
|
29335
|
+
if (!existsSync29(RUNNERS_PATH)) return;
|
|
29236
29336
|
for (const prev of watchedFiles) {
|
|
29237
|
-
if (!
|
|
29337
|
+
if (!existsSync29(prev)) {
|
|
29238
29338
|
unwatchFile(prev);
|
|
29239
29339
|
watchedFiles.delete(prev);
|
|
29240
29340
|
}
|
|
29241
29341
|
}
|
|
29242
29342
|
const files = readdirSync14(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
29243
29343
|
for (const file of files) {
|
|
29244
|
-
const fullPath =
|
|
29344
|
+
const fullPath = join32(RUNNERS_PATH, file);
|
|
29245
29345
|
if (watchedFiles.has(fullPath)) continue;
|
|
29246
29346
|
watchedFiles.add(fullPath);
|
|
29247
29347
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -29759,8 +29859,8 @@ var init_telegram2 = __esm({
|
|
|
29759
29859
|
/** Watchdog interval that detects silent polling death */
|
|
29760
29860
|
pollingWatchdog = null;
|
|
29761
29861
|
/** Max time without any update before we consider polling dead (ms) */
|
|
29762
|
-
static POLLING_SILENCE_THRESHOLD_MS =
|
|
29763
|
-
//
|
|
29862
|
+
static POLLING_SILENCE_THRESHOLD_MS = 5 * 60 * 1e3;
|
|
29863
|
+
// 5 minutes
|
|
29764
29864
|
/** How often the watchdog checks for polling health (ms) */
|
|
29765
29865
|
static POLLING_WATCHDOG_INTERVAL_MS = 60 * 1e3;
|
|
29766
29866
|
// 60 seconds
|
|
@@ -30005,8 +30105,8 @@ var init_telegram2 = __esm({
|
|
|
30005
30105
|
if (!this.pollingExpected) return;
|
|
30006
30106
|
const silenceMs = Date.now() - this.lastUpdateAt;
|
|
30007
30107
|
if (silenceMs > _TelegramChannel.POLLING_SILENCE_THRESHOLD_MS) {
|
|
30008
|
-
|
|
30009
|
-
`[telegram]
|
|
30108
|
+
warn(
|
|
30109
|
+
`[telegram] No updates received for ${Math.round(silenceMs / 1e3)}s \u2014 triggering reconnect`
|
|
30010
30110
|
);
|
|
30011
30111
|
markChannelDown("telegram", `No updates for ${Math.round(silenceMs / 1e3)}s`);
|
|
30012
30112
|
this.lastUpdateAt = Date.now();
|
|
@@ -30533,19 +30633,19 @@ var init_telegram2 = __esm({
|
|
|
30533
30633
|
});
|
|
30534
30634
|
|
|
30535
30635
|
// src/skills/bootstrap.ts
|
|
30536
|
-
import { existsSync as
|
|
30636
|
+
import { existsSync as existsSync30, readFileSync as readFileSync19, writeFileSync as writeFileSync10, copyFileSync as copyFileSync3, readdirSync as readdirSync15 } from "fs";
|
|
30537
30637
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile6, copyFile } from "fs/promises";
|
|
30538
|
-
import { join as
|
|
30638
|
+
import { join as join33, dirname as dirname5 } from "path";
|
|
30539
30639
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
30540
30640
|
async function copyAgentManifestSkills() {
|
|
30541
|
-
if (!
|
|
30641
|
+
if (!existsSync30(PKG_SKILLS)) return;
|
|
30542
30642
|
try {
|
|
30543
30643
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
30544
30644
|
for (const entry of entries) {
|
|
30545
30645
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
30546
|
-
const src =
|
|
30547
|
-
const dest =
|
|
30548
|
-
if (
|
|
30646
|
+
const src = join33(PKG_SKILLS, entry.name);
|
|
30647
|
+
const dest = join33(SKILLS_PATH, entry.name);
|
|
30648
|
+
if (existsSync30(dest)) continue;
|
|
30549
30649
|
await copyFile(src, dest);
|
|
30550
30650
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
30551
30651
|
}
|
|
@@ -30556,8 +30656,8 @@ async function copyAgentManifestSkills() {
|
|
|
30556
30656
|
async function bootstrapSkills() {
|
|
30557
30657
|
await copyAgentManifestSkills();
|
|
30558
30658
|
migrateSkillsToThreeTier();
|
|
30559
|
-
const usmDir =
|
|
30560
|
-
if (
|
|
30659
|
+
const usmDir = join33(SKILLS_PATH, USM_DIR_NAME);
|
|
30660
|
+
if (existsSync30(usmDir)) return;
|
|
30561
30661
|
try {
|
|
30562
30662
|
const entries = await readdir6(SKILLS_PATH);
|
|
30563
30663
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -30580,8 +30680,8 @@ async function bootstrapSkills() {
|
|
|
30580
30680
|
}
|
|
30581
30681
|
}
|
|
30582
30682
|
async function patchUsmForCcClaw(usmDir) {
|
|
30583
|
-
const skillPath =
|
|
30584
|
-
if (!
|
|
30683
|
+
const skillPath = join33(usmDir, "SKILL.md");
|
|
30684
|
+
if (!existsSync30(skillPath)) return;
|
|
30585
30685
|
try {
|
|
30586
30686
|
let content = await readFile8(skillPath, "utf-8");
|
|
30587
30687
|
let patched = false;
|
|
@@ -30620,9 +30720,9 @@ async function patchUsmForCcClaw(usmDir) {
|
|
|
30620
30720
|
}
|
|
30621
30721
|
}
|
|
30622
30722
|
function migrateSkillsToThreeTier() {
|
|
30623
|
-
const markerPath =
|
|
30624
|
-
if (
|
|
30625
|
-
if (!
|
|
30723
|
+
const markerPath = join33(SKILLS_PATH, MIGRATION_MARKER);
|
|
30724
|
+
if (existsSync30(markerPath)) return;
|
|
30725
|
+
if (!existsSync30(SKILLS_PATH)) return;
|
|
30626
30726
|
let entries;
|
|
30627
30727
|
try {
|
|
30628
30728
|
entries = readdirSync15(SKILLS_PATH, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
|
|
@@ -30636,15 +30736,15 @@ function migrateSkillsToThreeTier() {
|
|
|
30636
30736
|
for (const dirName of entries) {
|
|
30637
30737
|
let skillPath;
|
|
30638
30738
|
for (const candidate of SKILL_FILE_CANDIDATES2) {
|
|
30639
|
-
const p =
|
|
30640
|
-
if (
|
|
30739
|
+
const p = join33(SKILLS_PATH, dirName, candidate);
|
|
30740
|
+
if (existsSync30(p)) {
|
|
30641
30741
|
skillPath = p;
|
|
30642
30742
|
break;
|
|
30643
30743
|
}
|
|
30644
30744
|
}
|
|
30645
30745
|
if (!skillPath) continue;
|
|
30646
30746
|
try {
|
|
30647
|
-
const raw =
|
|
30747
|
+
const raw = readFileSync19(skillPath, "utf-8");
|
|
30648
30748
|
const fmMatch = raw.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
30649
30749
|
if (fmMatch) {
|
|
30650
30750
|
const fm = fmMatch[1];
|
|
@@ -30658,7 +30758,7 @@ function migrateSkillsToThreeTier() {
|
|
|
30658
30758
|
copyFileSync3(skillPath, backupPath);
|
|
30659
30759
|
let updated = ensureThreeTierFrontmatter(raw, { name: dirName, source: "cc-claw" });
|
|
30660
30760
|
updated = updateFrontmatter(updated, { status: "approved" });
|
|
30661
|
-
|
|
30761
|
+
writeFileSync10(skillPath, updated, "utf-8");
|
|
30662
30762
|
migrated++;
|
|
30663
30763
|
log(`[skills] Migrated "${dirName}" to three-tier format (backed up to ${backupPath})`);
|
|
30664
30764
|
} catch (err) {
|
|
@@ -30667,7 +30767,7 @@ function migrateSkillsToThreeTier() {
|
|
|
30667
30767
|
}
|
|
30668
30768
|
}
|
|
30669
30769
|
try {
|
|
30670
|
-
|
|
30770
|
+
writeFileSync10(markerPath, [
|
|
30671
30771
|
`# Three-tier skill migration completed`,
|
|
30672
30772
|
`# Date: ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
30673
30773
|
`# Migrated: ${migrated}, Skipped: ${skipped}, Failed: ${failed}`,
|
|
@@ -30693,8 +30793,8 @@ var init_bootstrap = __esm({
|
|
|
30693
30793
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
30694
30794
|
USM_DIR_NAME = "universal-skills-manager";
|
|
30695
30795
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
30696
|
-
PKG_ROOT =
|
|
30697
|
-
PKG_SKILLS =
|
|
30796
|
+
PKG_ROOT = join33(dirname5(fileURLToPath2(import.meta.url)), "..", "..");
|
|
30797
|
+
PKG_SKILLS = join33(PKG_ROOT, "skills");
|
|
30698
30798
|
MIGRATION_MARKER = ".three-tier-migrated";
|
|
30699
30799
|
SKILL_FILE_CANDIDATES2 = ["SKILL.md", "skill.md"];
|
|
30700
30800
|
}
|
|
@@ -30809,13 +30909,13 @@ __export(ai_skill_exports, {
|
|
|
30809
30909
|
generateAiSkill: () => generateAiSkill,
|
|
30810
30910
|
installAiSkill: () => installAiSkill
|
|
30811
30911
|
});
|
|
30812
|
-
import { existsSync as
|
|
30813
|
-
import { join as
|
|
30912
|
+
import { existsSync as existsSync31, writeFileSync as writeFileSync11, mkdirSync as mkdirSync11 } from "fs";
|
|
30913
|
+
import { join as join34 } from "path";
|
|
30814
30914
|
import { homedir as homedir9 } from "os";
|
|
30815
30915
|
function generateAiSkill() {
|
|
30816
30916
|
const version = VERSION;
|
|
30817
30917
|
let systemState = "";
|
|
30818
|
-
if (
|
|
30918
|
+
if (existsSync31(DB_PATH)) {
|
|
30819
30919
|
try {
|
|
30820
30920
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
30821
30921
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -31257,11 +31357,11 @@ function installAiSkill() {
|
|
|
31257
31357
|
const failed = [];
|
|
31258
31358
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
31259
31359
|
for (const dir of dirs) {
|
|
31260
|
-
const skillDir =
|
|
31261
|
-
const skillPath =
|
|
31360
|
+
const skillDir = join34(dir, "cc-claw-cli");
|
|
31361
|
+
const skillPath = join34(skillDir, "SKILL.md");
|
|
31262
31362
|
try {
|
|
31263
31363
|
mkdirSync11(skillDir, { recursive: true });
|
|
31264
|
-
|
|
31364
|
+
writeFileSync11(skillPath, skill, "utf-8");
|
|
31265
31365
|
installed.push(skillPath);
|
|
31266
31366
|
} catch {
|
|
31267
31367
|
failed.push(skillPath);
|
|
@@ -31277,11 +31377,11 @@ var init_ai_skill = __esm({
|
|
|
31277
31377
|
init_paths();
|
|
31278
31378
|
init_version();
|
|
31279
31379
|
BACKEND_SKILL_DIRS2 = {
|
|
31280
|
-
"cc-claw": [
|
|
31281
|
-
claude: [
|
|
31282
|
-
gemini: [
|
|
31283
|
-
codex: [
|
|
31284
|
-
cursor: [
|
|
31380
|
+
"cc-claw": [join34(homedir9(), ".cc-claw", "workspace", "skills")],
|
|
31381
|
+
claude: [join34(homedir9(), ".claude", "skills")],
|
|
31382
|
+
gemini: [join34(homedir9(), ".gemini", "skills")],
|
|
31383
|
+
codex: [join34(homedir9(), ".agents", "skills")],
|
|
31384
|
+
cursor: [join34(homedir9(), ".cursor", "skills"), join34(homedir9(), ".cursor", "skills-cursor")]
|
|
31285
31385
|
};
|
|
31286
31386
|
}
|
|
31287
31387
|
});
|
|
@@ -31291,21 +31391,21 @@ var index_exports = {};
|
|
|
31291
31391
|
__export(index_exports, {
|
|
31292
31392
|
main: () => main
|
|
31293
31393
|
});
|
|
31294
|
-
import { mkdirSync as mkdirSync12, existsSync as
|
|
31295
|
-
import { join as
|
|
31394
|
+
import { mkdirSync as mkdirSync12, existsSync as existsSync32, renameSync as renameSync2, statSync as statSync8, readFileSync as readFileSync21 } from "fs";
|
|
31395
|
+
import { join as join35 } from "path";
|
|
31296
31396
|
import dotenv from "dotenv";
|
|
31297
31397
|
function migrateLayout() {
|
|
31298
31398
|
const moves = [
|
|
31299
|
-
[
|
|
31300
|
-
[
|
|
31301
|
-
[
|
|
31302
|
-
[
|
|
31303
|
-
[
|
|
31304
|
-
[
|
|
31305
|
-
[
|
|
31399
|
+
[join35(CC_CLAW_HOME, "cc-claw.db"), join35(DATA_PATH, "cc-claw.db")],
|
|
31400
|
+
[join35(CC_CLAW_HOME, "cc-claw.db-shm"), join35(DATA_PATH, "cc-claw.db-shm")],
|
|
31401
|
+
[join35(CC_CLAW_HOME, "cc-claw.db-wal"), join35(DATA_PATH, "cc-claw.db-wal")],
|
|
31402
|
+
[join35(CC_CLAW_HOME, "cc-claw.log"), join35(LOGS_PATH, "cc-claw.log")],
|
|
31403
|
+
[join35(CC_CLAW_HOME, "cc-claw.log.1"), join35(LOGS_PATH, "cc-claw.log.1")],
|
|
31404
|
+
[join35(CC_CLAW_HOME, "cc-claw.error.log"), join35(LOGS_PATH, "cc-claw.error.log")],
|
|
31405
|
+
[join35(CC_CLAW_HOME, "cc-claw.error.log.1"), join35(LOGS_PATH, "cc-claw.error.log.1")]
|
|
31306
31406
|
];
|
|
31307
31407
|
for (const [from, to] of moves) {
|
|
31308
|
-
if (
|
|
31408
|
+
if (existsSync32(from) && !existsSync32(to)) {
|
|
31309
31409
|
try {
|
|
31310
31410
|
renameSync2(from, to);
|
|
31311
31411
|
} catch {
|
|
@@ -31334,7 +31434,7 @@ async function main() {
|
|
|
31334
31434
|
let version = "unknown";
|
|
31335
31435
|
try {
|
|
31336
31436
|
const pkgPath = new URL("../package.json", import.meta.url);
|
|
31337
|
-
version = JSON.parse(
|
|
31437
|
+
version = JSON.parse(readFileSync21(pkgPath, "utf-8")).version;
|
|
31338
31438
|
} catch {
|
|
31339
31439
|
}
|
|
31340
31440
|
log(`[cc-claw] Starting v${version}`);
|
|
@@ -31481,11 +31581,11 @@ async function main() {
|
|
|
31481
31581
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
31482
31582
|
try {
|
|
31483
31583
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
31484
|
-
const { writeFileSync:
|
|
31485
|
-
const { join:
|
|
31486
|
-
const skillDir =
|
|
31584
|
+
const { writeFileSync: writeFileSync16, mkdirSync: mkdirSync19 } = await import("fs");
|
|
31585
|
+
const { join: join41 } = await import("path");
|
|
31586
|
+
const skillDir = join41(SKILLS_PATH, "cc-claw-cli");
|
|
31487
31587
|
mkdirSync19(skillDir, { recursive: true });
|
|
31488
|
-
|
|
31588
|
+
writeFileSync16(join41(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
31489
31589
|
log("[cc-claw] AI skill updated");
|
|
31490
31590
|
} catch {
|
|
31491
31591
|
}
|
|
@@ -31585,10 +31685,10 @@ var init_index = __esm({
|
|
|
31585
31685
|
init_health3();
|
|
31586
31686
|
init_image_gen();
|
|
31587
31687
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SESSION_LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
31588
|
-
if (!
|
|
31688
|
+
if (!existsSync32(dir)) mkdirSync12(dir, { recursive: true });
|
|
31589
31689
|
}
|
|
31590
31690
|
migrateLayout();
|
|
31591
|
-
if (
|
|
31691
|
+
if (existsSync32(ENV_PATH)) {
|
|
31592
31692
|
dotenv.config({ path: ENV_PATH });
|
|
31593
31693
|
} else {
|
|
31594
31694
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -31609,12 +31709,12 @@ __export(api_client_exports, {
|
|
|
31609
31709
|
apiPost: () => apiPost,
|
|
31610
31710
|
isDaemonRunning: () => isDaemonRunning
|
|
31611
31711
|
});
|
|
31612
|
-
import { readFileSync as
|
|
31712
|
+
import { readFileSync as readFileSync22, existsSync as existsSync33 } from "fs";
|
|
31613
31713
|
import { request as httpRequest, Agent } from "http";
|
|
31614
31714
|
function getToken() {
|
|
31615
31715
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
31616
31716
|
try {
|
|
31617
|
-
if (
|
|
31717
|
+
if (existsSync33(TOKEN_PATH)) return readFileSync22(TOKEN_PATH, "utf-8").trim();
|
|
31618
31718
|
} catch {
|
|
31619
31719
|
}
|
|
31620
31720
|
return null;
|
|
@@ -31713,19 +31813,19 @@ __export(service_exports2, {
|
|
|
31713
31813
|
serviceStatus: () => serviceStatus,
|
|
31714
31814
|
uninstallService: () => uninstallService
|
|
31715
31815
|
});
|
|
31716
|
-
import { existsSync as
|
|
31717
|
-
import { execFileSync as
|
|
31816
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync13, writeFileSync as writeFileSync12, unlinkSync as unlinkSync8 } from "fs";
|
|
31817
|
+
import { execFileSync as execFileSync5, execSync as execSync5 } from "child_process";
|
|
31718
31818
|
import { homedir as homedir10, platform } from "os";
|
|
31719
|
-
import { join as
|
|
31819
|
+
import { join as join36, dirname as dirname6 } from "path";
|
|
31720
31820
|
function xmlEscape(s) {
|
|
31721
31821
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
31722
31822
|
}
|
|
31723
31823
|
function resolveExecutable3(name) {
|
|
31724
31824
|
try {
|
|
31725
|
-
return
|
|
31825
|
+
return execFileSync5("which", [name], { encoding: "utf-8" }).trim();
|
|
31726
31826
|
} catch {
|
|
31727
31827
|
const fallback = process.argv[1];
|
|
31728
|
-
if (fallback &&
|
|
31828
|
+
if (fallback && existsSync34(fallback)) return fallback;
|
|
31729
31829
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
31730
31830
|
}
|
|
31731
31831
|
}
|
|
@@ -31734,14 +31834,14 @@ function getPathDirs() {
|
|
|
31734
31834
|
const home = homedir10();
|
|
31735
31835
|
const dirs = /* @__PURE__ */ new Set([
|
|
31736
31836
|
nodeBin,
|
|
31737
|
-
|
|
31837
|
+
join36(home, ".local", "bin"),
|
|
31738
31838
|
"/usr/local/bin",
|
|
31739
31839
|
"/usr/bin",
|
|
31740
31840
|
"/bin"
|
|
31741
31841
|
]);
|
|
31742
31842
|
try {
|
|
31743
31843
|
const prefix = execSync5("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
31744
|
-
if (prefix) dirs.add(
|
|
31844
|
+
if (prefix) dirs.add(join36(prefix, "bin"));
|
|
31745
31845
|
} catch {
|
|
31746
31846
|
}
|
|
31747
31847
|
return [...dirs].join(":");
|
|
@@ -31800,26 +31900,26 @@ function generatePlist() {
|
|
|
31800
31900
|
}
|
|
31801
31901
|
function installMacOS() {
|
|
31802
31902
|
const agentsDir = dirname6(PLIST_PATH);
|
|
31803
|
-
if (!
|
|
31804
|
-
if (!
|
|
31805
|
-
if (
|
|
31903
|
+
if (!existsSync34(agentsDir)) mkdirSync13(agentsDir, { recursive: true });
|
|
31904
|
+
if (!existsSync34(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
31905
|
+
if (existsSync34(PLIST_PATH)) {
|
|
31806
31906
|
try {
|
|
31807
|
-
|
|
31907
|
+
execFileSync5("launchctl", ["unload", PLIST_PATH]);
|
|
31808
31908
|
} catch {
|
|
31809
31909
|
}
|
|
31810
31910
|
}
|
|
31811
|
-
|
|
31911
|
+
writeFileSync12(PLIST_PATH, generatePlist());
|
|
31812
31912
|
console.log(` Installed: ${PLIST_PATH}`);
|
|
31813
|
-
|
|
31913
|
+
execFileSync5("launchctl", ["load", PLIST_PATH]);
|
|
31814
31914
|
console.log(" Service loaded and starting.");
|
|
31815
31915
|
}
|
|
31816
31916
|
function uninstallMacOS() {
|
|
31817
|
-
if (!
|
|
31917
|
+
if (!existsSync34(PLIST_PATH)) {
|
|
31818
31918
|
console.log(" No service found to uninstall.");
|
|
31819
31919
|
return;
|
|
31820
31920
|
}
|
|
31821
31921
|
try {
|
|
31822
|
-
|
|
31922
|
+
execFileSync5("launchctl", ["unload", PLIST_PATH]);
|
|
31823
31923
|
} catch {
|
|
31824
31924
|
}
|
|
31825
31925
|
unlinkSync8(PLIST_PATH);
|
|
@@ -31845,7 +31945,7 @@ async function getUptimeFromDaemon() {
|
|
|
31845
31945
|
}
|
|
31846
31946
|
function statusMacOS() {
|
|
31847
31947
|
try {
|
|
31848
|
-
const out =
|
|
31948
|
+
const out = execFileSync5("launchctl", ["list"], { encoding: "utf-8" });
|
|
31849
31949
|
const line = out.split("\n").find((l) => l.includes("cc-claw"));
|
|
31850
31950
|
if (line) {
|
|
31851
31951
|
const parts = line.trim().split(/\s+/);
|
|
@@ -31889,30 +31989,30 @@ WantedBy=default.target
|
|
|
31889
31989
|
`;
|
|
31890
31990
|
}
|
|
31891
31991
|
function installLinux() {
|
|
31892
|
-
if (!
|
|
31893
|
-
if (!
|
|
31894
|
-
|
|
31992
|
+
if (!existsSync34(SYSTEMD_DIR)) mkdirSync13(SYSTEMD_DIR, { recursive: true });
|
|
31993
|
+
if (!existsSync34(LOGS_PATH)) mkdirSync13(LOGS_PATH, { recursive: true });
|
|
31994
|
+
writeFileSync12(UNIT_PATH, generateUnit());
|
|
31895
31995
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
31896
|
-
|
|
31897
|
-
|
|
31898
|
-
|
|
31996
|
+
execFileSync5("systemctl", ["--user", "daemon-reload"]);
|
|
31997
|
+
execFileSync5("systemctl", ["--user", "enable", "cc-claw"]);
|
|
31998
|
+
execFileSync5("systemctl", ["--user", "start", "cc-claw"]);
|
|
31899
31999
|
console.log(" Service enabled and started.");
|
|
31900
32000
|
}
|
|
31901
32001
|
function uninstallLinux() {
|
|
31902
|
-
if (!
|
|
32002
|
+
if (!existsSync34(UNIT_PATH)) {
|
|
31903
32003
|
console.log(" No service found to uninstall.");
|
|
31904
32004
|
return;
|
|
31905
32005
|
}
|
|
31906
32006
|
try {
|
|
31907
|
-
|
|
32007
|
+
execFileSync5("systemctl", ["--user", "stop", "cc-claw"]);
|
|
31908
32008
|
} catch {
|
|
31909
32009
|
}
|
|
31910
32010
|
try {
|
|
31911
|
-
|
|
32011
|
+
execFileSync5("systemctl", ["--user", "disable", "cc-claw"]);
|
|
31912
32012
|
} catch {
|
|
31913
32013
|
}
|
|
31914
32014
|
unlinkSync8(UNIT_PATH);
|
|
31915
|
-
|
|
32015
|
+
execFileSync5("systemctl", ["--user", "daemon-reload"]);
|
|
31916
32016
|
console.log(" Service uninstalled.");
|
|
31917
32017
|
}
|
|
31918
32018
|
function statusLinux() {
|
|
@@ -31924,7 +32024,7 @@ function statusLinux() {
|
|
|
31924
32024
|
}
|
|
31925
32025
|
}
|
|
31926
32026
|
function installService() {
|
|
31927
|
-
if (!
|
|
32027
|
+
if (!existsSync34(join36(CC_CLAW_HOME, ".env"))) {
|
|
31928
32028
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
31929
32029
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
31930
32030
|
process.exitCode = 1;
|
|
@@ -31953,9 +32053,9 @@ var init_service2 = __esm({
|
|
|
31953
32053
|
"use strict";
|
|
31954
32054
|
init_paths();
|
|
31955
32055
|
PLIST_LABEL = "com.cc-claw";
|
|
31956
|
-
PLIST_PATH =
|
|
31957
|
-
SYSTEMD_DIR =
|
|
31958
|
-
UNIT_PATH =
|
|
32056
|
+
PLIST_PATH = join36(homedir10(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
32057
|
+
SYSTEMD_DIR = join36(homedir10(), ".config", "systemd", "user");
|
|
32058
|
+
UNIT_PATH = join36(SYSTEMD_DIR, "cc-claw.service");
|
|
31959
32059
|
}
|
|
31960
32060
|
});
|
|
31961
32061
|
|
|
@@ -32122,13 +32222,13 @@ var init_daemon = __esm({
|
|
|
32122
32222
|
});
|
|
32123
32223
|
|
|
32124
32224
|
// src/cli/resolve-chat.ts
|
|
32125
|
-
import { readFileSync as
|
|
32225
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
32126
32226
|
function resolveChatId2(globalOpts) {
|
|
32127
32227
|
const explicit = globalOpts.chat;
|
|
32128
32228
|
if (explicit) return explicit;
|
|
32129
32229
|
if (_cachedDefault) return _cachedDefault;
|
|
32130
32230
|
try {
|
|
32131
|
-
const content =
|
|
32231
|
+
const content = readFileSync24(ENV_PATH, "utf-8");
|
|
32132
32232
|
const match = content.match(/^ALLOWED_CHAT_ID=(.+)$/m);
|
|
32133
32233
|
if (match) {
|
|
32134
32234
|
_cachedDefault = match[1].split(",")[0].trim();
|
|
@@ -32152,7 +32252,7 @@ var status_exports = {};
|
|
|
32152
32252
|
__export(status_exports, {
|
|
32153
32253
|
statusCommand: () => statusCommand
|
|
32154
32254
|
});
|
|
32155
|
-
import { existsSync as
|
|
32255
|
+
import { existsSync as existsSync35, statSync as statSync9 } from "fs";
|
|
32156
32256
|
async function statusCommand(globalOpts, localOpts) {
|
|
32157
32257
|
try {
|
|
32158
32258
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -32192,7 +32292,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
32192
32292
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
32193
32293
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
32194
32294
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
32195
|
-
const dbStat =
|
|
32295
|
+
const dbStat = existsSync35(DB_PATH) ? statSync9(DB_PATH) : null;
|
|
32196
32296
|
let daemonRunning = false;
|
|
32197
32297
|
let daemonInfo = {};
|
|
32198
32298
|
try {
|
|
@@ -32304,13 +32404,13 @@ __export(doctor_exports, {
|
|
|
32304
32404
|
doctorCommand: () => doctorCommand,
|
|
32305
32405
|
doctorErrors: () => doctorErrors
|
|
32306
32406
|
});
|
|
32307
|
-
import { existsSync as
|
|
32308
|
-
import { execFileSync as
|
|
32407
|
+
import { existsSync as existsSync36, accessSync, constants } from "fs";
|
|
32408
|
+
import { execFileSync as execFileSync6 } from "child_process";
|
|
32309
32409
|
async function doctorCommand(globalOpts, localOpts) {
|
|
32310
32410
|
const checks = [];
|
|
32311
32411
|
const dbChecks = checkDatabase();
|
|
32312
32412
|
checks.push(...dbChecks);
|
|
32313
|
-
if (
|
|
32413
|
+
if (existsSync36(DB_PATH)) {
|
|
32314
32414
|
try {
|
|
32315
32415
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
32316
32416
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -32336,7 +32436,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
32336
32436
|
checks.push({ name: "Database health", status: "error", message: err.message });
|
|
32337
32437
|
}
|
|
32338
32438
|
}
|
|
32339
|
-
if (
|
|
32439
|
+
if (existsSync36(ENV_PATH)) {
|
|
32340
32440
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
32341
32441
|
} else {
|
|
32342
32442
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -32372,14 +32472,14 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
32372
32472
|
checks.push({ name: "Daemon", status: "warning", message: "could not probe" });
|
|
32373
32473
|
}
|
|
32374
32474
|
try {
|
|
32375
|
-
const latest =
|
|
32475
|
+
const latest = execFileSync6("npm", ["view", "cc-claw", "version"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
32376
32476
|
if (latest && latest !== VERSION) {
|
|
32377
32477
|
checks.push({ name: "Update available", status: "warning", message: `v${latest} available (current: v${VERSION})`, fix: "npm install -g cc-claw@latest" });
|
|
32378
32478
|
}
|
|
32379
32479
|
} catch {
|
|
32380
32480
|
}
|
|
32381
32481
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
32382
|
-
if (
|
|
32482
|
+
if (existsSync36(tokenPath)) {
|
|
32383
32483
|
try {
|
|
32384
32484
|
accessSync(tokenPath, constants.R_OK);
|
|
32385
32485
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -32445,10 +32545,10 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
32445
32545
|
const errorChecks = checks.filter(
|
|
32446
32546
|
(c) => ["Rate limits", "Content silence", "Spawn timeouts", "Other errors"].includes(c.name) && c.status !== "ok"
|
|
32447
32547
|
);
|
|
32448
|
-
if (errorChecks.length > 0 &&
|
|
32548
|
+
if (errorChecks.length > 0 && existsSync36(ERROR_LOG_PATH)) {
|
|
32449
32549
|
try {
|
|
32450
|
-
const { writeFileSync:
|
|
32451
|
-
|
|
32550
|
+
const { writeFileSync: writeFileSync16 } = await import("fs");
|
|
32551
|
+
writeFileSync16(ERROR_LOG_PATH, "");
|
|
32452
32552
|
for (const c of errorChecks) {
|
|
32453
32553
|
c.status = "ok";
|
|
32454
32554
|
c.message = "cleared (log truncated)";
|
|
@@ -32574,15 +32674,15 @@ var logs_exports = {};
|
|
|
32574
32674
|
__export(logs_exports, {
|
|
32575
32675
|
logsCommand: () => logsCommand
|
|
32576
32676
|
});
|
|
32577
|
-
import { existsSync as
|
|
32677
|
+
import { existsSync as existsSync37, readFileSync as readFileSync26, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
32578
32678
|
async function logsCommand(opts) {
|
|
32579
32679
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
32580
|
-
if (!
|
|
32680
|
+
if (!existsSync37(logFile)) {
|
|
32581
32681
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
32582
32682
|
process.exit(1);
|
|
32583
32683
|
}
|
|
32584
32684
|
const maxLines = parseInt(opts.lines ?? "100", 10);
|
|
32585
|
-
const content =
|
|
32685
|
+
const content = readFileSync26(logFile, "utf-8");
|
|
32586
32686
|
const allLines = content.split("\n");
|
|
32587
32687
|
const tailLines = allLines.slice(-maxLines);
|
|
32588
32688
|
console.log(muted(` \u2500\u2500 ${logFile} (last ${tailLines.length} lines) \u2500\u2500`));
|
|
@@ -32592,7 +32692,7 @@ async function logsCommand(opts) {
|
|
|
32592
32692
|
let lastLength = content.length;
|
|
32593
32693
|
watchFile2(logFile, { interval: 500 }, () => {
|
|
32594
32694
|
try {
|
|
32595
|
-
const newContent =
|
|
32695
|
+
const newContent = readFileSync26(logFile, "utf-8");
|
|
32596
32696
|
if (newContent.length > lastLength) {
|
|
32597
32697
|
const newPart = newContent.slice(lastLength);
|
|
32598
32698
|
process.stdout.write(newPart);
|
|
@@ -32624,7 +32724,7 @@ __export(session_logs_exports, {
|
|
|
32624
32724
|
sessionLogsList: () => sessionLogsList,
|
|
32625
32725
|
sessionLogsTail: () => sessionLogsTail
|
|
32626
32726
|
});
|
|
32627
|
-
import { readFileSync as
|
|
32727
|
+
import { readFileSync as readFileSync27, watchFile as watchFile3, unwatchFile as unwatchFile3 } from "fs";
|
|
32628
32728
|
async function sessionLogsList(opts) {
|
|
32629
32729
|
const logs = listSessionLogs();
|
|
32630
32730
|
if (logs.length === 0) {
|
|
@@ -32681,12 +32781,12 @@ async function sessionLogsTail(opts) {
|
|
|
32681
32781
|
console.log(muted("\n Following... (Ctrl+C to stop)\n"));
|
|
32682
32782
|
let lastLength = 0;
|
|
32683
32783
|
try {
|
|
32684
|
-
lastLength =
|
|
32784
|
+
lastLength = readFileSync27(targetPath, "utf-8").length;
|
|
32685
32785
|
} catch {
|
|
32686
32786
|
}
|
|
32687
32787
|
watchFile3(targetPath, { interval: 500 }, () => {
|
|
32688
32788
|
try {
|
|
32689
|
-
const content =
|
|
32789
|
+
const content = readFileSync27(targetPath, "utf-8");
|
|
32690
32790
|
if (content.length > lastLength) {
|
|
32691
32791
|
process.stdout.write(content.slice(lastLength));
|
|
32692
32792
|
lastLength = content.length;
|
|
@@ -32730,11 +32830,11 @@ __export(gemini_exports, {
|
|
|
32730
32830
|
geminiReorder: () => geminiReorder,
|
|
32731
32831
|
geminiRotation: () => geminiRotation
|
|
32732
32832
|
});
|
|
32733
|
-
import { existsSync as
|
|
32734
|
-
import { join as
|
|
32833
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync14, writeFileSync as writeFileSync13, readFileSync as readFileSync28, chmodSync } from "fs";
|
|
32834
|
+
import { join as join37 } from "path";
|
|
32735
32835
|
import { createInterface as createInterface8 } from "readline";
|
|
32736
32836
|
function requireDb() {
|
|
32737
|
-
if (!
|
|
32837
|
+
if (!existsSync39(DB_PATH)) {
|
|
32738
32838
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
32739
32839
|
process.exit(1);
|
|
32740
32840
|
}
|
|
@@ -32759,9 +32859,9 @@ async function resolveSlotId(idOrLabel) {
|
|
|
32759
32859
|
function resolveOAuthEmail(configHome) {
|
|
32760
32860
|
if (!configHome) return null;
|
|
32761
32861
|
try {
|
|
32762
|
-
const accountsPath =
|
|
32763
|
-
if (!
|
|
32764
|
-
const accounts = JSON.parse(
|
|
32862
|
+
const accountsPath = join37(configHome, ".gemini", "google_accounts.json");
|
|
32863
|
+
if (!existsSync39(accountsPath)) return null;
|
|
32864
|
+
const accounts = JSON.parse(readFileSync28(accountsPath, "utf-8"));
|
|
32765
32865
|
return accounts.active || null;
|
|
32766
32866
|
} catch {
|
|
32767
32867
|
return null;
|
|
@@ -32843,14 +32943,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
32843
32943
|
}
|
|
32844
32944
|
async function geminiAddAccount(globalOpts, opts) {
|
|
32845
32945
|
await requireWriteDb();
|
|
32846
|
-
const slotsDir =
|
|
32847
|
-
if (!
|
|
32946
|
+
const slotsDir = join37(CC_CLAW_HOME, "gemini-slots");
|
|
32947
|
+
if (!existsSync39(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
32848
32948
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
32849
32949
|
const tempId = Date.now();
|
|
32850
|
-
const slotDir =
|
|
32950
|
+
const slotDir = join37(slotsDir, `slot-${tempId}`);
|
|
32851
32951
|
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
32852
|
-
mkdirSync14(
|
|
32853
|
-
|
|
32952
|
+
mkdirSync14(join37(slotDir, ".gemini"), { recursive: true });
|
|
32953
|
+
writeFileSync13(join37(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
32854
32954
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
32855
32955
|
}, null, 2));
|
|
32856
32956
|
console.log("");
|
|
@@ -32867,8 +32967,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
32867
32967
|
});
|
|
32868
32968
|
} catch {
|
|
32869
32969
|
}
|
|
32870
|
-
const oauthPath =
|
|
32871
|
-
if (!
|
|
32970
|
+
const oauthPath = join37(slotDir, ".gemini", "oauth_creds.json");
|
|
32971
|
+
if (!existsSync39(oauthPath)) {
|
|
32872
32972
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
32873
32973
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
32874
32974
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -32876,7 +32976,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
32876
32976
|
}
|
|
32877
32977
|
let accountEmail = "unknown";
|
|
32878
32978
|
try {
|
|
32879
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
32979
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join37(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
32880
32980
|
accountEmail = accounts.active || accountEmail;
|
|
32881
32981
|
} catch {
|
|
32882
32982
|
}
|
|
@@ -32987,10 +33087,10 @@ async function geminiRelogin(globalOpts, idOrLabel) {
|
|
|
32987
33087
|
outputError("NO_CONFIG", `Slot "${idOrLabel}" has no config directory \u2014 cannot re-login.`);
|
|
32988
33088
|
return;
|
|
32989
33089
|
}
|
|
32990
|
-
const settingsPath =
|
|
32991
|
-
if (!
|
|
32992
|
-
mkdirSync14(
|
|
32993
|
-
|
|
33090
|
+
const settingsPath = join37(slot.configHome, ".gemini", "settings.json");
|
|
33091
|
+
if (!existsSync39(settingsPath)) {
|
|
33092
|
+
mkdirSync14(join37(slot.configHome, ".gemini"), { recursive: true });
|
|
33093
|
+
writeFileSync13(settingsPath, JSON.stringify({
|
|
32994
33094
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
32995
33095
|
}, null, 2));
|
|
32996
33096
|
}
|
|
@@ -33013,8 +33113,8 @@ async function geminiRelogin(globalOpts, idOrLabel) {
|
|
|
33013
33113
|
});
|
|
33014
33114
|
} catch {
|
|
33015
33115
|
}
|
|
33016
|
-
const oauthPath =
|
|
33017
|
-
if (!
|
|
33116
|
+
const oauthPath = join37(slot.configHome, ".gemini", "oauth_creds.json");
|
|
33117
|
+
if (!existsSync39(oauthPath)) {
|
|
33018
33118
|
console.log(error2("\n Re-login failed \u2014 no OAuth credentials found."));
|
|
33019
33119
|
console.log(` Try again: cc-claw gemini re-login ${idOrLabel}
|
|
33020
33120
|
`);
|
|
@@ -33024,7 +33124,7 @@ async function geminiRelogin(globalOpts, idOrLabel) {
|
|
|
33024
33124
|
setGeminiSlotEnabled2(slotId, true);
|
|
33025
33125
|
let accountEmail = slot.label;
|
|
33026
33126
|
try {
|
|
33027
|
-
const accounts = JSON.parse(
|
|
33127
|
+
const accounts = JSON.parse(readFileSync28(join37(slot.configHome, ".gemini", "google_accounts.json"), "utf-8"));
|
|
33028
33128
|
if (accounts.active) accountEmail = accounts.active;
|
|
33029
33129
|
} catch {
|
|
33030
33130
|
}
|
|
@@ -33083,11 +33183,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
33083
33183
|
makeReorder: () => makeReorder,
|
|
33084
33184
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
33085
33185
|
});
|
|
33086
|
-
import { existsSync as
|
|
33087
|
-
import { join as
|
|
33186
|
+
import { existsSync as existsSync40, mkdirSync as mkdirSync15, readFileSync as readFileSync29 } from "fs";
|
|
33187
|
+
import { join as join38 } from "path";
|
|
33088
33188
|
import { createInterface as createInterface9 } from "readline";
|
|
33089
33189
|
function requireDb2() {
|
|
33090
|
-
if (!
|
|
33190
|
+
if (!existsSync40(DB_PATH)) {
|
|
33091
33191
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
33092
33192
|
process.exit(1);
|
|
33093
33193
|
}
|
|
@@ -33176,10 +33276,10 @@ function makeAddAccount(backend2, displayName) {
|
|
|
33176
33276
|
process.exit(1);
|
|
33177
33277
|
}
|
|
33178
33278
|
await requireWriteDb2();
|
|
33179
|
-
const slotsDir =
|
|
33180
|
-
if (!
|
|
33279
|
+
const slotsDir = join38(CC_CLAW_HOME, config2.slotsSubdir);
|
|
33280
|
+
if (!existsSync40(slotsDir)) mkdirSync15(slotsDir, { recursive: true });
|
|
33181
33281
|
const tempId = Date.now();
|
|
33182
|
-
const slotDir =
|
|
33282
|
+
const slotDir = join38(slotsDir, `slot-${tempId}`);
|
|
33183
33283
|
mkdirSync15(slotDir, { recursive: true, mode: 448 });
|
|
33184
33284
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
33185
33285
|
console.log("");
|
|
@@ -33430,22 +33530,22 @@ var init_backend_cmd_factory = __esm({
|
|
|
33430
33530
|
envValue: (slotDir) => slotDir,
|
|
33431
33531
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
33432
33532
|
preSetup: (slotDir) => {
|
|
33433
|
-
mkdirSync15(
|
|
33533
|
+
mkdirSync15(join38(slotDir, ".claude"), { recursive: true });
|
|
33434
33534
|
},
|
|
33435
33535
|
verifyCredentials: (slotDir) => {
|
|
33436
|
-
const claudeJson =
|
|
33437
|
-
const claudeJsonNested =
|
|
33438
|
-
if (
|
|
33536
|
+
const claudeJson = join38(slotDir, ".claude.json");
|
|
33537
|
+
const claudeJsonNested = join38(slotDir, ".claude", ".claude.json");
|
|
33538
|
+
if (existsSync40(claudeJson)) {
|
|
33439
33539
|
try {
|
|
33440
|
-
const data = JSON.parse(
|
|
33540
|
+
const data = JSON.parse(readFileSync29(claudeJson, "utf-8"));
|
|
33441
33541
|
return Boolean(data.oauthAccount);
|
|
33442
33542
|
} catch {
|
|
33443
33543
|
return false;
|
|
33444
33544
|
}
|
|
33445
33545
|
}
|
|
33446
|
-
if (
|
|
33546
|
+
if (existsSync40(claudeJsonNested)) {
|
|
33447
33547
|
try {
|
|
33448
|
-
const data = JSON.parse(
|
|
33548
|
+
const data = JSON.parse(readFileSync29(claudeJsonNested, "utf-8"));
|
|
33449
33549
|
return Boolean(data.oauthAccount);
|
|
33450
33550
|
} catch {
|
|
33451
33551
|
return false;
|
|
@@ -33466,9 +33566,9 @@ var init_backend_cmd_factory = __esm({
|
|
|
33466
33566
|
} catch {
|
|
33467
33567
|
}
|
|
33468
33568
|
try {
|
|
33469
|
-
const claudeJson =
|
|
33470
|
-
if (
|
|
33471
|
-
const data = JSON.parse(
|
|
33569
|
+
const claudeJson = join38(slotDir, ".claude.json");
|
|
33570
|
+
if (existsSync40(claudeJson)) {
|
|
33571
|
+
const data = JSON.parse(readFileSync29(claudeJson, "utf-8"));
|
|
33472
33572
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
33473
33573
|
}
|
|
33474
33574
|
} catch {
|
|
@@ -33483,11 +33583,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
33483
33583
|
envValue: (slotDir) => slotDir,
|
|
33484
33584
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
33485
33585
|
verifyCredentials: (slotDir) => {
|
|
33486
|
-
return
|
|
33586
|
+
return existsSync40(join38(slotDir, "auth.json"));
|
|
33487
33587
|
},
|
|
33488
33588
|
extractLabel: (slotDir) => {
|
|
33489
33589
|
try {
|
|
33490
|
-
const authData = JSON.parse(
|
|
33590
|
+
const authData = JSON.parse(readFileSync29(join38(slotDir, "auth.json"), "utf-8"));
|
|
33491
33591
|
if (authData.email) return authData.email;
|
|
33492
33592
|
if (authData.account_name) return authData.account_name;
|
|
33493
33593
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -33511,9 +33611,9 @@ __export(ollama_exports3, {
|
|
|
33511
33611
|
ollamaRemove: () => ollamaRemove,
|
|
33512
33612
|
ollamaTest: () => ollamaTest
|
|
33513
33613
|
});
|
|
33514
|
-
import { existsSync as
|
|
33614
|
+
import { existsSync as existsSync41 } from "fs";
|
|
33515
33615
|
function requireDb3() {
|
|
33516
|
-
if (!
|
|
33616
|
+
if (!existsSync41(DB_PATH)) {
|
|
33517
33617
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
33518
33618
|
process.exit(1);
|
|
33519
33619
|
}
|
|
@@ -33772,12 +33872,12 @@ __export(backend_exports, {
|
|
|
33772
33872
|
backendList: () => backendList,
|
|
33773
33873
|
backendSet: () => backendSet
|
|
33774
33874
|
});
|
|
33775
|
-
import { existsSync as
|
|
33875
|
+
import { existsSync as existsSync42 } from "fs";
|
|
33776
33876
|
async function backendList(globalOpts) {
|
|
33777
33877
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
33778
33878
|
const chatId = resolveChatId2(globalOpts);
|
|
33779
33879
|
let activeBackend = null;
|
|
33780
|
-
if (
|
|
33880
|
+
if (existsSync42(DB_PATH)) {
|
|
33781
33881
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
33782
33882
|
const readDb = openDatabaseReadOnly2();
|
|
33783
33883
|
try {
|
|
@@ -33808,7 +33908,7 @@ async function backendList(globalOpts) {
|
|
|
33808
33908
|
}
|
|
33809
33909
|
async function backendGet(globalOpts) {
|
|
33810
33910
|
const chatId = resolveChatId2(globalOpts);
|
|
33811
|
-
if (!
|
|
33911
|
+
if (!existsSync42(DB_PATH)) {
|
|
33812
33912
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
33813
33913
|
process.exit(1);
|
|
33814
33914
|
}
|
|
@@ -33852,13 +33952,13 @@ __export(model_exports, {
|
|
|
33852
33952
|
modelList: () => modelList,
|
|
33853
33953
|
modelSet: () => modelSet
|
|
33854
33954
|
});
|
|
33855
|
-
import { existsSync as
|
|
33955
|
+
import { existsSync as existsSync43 } from "fs";
|
|
33856
33956
|
async function modelList(globalOpts) {
|
|
33857
33957
|
const chatId = resolveChatId2(globalOpts);
|
|
33858
33958
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
33859
33959
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
33860
33960
|
let backendId = "claude";
|
|
33861
|
-
if (
|
|
33961
|
+
if (existsSync43(DB_PATH)) {
|
|
33862
33962
|
const readDb = openDatabaseReadOnly2();
|
|
33863
33963
|
try {
|
|
33864
33964
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -33891,7 +33991,7 @@ async function modelList(globalOpts) {
|
|
|
33891
33991
|
}
|
|
33892
33992
|
async function modelGet(globalOpts) {
|
|
33893
33993
|
const chatId = resolveChatId2(globalOpts);
|
|
33894
|
-
if (!
|
|
33994
|
+
if (!existsSync43(DB_PATH)) {
|
|
33895
33995
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
33896
33996
|
process.exit(1);
|
|
33897
33997
|
}
|
|
@@ -33935,9 +34035,9 @@ __export(memory_exports2, {
|
|
|
33935
34035
|
memoryList: () => memoryList,
|
|
33936
34036
|
memorySearch: () => memorySearch
|
|
33937
34037
|
});
|
|
33938
|
-
import { existsSync as
|
|
34038
|
+
import { existsSync as existsSync44 } from "fs";
|
|
33939
34039
|
async function memoryList(globalOpts) {
|
|
33940
|
-
if (!
|
|
34040
|
+
if (!existsSync44(DB_PATH)) {
|
|
33941
34041
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
33942
34042
|
process.exit(1);
|
|
33943
34043
|
}
|
|
@@ -33961,7 +34061,7 @@ async function memoryList(globalOpts) {
|
|
|
33961
34061
|
});
|
|
33962
34062
|
}
|
|
33963
34063
|
async function memorySearch(globalOpts, query) {
|
|
33964
|
-
if (!
|
|
34064
|
+
if (!existsSync44(DB_PATH)) {
|
|
33965
34065
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
33966
34066
|
process.exit(1);
|
|
33967
34067
|
}
|
|
@@ -33983,7 +34083,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
33983
34083
|
});
|
|
33984
34084
|
}
|
|
33985
34085
|
async function memoryHistory(globalOpts, opts) {
|
|
33986
|
-
if (!
|
|
34086
|
+
if (!existsSync44(DB_PATH)) {
|
|
33987
34087
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
33988
34088
|
process.exit(1);
|
|
33989
34089
|
}
|
|
@@ -34031,7 +34131,7 @@ __export(cron_exports2, {
|
|
|
34031
34131
|
cronList: () => cronList,
|
|
34032
34132
|
cronRuns: () => cronRuns
|
|
34033
34133
|
});
|
|
34034
|
-
import { existsSync as
|
|
34134
|
+
import { existsSync as existsSync45 } from "fs";
|
|
34035
34135
|
function parseFallbacks(raw) {
|
|
34036
34136
|
return raw.slice(0, 3).map((f) => {
|
|
34037
34137
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -34052,7 +34152,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
34052
34152
|
return val;
|
|
34053
34153
|
}
|
|
34054
34154
|
async function cronList(globalOpts) {
|
|
34055
|
-
if (!
|
|
34155
|
+
if (!existsSync45(DB_PATH)) {
|
|
34056
34156
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34057
34157
|
process.exit(1);
|
|
34058
34158
|
}
|
|
@@ -34090,7 +34190,7 @@ async function cronList(globalOpts) {
|
|
|
34090
34190
|
});
|
|
34091
34191
|
}
|
|
34092
34192
|
async function cronHealth(globalOpts) {
|
|
34093
|
-
if (!
|
|
34193
|
+
if (!existsSync45(DB_PATH)) {
|
|
34094
34194
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34095
34195
|
process.exit(1);
|
|
34096
34196
|
}
|
|
@@ -34274,7 +34374,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
34274
34374
|
}
|
|
34275
34375
|
}
|
|
34276
34376
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
34277
|
-
if (!
|
|
34377
|
+
if (!existsSync45(DB_PATH)) {
|
|
34278
34378
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34279
34379
|
process.exit(1);
|
|
34280
34380
|
}
|
|
@@ -34321,9 +34421,9 @@ __export(agents_exports, {
|
|
|
34321
34421
|
runnersList: () => runnersList,
|
|
34322
34422
|
tasksList: () => tasksList
|
|
34323
34423
|
});
|
|
34324
|
-
import { existsSync as
|
|
34424
|
+
import { existsSync as existsSync46 } from "fs";
|
|
34325
34425
|
async function agentsList(globalOpts) {
|
|
34326
|
-
if (!
|
|
34426
|
+
if (!existsSync46(DB_PATH)) {
|
|
34327
34427
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34328
34428
|
process.exit(1);
|
|
34329
34429
|
}
|
|
@@ -34354,7 +34454,7 @@ async function agentsList(globalOpts) {
|
|
|
34354
34454
|
});
|
|
34355
34455
|
}
|
|
34356
34456
|
async function tasksList(globalOpts) {
|
|
34357
|
-
if (!
|
|
34457
|
+
if (!existsSync46(DB_PATH)) {
|
|
34358
34458
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34359
34459
|
process.exit(1);
|
|
34360
34460
|
}
|
|
@@ -34482,10 +34582,10 @@ __export(db_exports, {
|
|
|
34482
34582
|
dbPath: () => dbPath,
|
|
34483
34583
|
dbStats: () => dbStats
|
|
34484
34584
|
});
|
|
34485
|
-
import { existsSync as
|
|
34585
|
+
import { existsSync as existsSync47, statSync as statSync10, copyFileSync as copyFileSync4, mkdirSync as mkdirSync16 } from "fs";
|
|
34486
34586
|
import { dirname as dirname7 } from "path";
|
|
34487
34587
|
async function dbStats(globalOpts) {
|
|
34488
|
-
if (!
|
|
34588
|
+
if (!existsSync47(DB_PATH)) {
|
|
34489
34589
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
34490
34590
|
process.exit(1);
|
|
34491
34591
|
}
|
|
@@ -34493,7 +34593,7 @@ async function dbStats(globalOpts) {
|
|
|
34493
34593
|
const readDb = openDatabaseReadOnly2();
|
|
34494
34594
|
const mainSize = statSync10(DB_PATH).size;
|
|
34495
34595
|
const walPath = DB_PATH + "-wal";
|
|
34496
|
-
const walSize =
|
|
34596
|
+
const walSize = existsSync47(walPath) ? statSync10(walPath).size : 0;
|
|
34497
34597
|
const tableNames = readDb.prepare(
|
|
34498
34598
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
34499
34599
|
).all();
|
|
@@ -34527,7 +34627,7 @@ async function dbPath(globalOpts) {
|
|
|
34527
34627
|
output({ path: DB_PATH }, (d) => d.path);
|
|
34528
34628
|
}
|
|
34529
34629
|
async function dbBackup(globalOpts, destPath) {
|
|
34530
|
-
if (!
|
|
34630
|
+
if (!existsSync47(DB_PATH)) {
|
|
34531
34631
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
34532
34632
|
process.exit(1);
|
|
34533
34633
|
}
|
|
@@ -34536,7 +34636,7 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
34536
34636
|
mkdirSync16(dirname7(dest), { recursive: true });
|
|
34537
34637
|
copyFileSync4(DB_PATH, dest);
|
|
34538
34638
|
const walPath = DB_PATH + "-wal";
|
|
34539
|
-
if (
|
|
34639
|
+
if (existsSync47(walPath)) copyFileSync4(walPath, dest + "-wal");
|
|
34540
34640
|
output({ path: dest, sizeBytes: statSync10(dest).size }, (d) => {
|
|
34541
34641
|
const b = d;
|
|
34542
34642
|
return `
|
|
@@ -34565,9 +34665,9 @@ __export(usage_exports, {
|
|
|
34565
34665
|
usageCost: () => usageCost,
|
|
34566
34666
|
usageTokens: () => usageTokens
|
|
34567
34667
|
});
|
|
34568
|
-
import { existsSync as
|
|
34668
|
+
import { existsSync as existsSync48 } from "fs";
|
|
34569
34669
|
function ensureDb() {
|
|
34570
|
-
if (!
|
|
34670
|
+
if (!existsSync48(DB_PATH)) {
|
|
34571
34671
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
34572
34672
|
process.exit(1);
|
|
34573
34673
|
}
|
|
@@ -34757,9 +34857,9 @@ __export(config_exports2, {
|
|
|
34757
34857
|
configList: () => configList,
|
|
34758
34858
|
configSet: () => configSet
|
|
34759
34859
|
});
|
|
34760
|
-
import { existsSync as
|
|
34860
|
+
import { existsSync as existsSync49, readFileSync as readFileSync30 } from "fs";
|
|
34761
34861
|
async function configList(globalOpts) {
|
|
34762
|
-
if (!
|
|
34862
|
+
if (!existsSync49(DB_PATH)) {
|
|
34763
34863
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34764
34864
|
process.exit(1);
|
|
34765
34865
|
}
|
|
@@ -34793,7 +34893,7 @@ async function configGet(globalOpts, key) {
|
|
|
34793
34893
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
34794
34894
|
process.exit(1);
|
|
34795
34895
|
}
|
|
34796
|
-
if (!
|
|
34896
|
+
if (!existsSync49(DB_PATH)) {
|
|
34797
34897
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34798
34898
|
process.exit(1);
|
|
34799
34899
|
}
|
|
@@ -34839,11 +34939,11 @@ async function configSet(globalOpts, key, value) {
|
|
|
34839
34939
|
}
|
|
34840
34940
|
}
|
|
34841
34941
|
async function configEnv(_globalOpts) {
|
|
34842
|
-
if (!
|
|
34942
|
+
if (!existsSync49(ENV_PATH)) {
|
|
34843
34943
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
34844
34944
|
process.exit(1);
|
|
34845
34945
|
}
|
|
34846
|
-
const content =
|
|
34946
|
+
const content = readFileSync30(ENV_PATH, "utf-8");
|
|
34847
34947
|
const entries = {};
|
|
34848
34948
|
const secretPatterns = /TOKEN|KEY|SECRET|PASSWORD|CREDENTIALS/i;
|
|
34849
34949
|
for (const line of content.split("\n")) {
|
|
@@ -34893,9 +34993,9 @@ __export(session_exports, {
|
|
|
34893
34993
|
sessionGet: () => sessionGet,
|
|
34894
34994
|
sessionNew: () => sessionNew
|
|
34895
34995
|
});
|
|
34896
|
-
import { existsSync as
|
|
34996
|
+
import { existsSync as existsSync50 } from "fs";
|
|
34897
34997
|
async function sessionGet(globalOpts) {
|
|
34898
|
-
if (!
|
|
34998
|
+
if (!existsSync50(DB_PATH)) {
|
|
34899
34999
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34900
35000
|
process.exit(1);
|
|
34901
35001
|
}
|
|
@@ -34956,9 +35056,9 @@ __export(permissions_exports, {
|
|
|
34956
35056
|
verboseGet: () => verboseGet,
|
|
34957
35057
|
verboseSet: () => verboseSet
|
|
34958
35058
|
});
|
|
34959
|
-
import { existsSync as
|
|
35059
|
+
import { existsSync as existsSync51 } from "fs";
|
|
34960
35060
|
function ensureDb2() {
|
|
34961
|
-
if (!
|
|
35061
|
+
if (!existsSync51(DB_PATH)) {
|
|
34962
35062
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
34963
35063
|
process.exit(1);
|
|
34964
35064
|
}
|
|
@@ -35105,9 +35205,9 @@ __export(cwd_exports, {
|
|
|
35105
35205
|
cwdGet: () => cwdGet,
|
|
35106
35206
|
cwdSet: () => cwdSet
|
|
35107
35207
|
});
|
|
35108
|
-
import { existsSync as
|
|
35208
|
+
import { existsSync as existsSync52 } from "fs";
|
|
35109
35209
|
async function cwdGet(globalOpts) {
|
|
35110
|
-
if (!
|
|
35210
|
+
if (!existsSync52(DB_PATH)) {
|
|
35111
35211
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35112
35212
|
process.exit(1);
|
|
35113
35213
|
}
|
|
@@ -35169,9 +35269,9 @@ __export(voice_exports, {
|
|
|
35169
35269
|
voiceGet: () => voiceGet,
|
|
35170
35270
|
voiceSet: () => voiceSet
|
|
35171
35271
|
});
|
|
35172
|
-
import { existsSync as
|
|
35272
|
+
import { existsSync as existsSync53 } from "fs";
|
|
35173
35273
|
async function voiceGet(globalOpts) {
|
|
35174
|
-
if (!
|
|
35274
|
+
if (!existsSync53(DB_PATH)) {
|
|
35175
35275
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35176
35276
|
process.exit(1);
|
|
35177
35277
|
}
|
|
@@ -35220,9 +35320,9 @@ __export(heartbeat_exports2, {
|
|
|
35220
35320
|
heartbeatGet: () => heartbeatGet,
|
|
35221
35321
|
heartbeatSet: () => heartbeatSet
|
|
35222
35322
|
});
|
|
35223
|
-
import { existsSync as
|
|
35323
|
+
import { existsSync as existsSync54 } from "fs";
|
|
35224
35324
|
async function heartbeatGet(globalOpts) {
|
|
35225
|
-
if (!
|
|
35325
|
+
if (!existsSync54(DB_PATH)) {
|
|
35226
35326
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35227
35327
|
process.exit(1);
|
|
35228
35328
|
}
|
|
@@ -35433,9 +35533,9 @@ __export(summarizer_exports, {
|
|
|
35433
35533
|
summarizerGet: () => summarizerGet,
|
|
35434
35534
|
summarizerSet: () => summarizerSet
|
|
35435
35535
|
});
|
|
35436
|
-
import { existsSync as
|
|
35536
|
+
import { existsSync as existsSync55 } from "fs";
|
|
35437
35537
|
async function summarizerGet(globalOpts) {
|
|
35438
|
-
if (!
|
|
35538
|
+
if (!existsSync55(DB_PATH)) {
|
|
35439
35539
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35440
35540
|
process.exit(1);
|
|
35441
35541
|
}
|
|
@@ -35479,9 +35579,9 @@ __export(thinking_exports, {
|
|
|
35479
35579
|
thinkingGet: () => thinkingGet,
|
|
35480
35580
|
thinkingSet: () => thinkingSet
|
|
35481
35581
|
});
|
|
35482
|
-
import { existsSync as
|
|
35582
|
+
import { existsSync as existsSync56 } from "fs";
|
|
35483
35583
|
async function thinkingGet(globalOpts) {
|
|
35484
|
-
if (!
|
|
35584
|
+
if (!existsSync56(DB_PATH)) {
|
|
35485
35585
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35486
35586
|
process.exit(1);
|
|
35487
35587
|
}
|
|
@@ -35525,9 +35625,9 @@ __export(chats_exports, {
|
|
|
35525
35625
|
chatsList: () => chatsList,
|
|
35526
35626
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
35527
35627
|
});
|
|
35528
|
-
import { existsSync as
|
|
35628
|
+
import { existsSync as existsSync57 } from "fs";
|
|
35529
35629
|
async function chatsList(_globalOpts) {
|
|
35530
|
-
if (!
|
|
35630
|
+
if (!existsSync57(DB_PATH)) {
|
|
35531
35631
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35532
35632
|
process.exit(1);
|
|
35533
35633
|
}
|
|
@@ -35655,9 +35755,9 @@ var mcps_exports2 = {};
|
|
|
35655
35755
|
__export(mcps_exports2, {
|
|
35656
35756
|
mcpsList: () => mcpsList
|
|
35657
35757
|
});
|
|
35658
|
-
import { existsSync as
|
|
35758
|
+
import { existsSync as existsSync58 } from "fs";
|
|
35659
35759
|
async function mcpsList(_globalOpts) {
|
|
35660
|
-
if (!
|
|
35760
|
+
if (!existsSync58(DB_PATH)) {
|
|
35661
35761
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
35662
35762
|
process.exit(1);
|
|
35663
35763
|
}
|
|
@@ -35694,11 +35794,11 @@ __export(chat_exports2, {
|
|
|
35694
35794
|
chatSend: () => chatSend
|
|
35695
35795
|
});
|
|
35696
35796
|
import { request as httpRequest2 } from "http";
|
|
35697
|
-
import { readFileSync as
|
|
35797
|
+
import { readFileSync as readFileSync31, existsSync as existsSync59 } from "fs";
|
|
35698
35798
|
function getToken2() {
|
|
35699
35799
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
35700
35800
|
try {
|
|
35701
|
-
if (
|
|
35801
|
+
if (existsSync59(TOKEN_PATH2)) return readFileSync31(TOKEN_PATH2, "utf-8").trim();
|
|
35702
35802
|
} catch {
|
|
35703
35803
|
}
|
|
35704
35804
|
return null;
|
|
@@ -36185,8 +36285,8 @@ var completion_exports = {};
|
|
|
36185
36285
|
__export(completion_exports, {
|
|
36186
36286
|
completionCommand: () => completionCommand
|
|
36187
36287
|
});
|
|
36188
|
-
import { writeFileSync as
|
|
36189
|
-
import { join as
|
|
36288
|
+
import { writeFileSync as writeFileSync14, mkdirSync as mkdirSync17 } from "fs";
|
|
36289
|
+
import { join as join39 } from "path";
|
|
36190
36290
|
import { homedir as homedir11 } from "os";
|
|
36191
36291
|
async function completionCommand(opts) {
|
|
36192
36292
|
const shell = opts.shell ?? detectShell();
|
|
@@ -36202,11 +36302,11 @@ async function completionCommand(opts) {
|
|
|
36202
36302
|
process.exit(1);
|
|
36203
36303
|
}
|
|
36204
36304
|
if (opts.install) {
|
|
36205
|
-
const dir =
|
|
36305
|
+
const dir = join39(homedir11(), ".config", "cc-claw", "completions");
|
|
36206
36306
|
mkdirSync17(dir, { recursive: true });
|
|
36207
36307
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
36208
|
-
const filepath =
|
|
36209
|
-
|
|
36308
|
+
const filepath = join39(dir, filename);
|
|
36309
|
+
writeFileSync14(filepath, script, "utf-8");
|
|
36210
36310
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
36211
36311
|
`);
|
|
36212
36312
|
if (shell === "zsh") {
|
|
@@ -36378,9 +36478,9 @@ __export(evolve_exports2, {
|
|
|
36378
36478
|
evolveStatus: () => evolveStatus,
|
|
36379
36479
|
evolveUndo: () => evolveUndo
|
|
36380
36480
|
});
|
|
36381
|
-
import { existsSync as
|
|
36481
|
+
import { existsSync as existsSync60 } from "fs";
|
|
36382
36482
|
function ensureDb3() {
|
|
36383
|
-
if (!
|
|
36483
|
+
if (!existsSync60(DB_PATH)) {
|
|
36384
36484
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
36385
36485
|
process.exit(1);
|
|
36386
36486
|
}
|
|
@@ -36854,10 +36954,10 @@ var init_optimize2 = __esm({
|
|
|
36854
36954
|
|
|
36855
36955
|
// src/setup.ts
|
|
36856
36956
|
var setup_exports = {};
|
|
36857
|
-
import { existsSync as
|
|
36858
|
-
import { execFileSync as
|
|
36957
|
+
import { existsSync as existsSync61, writeFileSync as writeFileSync15, readFileSync as readFileSync32, copyFileSync as copyFileSync5, mkdirSync as mkdirSync18, statSync as statSync11 } from "fs";
|
|
36958
|
+
import { execFileSync as execFileSync7 } from "child_process";
|
|
36859
36959
|
import { createInterface as createInterface11 } from "readline";
|
|
36860
|
-
import { join as
|
|
36960
|
+
import { join as join40 } from "path";
|
|
36861
36961
|
function divider2() {
|
|
36862
36962
|
console.log(dim("\u2500".repeat(55)));
|
|
36863
36963
|
}
|
|
@@ -36919,7 +37019,7 @@ async function setup() {
|
|
|
36919
37019
|
let foundAnyBackend = false;
|
|
36920
37020
|
for (const bk of backends) {
|
|
36921
37021
|
try {
|
|
36922
|
-
const path =
|
|
37022
|
+
const path = execFileSync7("which", [bk.cmd], { encoding: "utf-8" }).trim();
|
|
36923
37023
|
console.log(green(` ${bk.name} CLI found: ${path}`));
|
|
36924
37024
|
foundAnyBackend = true;
|
|
36925
37025
|
} catch {
|
|
@@ -36932,21 +37032,21 @@ async function setup() {
|
|
|
36932
37032
|
}
|
|
36933
37033
|
console.log("");
|
|
36934
37034
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
36935
|
-
if (!
|
|
37035
|
+
if (!existsSync61(dir)) mkdirSync18(dir, { recursive: true });
|
|
36936
37036
|
}
|
|
36937
37037
|
const env = {};
|
|
36938
|
-
const envSource =
|
|
37038
|
+
const envSource = existsSync61(ENV_PATH) ? ENV_PATH : existsSync61(".env") ? ".env" : null;
|
|
36939
37039
|
if (envSource) {
|
|
36940
37040
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
36941
37041
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
36942
|
-
const existing =
|
|
37042
|
+
const existing = readFileSync32(envSource, "utf-8");
|
|
36943
37043
|
for (const line of existing.split("\n")) {
|
|
36944
37044
|
const match = line.match(/^([^#=]+)=(.*)$/);
|
|
36945
37045
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
36946
37046
|
}
|
|
36947
37047
|
}
|
|
36948
|
-
const cwdDb =
|
|
36949
|
-
if (
|
|
37048
|
+
const cwdDb = join40(process.cwd(), "cc-claw.db");
|
|
37049
|
+
if (existsSync61(cwdDb) && !existsSync61(DB_PATH)) {
|
|
36950
37050
|
const { size } = statSync11(cwdDb);
|
|
36951
37051
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
36952
37052
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
@@ -37193,7 +37293,7 @@ async function setup() {
|
|
|
37193
37293
|
envLines.push("", "# Video Analysis", `GEMINI_API_KEY=${env.GEMINI_API_KEY}`);
|
|
37194
37294
|
}
|
|
37195
37295
|
const envContent = envLines.join("\n") + "\n";
|
|
37196
|
-
|
|
37296
|
+
writeFileSync15(ENV_PATH, envContent, { mode: 384 });
|
|
37197
37297
|
console.log(green(` Config saved to ${ENV_PATH} (permissions: owner-only)`));
|
|
37198
37298
|
header(6, TOTAL_STEPS, "Run on Startup (Daemon)");
|
|
37199
37299
|
console.log(" CC-Claw can run automatically in the background, starting");
|
|
@@ -37871,8 +37971,8 @@ async function run(argv = process.argv) {
|
|
|
37871
37971
|
if (argv.includes("--version") || argv.includes("-V")) {
|
|
37872
37972
|
console.log(VERSION);
|
|
37873
37973
|
try {
|
|
37874
|
-
const { execFileSync:
|
|
37875
|
-
const latest =
|
|
37974
|
+
const { execFileSync: execFileSync8 } = await import("child_process");
|
|
37975
|
+
const latest = execFileSync8("npm", ["view", "cc-claw", "version"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
37876
37976
|
if (latest && latest !== VERSION) {
|
|
37877
37977
|
console.log(`
|
|
37878
37978
|
Update available: v${latest} (current: v${VERSION})`);
|