cc-claw 0.16.3 → 0.17.0
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 +887 -372
- 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.
|
|
36
|
+
VERSION = true ? "0.17.0" : (() => {
|
|
37
37
|
try {
|
|
38
38
|
return JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
39
39
|
} catch {
|
|
@@ -1729,6 +1729,12 @@ function initSchema(db3) {
|
|
|
1729
1729
|
mode TEXT NOT NULL DEFAULT 'auto'
|
|
1730
1730
|
);
|
|
1731
1731
|
`);
|
|
1732
|
+
db3.exec(`
|
|
1733
|
+
CREATE TABLE IF NOT EXISTS chat_exec_mode (
|
|
1734
|
+
chat_id TEXT PRIMARY KEY,
|
|
1735
|
+
mode TEXT NOT NULL DEFAULT 'approved'
|
|
1736
|
+
);
|
|
1737
|
+
`);
|
|
1732
1738
|
db3.exec(`
|
|
1733
1739
|
CREATE TABLE IF NOT EXISTS backend_credentials (
|
|
1734
1740
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -2643,6 +2649,22 @@ function setAgentMode(chatId, mode) {
|
|
|
2643
2649
|
function clearAgentMode(chatId) {
|
|
2644
2650
|
getDb().prepare("DELETE FROM chat_agent_mode WHERE chat_id = ?").run(chatId);
|
|
2645
2651
|
}
|
|
2652
|
+
function getExecMode(chatId) {
|
|
2653
|
+
const row = getDb().prepare(
|
|
2654
|
+
"SELECT mode FROM chat_exec_mode WHERE chat_id = ?"
|
|
2655
|
+
).get(chatId);
|
|
2656
|
+
return row?.mode ?? "approved";
|
|
2657
|
+
}
|
|
2658
|
+
function setExecMode(chatId, mode) {
|
|
2659
|
+
getDb().prepare(`
|
|
2660
|
+
INSERT INTO chat_exec_mode (chat_id, mode)
|
|
2661
|
+
VALUES (?, ?)
|
|
2662
|
+
ON CONFLICT(chat_id) DO UPDATE SET mode = excluded.mode
|
|
2663
|
+
`).run(chatId, mode);
|
|
2664
|
+
}
|
|
2665
|
+
function clearExecMode(chatId) {
|
|
2666
|
+
getDb().prepare("DELETE FROM chat_exec_mode WHERE chat_id = ?").run(chatId);
|
|
2667
|
+
}
|
|
2646
2668
|
var pendingEscalations, ESCALATION_TTL_MS, ALL_TOOLS;
|
|
2647
2669
|
var init_chat_settings = __esm({
|
|
2648
2670
|
"src/memory/chat-settings.ts"() {
|
|
@@ -3450,6 +3472,7 @@ __export(store_exports5, {
|
|
|
3450
3472
|
clearChatBackendSlot: () => clearChatBackendSlot,
|
|
3451
3473
|
clearChatGeminiSlot: () => clearChatGeminiSlot,
|
|
3452
3474
|
clearCwd: () => clearCwd,
|
|
3475
|
+
clearExecMode: () => clearExecMode,
|
|
3453
3476
|
clearMessageLog: () => clearMessageLog,
|
|
3454
3477
|
clearModel: () => clearModel,
|
|
3455
3478
|
clearSession: () => clearSession,
|
|
@@ -3487,6 +3510,7 @@ __export(store_exports5, {
|
|
|
3487
3510
|
getEligibleBackendSlots: () => getEligibleBackendSlots,
|
|
3488
3511
|
getEligibleGeminiSlots: () => getEligibleGeminiSlots,
|
|
3489
3512
|
getEnabledTools: () => getEnabledTools,
|
|
3513
|
+
getExecMode: () => getExecMode,
|
|
3490
3514
|
getGeminiRotationMode: () => getGeminiRotationMode,
|
|
3491
3515
|
getGeminiSlots: () => getGeminiSlots,
|
|
3492
3516
|
getHeartbeatConfig: () => getHeartbeatConfig,
|
|
@@ -3557,6 +3581,7 @@ __export(store_exports5, {
|
|
|
3557
3581
|
setBootTime: () => setBootTime,
|
|
3558
3582
|
setChatAlias: () => setChatAlias,
|
|
3559
3583
|
setCwd: () => setCwd,
|
|
3584
|
+
setExecMode: () => setExecMode,
|
|
3560
3585
|
setGeminiRotationMode: () => setGeminiRotationMode,
|
|
3561
3586
|
setGeminiSlotEnabled: () => setGeminiSlotEnabled,
|
|
3562
3587
|
setHeartbeatConfig: () => setHeartbeatConfig,
|
|
@@ -3944,10 +3969,199 @@ var init_claude = __esm({
|
|
|
3944
3969
|
}
|
|
3945
3970
|
});
|
|
3946
3971
|
|
|
3972
|
+
// src/slots/symlink-manager.ts
|
|
3973
|
+
var symlink_manager_exports = {};
|
|
3974
|
+
__export(symlink_manager_exports, {
|
|
3975
|
+
SYMLINK_LAYOUTS: () => SYMLINK_LAYOUTS,
|
|
3976
|
+
getPrimaryDir: () => getPrimaryDir,
|
|
3977
|
+
migrateAllSlots: () => migrateAllSlots,
|
|
3978
|
+
migrateExistingSlots: () => migrateExistingSlots,
|
|
3979
|
+
setupSlotSymlinks: () => setupSlotSymlinks,
|
|
3980
|
+
validateSlotSymlinks: () => validateSlotSymlinks
|
|
3981
|
+
});
|
|
3982
|
+
import { existsSync as existsSync3, lstatSync, mkdirSync, readlinkSync, readdirSync as readdirSync2, symlinkSync, rmSync, copyFileSync, statSync as statSync2 } from "fs";
|
|
3983
|
+
import { join as join5, dirname } from "path";
|
|
3984
|
+
function setupSlotSymlinks(backend2, slotDir, primaryDir) {
|
|
3985
|
+
const layout = SYMLINK_LAYOUTS[backend2];
|
|
3986
|
+
if (!layout) {
|
|
3987
|
+
log(`[symlink] No layout defined for backend "${backend2}", skipping`);
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
for (const entry of layout.symlinks) {
|
|
3991
|
+
const slotPath = join5(slotDir, entry.slotSubpath);
|
|
3992
|
+
const primaryTarget = join5(primaryDir, entry.primarySubpath);
|
|
3993
|
+
if (!existsSync3(primaryTarget)) {
|
|
3994
|
+
mkdirSync(primaryTarget, { recursive: true });
|
|
3995
|
+
}
|
|
3996
|
+
if (existsSync3(slotPath) || isSymlink(slotPath)) {
|
|
3997
|
+
if (isSymlink(slotPath)) {
|
|
3998
|
+
const currentTarget = readlinkSync(slotPath);
|
|
3999
|
+
if (currentTarget === primaryTarget) {
|
|
4000
|
+
continue;
|
|
4001
|
+
}
|
|
4002
|
+
rmSync(slotPath);
|
|
4003
|
+
} else {
|
|
4004
|
+
migrateDirectoryContents(slotPath, primaryTarget);
|
|
4005
|
+
rmSync(slotPath, { recursive: true });
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
const parentDir = dirname(slotPath);
|
|
4009
|
+
if (!existsSync3(parentDir)) {
|
|
4010
|
+
mkdirSync(parentDir, { recursive: true });
|
|
4011
|
+
}
|
|
4012
|
+
symlinkSync(primaryTarget, slotPath);
|
|
4013
|
+
log(`[symlink] ${backend2}: ${slotPath} \u2192 ${primaryTarget}`);
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
function validateSlotSymlinks(backend2, slotDir, primaryDir) {
|
|
4017
|
+
const layout = SYMLINK_LAYOUTS[backend2];
|
|
4018
|
+
if (!layout) return { valid: true, broken: [] };
|
|
4019
|
+
const broken = [];
|
|
4020
|
+
for (const entry of layout.symlinks) {
|
|
4021
|
+
const slotPath = join5(slotDir, entry.slotSubpath);
|
|
4022
|
+
const primaryTarget = join5(primaryDir, entry.primarySubpath);
|
|
4023
|
+
if (!isSymlink(slotPath)) {
|
|
4024
|
+
if (existsSync3(slotPath)) {
|
|
4025
|
+
broken.push({ path: slotPath, issue: "real directory instead of symlink" });
|
|
4026
|
+
} else {
|
|
4027
|
+
broken.push({ path: slotPath, issue: "symlink missing" });
|
|
4028
|
+
}
|
|
4029
|
+
continue;
|
|
4030
|
+
}
|
|
4031
|
+
const currentTarget = readlinkSync(slotPath);
|
|
4032
|
+
if (currentTarget !== primaryTarget) {
|
|
4033
|
+
broken.push({ path: slotPath, issue: `symlink points to ${currentTarget}, expected ${primaryTarget}` });
|
|
4034
|
+
continue;
|
|
4035
|
+
}
|
|
4036
|
+
if (!existsSync3(primaryTarget)) {
|
|
4037
|
+
broken.push({ path: slotPath, issue: `symlink target ${primaryTarget} does not exist` });
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
return { valid: broken.length === 0, broken };
|
|
4041
|
+
}
|
|
4042
|
+
function migrateExistingSlots(backend2, slotsDir, primaryDir) {
|
|
4043
|
+
if (!existsSync3(slotsDir)) {
|
|
4044
|
+
return { migrated: 0, skipped: 0, errors: [] };
|
|
4045
|
+
}
|
|
4046
|
+
const layout = SYMLINK_LAYOUTS[backend2];
|
|
4047
|
+
if (!layout) return { migrated: 0, skipped: 0, errors: [] };
|
|
4048
|
+
const entries = readdirSync2(slotsDir, { withFileTypes: true });
|
|
4049
|
+
let migrated = 0;
|
|
4050
|
+
let skipped = 0;
|
|
4051
|
+
const errors = [];
|
|
4052
|
+
for (const entry of entries) {
|
|
4053
|
+
if (!entry.isDirectory()) continue;
|
|
4054
|
+
const slotDir = join5(slotsDir, entry.name);
|
|
4055
|
+
const validation = validateSlotSymlinks(backend2, slotDir, primaryDir);
|
|
4056
|
+
if (validation.valid) {
|
|
4057
|
+
skipped++;
|
|
4058
|
+
continue;
|
|
4059
|
+
}
|
|
4060
|
+
try {
|
|
4061
|
+
setupSlotSymlinks(backend2, slotDir, primaryDir);
|
|
4062
|
+
migrated++;
|
|
4063
|
+
log(`[symlink] Migrated slot: ${entry.name}`);
|
|
4064
|
+
} catch (err) {
|
|
4065
|
+
const msg = `Failed to migrate ${entry.name}: ${err instanceof Error ? err.message : String(err)}`;
|
|
4066
|
+
errors.push(msg);
|
|
4067
|
+
log(`[symlink] ERROR: ${msg}`);
|
|
4068
|
+
}
|
|
4069
|
+
}
|
|
4070
|
+
return { migrated, skipped, errors };
|
|
4071
|
+
}
|
|
4072
|
+
function getPrimaryDir(backend2) {
|
|
4073
|
+
const resolver = PRIMARY_DIR_MAP[backend2];
|
|
4074
|
+
return resolver ? resolver() : null;
|
|
4075
|
+
}
|
|
4076
|
+
function migrateAllSlots(ccClawHome) {
|
|
4077
|
+
const backends = [
|
|
4078
|
+
{ id: "claude", slotsSubdir: "claude-slots" },
|
|
4079
|
+
{ id: "codex", slotsSubdir: "codex-slots" },
|
|
4080
|
+
{ id: "gemini", slotsSubdir: "gemini-slots" }
|
|
4081
|
+
];
|
|
4082
|
+
for (const { id, slotsSubdir } of backends) {
|
|
4083
|
+
const slotsDir = join5(ccClawHome, slotsSubdir);
|
|
4084
|
+
const primaryDir = getPrimaryDir(id);
|
|
4085
|
+
if (!primaryDir || !existsSync3(slotsDir)) continue;
|
|
4086
|
+
const result = migrateExistingSlots(id, slotsDir, primaryDir);
|
|
4087
|
+
if (result.migrated > 0) {
|
|
4088
|
+
log(`[symlink] ${id}: migrated ${result.migrated} slot(s), skipped ${result.skipped}`);
|
|
4089
|
+
}
|
|
4090
|
+
if (result.errors.length > 0) {
|
|
4091
|
+
for (const err of result.errors) log(`[symlink] ${id}: ${err}`);
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
function isSymlink(path) {
|
|
4096
|
+
try {
|
|
4097
|
+
return lstatSync(path).isSymbolicLink();
|
|
4098
|
+
} catch {
|
|
4099
|
+
return false;
|
|
4100
|
+
}
|
|
4101
|
+
}
|
|
4102
|
+
function migrateDirectoryContents(src, dest) {
|
|
4103
|
+
if (!existsSync3(src) || !statSync2(src).isDirectory()) return;
|
|
4104
|
+
const entries = readdirSync2(src, { withFileTypes: true });
|
|
4105
|
+
for (const entry of entries) {
|
|
4106
|
+
const srcPath = join5(src, entry.name);
|
|
4107
|
+
const destPath = join5(dest, entry.name);
|
|
4108
|
+
if (entry.isDirectory()) {
|
|
4109
|
+
if (!existsSync3(destPath)) {
|
|
4110
|
+
mkdirSync(destPath, { recursive: true });
|
|
4111
|
+
}
|
|
4112
|
+
migrateDirectoryContents(srcPath, destPath);
|
|
4113
|
+
} else if (entry.isFile()) {
|
|
4114
|
+
if (!existsSync3(destPath)) {
|
|
4115
|
+
copyFileSync(srcPath, destPath);
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
var SYMLINK_LAYOUTS, PRIMARY_DIR_MAP;
|
|
4121
|
+
var init_symlink_manager = __esm({
|
|
4122
|
+
"src/slots/symlink-manager.ts"() {
|
|
4123
|
+
"use strict";
|
|
4124
|
+
init_log();
|
|
4125
|
+
SYMLINK_LAYOUTS = {
|
|
4126
|
+
claude: {
|
|
4127
|
+
symlinks: [
|
|
4128
|
+
{ slotSubpath: ".claude/projects", primarySubpath: "projects" },
|
|
4129
|
+
{ slotSubpath: ".claude/plans", primarySubpath: "plans" }
|
|
4130
|
+
]
|
|
4131
|
+
},
|
|
4132
|
+
codex: {
|
|
4133
|
+
symlinks: [
|
|
4134
|
+
{ slotSubpath: "memories", primarySubpath: "memories" }
|
|
4135
|
+
]
|
|
4136
|
+
},
|
|
4137
|
+
gemini: {
|
|
4138
|
+
symlinks: [
|
|
4139
|
+
{ slotSubpath: ".gemini/history", primarySubpath: "history" },
|
|
4140
|
+
{ slotSubpath: ".gemini/tmp", primarySubpath: "tmp" }
|
|
4141
|
+
]
|
|
4142
|
+
}
|
|
4143
|
+
};
|
|
4144
|
+
PRIMARY_DIR_MAP = {
|
|
4145
|
+
claude: () => {
|
|
4146
|
+
const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
|
|
4147
|
+
return join5(home, ".claude");
|
|
4148
|
+
},
|
|
4149
|
+
codex: () => {
|
|
4150
|
+
const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
|
|
4151
|
+
return process.env.CODEX_HOME ?? join5(home, ".codex");
|
|
4152
|
+
},
|
|
4153
|
+
gemini: () => {
|
|
4154
|
+
const home = process.env.HOME ?? `/Users/${process.env.USER ?? "unknown"}`;
|
|
4155
|
+
return process.env.GEMINI_CLI_HOME ?? join5(home, ".gemini");
|
|
4156
|
+
}
|
|
4157
|
+
};
|
|
4158
|
+
}
|
|
4159
|
+
});
|
|
4160
|
+
|
|
3947
4161
|
// src/backends/gemini.ts
|
|
3948
|
-
import { existsSync as
|
|
4162
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
3949
4163
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
3950
|
-
import { join as
|
|
4164
|
+
import { join as join6 } from "path";
|
|
3951
4165
|
var GeminiAdapter;
|
|
3952
4166
|
var init_gemini = __esm({
|
|
3953
4167
|
"src/backends/gemini.ts"() {
|
|
@@ -4015,14 +4229,14 @@ var init_gemini = __esm({
|
|
|
4015
4229
|
`${home}/.local/bin/gemini`,
|
|
4016
4230
|
`${home}/.npm-global/bin/gemini`
|
|
4017
4231
|
];
|
|
4018
|
-
this._resolvedPath = candidates.find((p) =>
|
|
4232
|
+
this._resolvedPath = candidates.find((p) => existsSync4(p)) ?? "gemini";
|
|
4019
4233
|
}
|
|
4020
4234
|
return this._resolvedPath;
|
|
4021
4235
|
}
|
|
4022
4236
|
getEnv(thinkingOverrides) {
|
|
4023
4237
|
const env = buildBaseEnv(thinkingOverrides);
|
|
4024
|
-
const identityFile =
|
|
4025
|
-
if (
|
|
4238
|
+
const identityFile = join6(IDENTITY_PATH, "CC-CLAW.md");
|
|
4239
|
+
if (existsSync4(identityFile)) {
|
|
4026
4240
|
env.GEMINI_SYSTEM_MD = identityFile;
|
|
4027
4241
|
}
|
|
4028
4242
|
return env;
|
|
@@ -4112,11 +4326,17 @@ var init_gemini = __esm({
|
|
|
4112
4326
|
if (!slot) return { env, slot: null };
|
|
4113
4327
|
if (slot.slotType === "api_key" && slot.apiKey) {
|
|
4114
4328
|
env.GEMINI_API_KEY = slot.apiKey;
|
|
4115
|
-
const isolatedHome =
|
|
4116
|
-
if (!
|
|
4329
|
+
const isolatedHome = join6(CC_CLAW_HOME, "gemini-slots", `apikey-${slot.id}`);
|
|
4330
|
+
if (!existsSync4(isolatedHome)) mkdirSync2(isolatedHome, { recursive: true });
|
|
4117
4331
|
log(`[gemini] api_key slot ${slot.id}: isolated home \u2192 ${isolatedHome}`);
|
|
4118
4332
|
env.GEMINI_CLI_HOME = isolatedHome;
|
|
4119
4333
|
delete env.GOOGLE_API_KEY;
|
|
4334
|
+
try {
|
|
4335
|
+
const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = (init_symlink_manager(), __toCommonJS(symlink_manager_exports));
|
|
4336
|
+
const primaryDir = getPrimaryDir2("gemini");
|
|
4337
|
+
if (primaryDir) setupSlotSymlinks2("gemini", isolatedHome, primaryDir);
|
|
4338
|
+
} catch {
|
|
4339
|
+
}
|
|
4120
4340
|
} else if (slot.slotType === "oauth" && slot.configHome) {
|
|
4121
4341
|
env.GEMINI_CLI_HOME = slot.configHome;
|
|
4122
4342
|
delete env.GEMINI_API_KEY;
|
|
@@ -4135,7 +4355,7 @@ var init_gemini = __esm({
|
|
|
4135
4355
|
});
|
|
4136
4356
|
|
|
4137
4357
|
// src/backends/codex.ts
|
|
4138
|
-
import { existsSync as
|
|
4358
|
+
import { existsSync as existsSync5 } from "fs";
|
|
4139
4359
|
import { execSync as execSync2 } from "child_process";
|
|
4140
4360
|
var CodexAdapter;
|
|
4141
4361
|
var init_codex = __esm({
|
|
@@ -4210,7 +4430,7 @@ var init_codex = __esm({
|
|
|
4210
4430
|
`${home}/.local/bin/codex`,
|
|
4211
4431
|
`${home}/.npm-global/bin/codex`
|
|
4212
4432
|
];
|
|
4213
|
-
this._resolvedPath = candidates.find((p) =>
|
|
4433
|
+
this._resolvedPath = candidates.find((p) => existsSync5(p)) ?? "codex";
|
|
4214
4434
|
}
|
|
4215
4435
|
return this._resolvedPath;
|
|
4216
4436
|
}
|
|
@@ -4321,7 +4541,7 @@ var init_codex = __esm({
|
|
|
4321
4541
|
});
|
|
4322
4542
|
|
|
4323
4543
|
// src/backends/cursor.ts
|
|
4324
|
-
import { existsSync as
|
|
4544
|
+
import { existsSync as existsSync6 } from "fs";
|
|
4325
4545
|
import { execSync as execSync3 } from "child_process";
|
|
4326
4546
|
function extractToolInfo(tc) {
|
|
4327
4547
|
if (tc.readToolCall) {
|
|
@@ -4470,7 +4690,7 @@ var init_cursor = __esm({
|
|
|
4470
4690
|
`${home}/.local/bin/agent`,
|
|
4471
4691
|
"/usr/local/bin/agent"
|
|
4472
4692
|
];
|
|
4473
|
-
this._resolvedPath = candidates.find((p) =>
|
|
4693
|
+
this._resolvedPath = candidates.find((p) => existsSync6(p)) ?? "agent";
|
|
4474
4694
|
}
|
|
4475
4695
|
return this._resolvedPath;
|
|
4476
4696
|
}
|
|
@@ -4634,14 +4854,14 @@ __export(backends_exports, {
|
|
|
4634
4854
|
isBackendAvailable: () => isBackendAvailable,
|
|
4635
4855
|
probeBackendAvailability: () => probeBackendAvailability
|
|
4636
4856
|
});
|
|
4637
|
-
import { existsSync as
|
|
4857
|
+
import { existsSync as existsSync7 } from "fs";
|
|
4638
4858
|
import { execSync as execSync4 } from "child_process";
|
|
4639
4859
|
function probeBackendAvailability() {
|
|
4640
4860
|
availableSet.clear();
|
|
4641
4861
|
for (const [id, adapter] of Object.entries(adapters)) {
|
|
4642
4862
|
try {
|
|
4643
4863
|
const exe = adapter.getExecutablePath();
|
|
4644
|
-
if (
|
|
4864
|
+
if (existsSync7(exe) || resolveOnPath(exe)) {
|
|
4645
4865
|
availableSet.add(id);
|
|
4646
4866
|
}
|
|
4647
4867
|
} catch {
|
|
@@ -4650,7 +4870,7 @@ function probeBackendAvailability() {
|
|
|
4650
4870
|
log(`[backends] Available: ${[...availableSet].join(", ") || "none"}`);
|
|
4651
4871
|
}
|
|
4652
4872
|
function resolveOnPath(name) {
|
|
4653
|
-
if (name.includes("/")) return
|
|
4873
|
+
if (name.includes("/")) return existsSync7(name);
|
|
4654
4874
|
try {
|
|
4655
4875
|
execSync4(`which ${name}`, { encoding: "utf-8", timeout: 3e3 });
|
|
4656
4876
|
return true;
|
|
@@ -5073,19 +5293,19 @@ If the user asks *how* to do something with CC-Claw, use this expertise to sugge
|
|
|
5073
5293
|
|
|
5074
5294
|
// src/bootstrap/init.ts
|
|
5075
5295
|
import {
|
|
5076
|
-
existsSync as
|
|
5296
|
+
existsSync as existsSync8,
|
|
5077
5297
|
writeFileSync,
|
|
5078
|
-
mkdirSync as
|
|
5298
|
+
mkdirSync as mkdirSync3,
|
|
5079
5299
|
readFileSync as readFileSync2,
|
|
5080
|
-
statSync as
|
|
5081
|
-
copyFileSync,
|
|
5300
|
+
statSync as statSync3,
|
|
5301
|
+
copyFileSync as copyFileSync2,
|
|
5082
5302
|
unlinkSync as unlinkSync2
|
|
5083
5303
|
} from "fs";
|
|
5084
|
-
import { join as
|
|
5304
|
+
import { join as join7 } from "path";
|
|
5085
5305
|
function migrateFile(legacyPath, newPath, label2) {
|
|
5086
|
-
if (
|
|
5087
|
-
if (
|
|
5088
|
-
|
|
5306
|
+
if (existsSync8(newPath)) return false;
|
|
5307
|
+
if (existsSync8(legacyPath)) {
|
|
5308
|
+
copyFileSync2(legacyPath, newPath);
|
|
5089
5309
|
const copied = readFileSync2(newPath, "utf-8");
|
|
5090
5310
|
if (copied.length > 0) {
|
|
5091
5311
|
unlinkSync2(legacyPath);
|
|
@@ -5098,28 +5318,28 @@ function migrateFile(legacyPath, newPath, label2) {
|
|
|
5098
5318
|
return false;
|
|
5099
5319
|
}
|
|
5100
5320
|
function bootstrapWorkspaceFiles() {
|
|
5101
|
-
if (!
|
|
5102
|
-
|
|
5321
|
+
if (!existsSync8(IDENTITY_PATH)) {
|
|
5322
|
+
mkdirSync3(IDENTITY_PATH, { recursive: true });
|
|
5103
5323
|
log("[bootstrap] Created identity/ directory");
|
|
5104
5324
|
}
|
|
5105
|
-
if (!
|
|
5106
|
-
|
|
5325
|
+
if (!existsSync8(WORKSPACE_PATH)) {
|
|
5326
|
+
mkdirSync3(WORKSPACE_PATH, { recursive: true });
|
|
5107
5327
|
}
|
|
5108
5328
|
migrateFile(LEGACY_SOUL_PATH, SOUL_PATH, "SOUL.md");
|
|
5109
5329
|
migrateFile(LEGACY_USER_PATH, USER_PATH, "USER.md");
|
|
5110
|
-
if (
|
|
5330
|
+
if (existsSync8(LEGACY_CLAUDE_MD)) {
|
|
5111
5331
|
unlinkSync2(LEGACY_CLAUDE_MD);
|
|
5112
5332
|
log("[bootstrap] Removed legacy workspace/CLAUDE.md (replaced by identity/CC-CLAW.md)");
|
|
5113
5333
|
}
|
|
5114
|
-
if (
|
|
5334
|
+
if (existsSync8(LEGACY_GEMINI_MD)) {
|
|
5115
5335
|
unlinkSync2(LEGACY_GEMINI_MD);
|
|
5116
5336
|
log("[bootstrap] Removed legacy workspace/GEMINI.md (replaced by identity/CC-CLAW.md)");
|
|
5117
5337
|
}
|
|
5118
|
-
if (!
|
|
5338
|
+
if (!existsSync8(SOUL_PATH)) {
|
|
5119
5339
|
writeFileSync(SOUL_PATH, DEFAULT_SOUL, "utf-8");
|
|
5120
5340
|
log("[bootstrap] Created default SOUL.md");
|
|
5121
5341
|
}
|
|
5122
|
-
if (!
|
|
5342
|
+
if (!existsSync8(USER_PATH)) {
|
|
5123
5343
|
let tz = "UTC";
|
|
5124
5344
|
try {
|
|
5125
5345
|
tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
@@ -5129,16 +5349,16 @@ function bootstrapWorkspaceFiles() {
|
|
|
5129
5349
|
writeFileSync(USER_PATH, userContent, "utf-8");
|
|
5130
5350
|
log(`[bootstrap] Created default USER.md (timezone: ${tz})`);
|
|
5131
5351
|
}
|
|
5132
|
-
if (!
|
|
5133
|
-
|
|
5352
|
+
if (!existsSync8(CONTEXT_DIR)) {
|
|
5353
|
+
mkdirSync3(CONTEXT_DIR, { recursive: true });
|
|
5134
5354
|
log("[bootstrap] Created context/ directory");
|
|
5135
5355
|
}
|
|
5136
|
-
if (!
|
|
5137
|
-
|
|
5356
|
+
if (!existsSync8(MEDIA_PATH)) {
|
|
5357
|
+
mkdirSync3(MEDIA_PATH, { recursive: true });
|
|
5138
5358
|
log("[bootstrap] Created media/ directory");
|
|
5139
5359
|
}
|
|
5140
|
-
const expertisePath =
|
|
5141
|
-
if (!
|
|
5360
|
+
const expertisePath = join7(CONTEXT_DIR, "cc-claw-expertise.md");
|
|
5361
|
+
if (!existsSync8(expertisePath)) {
|
|
5142
5362
|
writeFileSync(expertisePath, DEFAULT_EXPERTISE, "utf-8");
|
|
5143
5363
|
log("[bootstrap] Created default context/cc-claw-expertise.md");
|
|
5144
5364
|
}
|
|
@@ -5153,13 +5373,13 @@ function bootstrapWorkspaceFiles() {
|
|
|
5153
5373
|
"!context/**",
|
|
5154
5374
|
""
|
|
5155
5375
|
].join("\n");
|
|
5156
|
-
const gitignorePath =
|
|
5157
|
-
if (!
|
|
5376
|
+
const gitignorePath = join7(WORKSPACE_PATH, ".gitignore");
|
|
5377
|
+
if (!existsSync8(gitignorePath)) {
|
|
5158
5378
|
writeFileSync(gitignorePath, IGNORE_CONTENT, "utf-8");
|
|
5159
5379
|
log("[bootstrap] Created .gitignore (workspace allowlist)");
|
|
5160
5380
|
}
|
|
5161
|
-
const geminiignorePath =
|
|
5162
|
-
if (!
|
|
5381
|
+
const geminiignorePath = join7(WORKSPACE_PATH, ".geminiignore");
|
|
5382
|
+
if (!existsSync8(geminiignorePath)) {
|
|
5163
5383
|
writeFileSync(geminiignorePath, IGNORE_CONTENT, "utf-8");
|
|
5164
5384
|
log("[bootstrap] Created .geminiignore (workspace allowlist)");
|
|
5165
5385
|
}
|
|
@@ -5185,8 +5405,8 @@ function syncNativeCliFiles() {
|
|
|
5185
5405
|
}
|
|
5186
5406
|
}
|
|
5187
5407
|
try {
|
|
5188
|
-
const soulMtime =
|
|
5189
|
-
const userMtime =
|
|
5408
|
+
const soulMtime = existsSync8(SOUL_PATH) ? statSync3(SOUL_PATH).mtimeMs : 0;
|
|
5409
|
+
const userMtime = existsSync8(USER_PATH) ? statSync3(USER_PATH).mtimeMs : 0;
|
|
5190
5410
|
if (soulMtime > 0 && soulMtime === lastSoulMtime && userMtime === lastUserMtime) {
|
|
5191
5411
|
return;
|
|
5192
5412
|
}
|
|
@@ -5223,15 +5443,38 @@ function syncNativeCliFiles() {
|
|
|
5223
5443
|
"## CRITICAL: Tool Usage Rules",
|
|
5224
5444
|
"",
|
|
5225
5445
|
"- Do NOT use native CLI memory/storage tools (save_memory, etc.) \u2014 they are backend-local and invisible to other backends",
|
|
5226
|
-
"- Do NOT modify the database directly with SQL (no INSERT/UPDATE/DELETE) \u2014 use CC-Claw commands only",
|
|
5227
5446
|
"- To save a memory: use /remember in Telegram, or tell the user to use it",
|
|
5228
5447
|
"- To learn your full CLI: run `cc-claw --ai`",
|
|
5229
5448
|
"- All state changes must go through the CC-Claw API layer for cross-backend persistence",
|
|
5449
|
+
"",
|
|
5450
|
+
"## \u26D4 DATABASE SAFETY BOUNDARY \u2014 ABSOLUTE PROHIBITION",
|
|
5451
|
+
"",
|
|
5452
|
+
"**NEVER access ~/.cc-claw/data/cc-claw.db directly. No exceptions. No excuses.**",
|
|
5453
|
+
"",
|
|
5454
|
+
"This means ALL of the following are FORBIDDEN:",
|
|
5455
|
+
"- `sqlite3 ~/.cc-claw/data/cc-claw.db` \u2014 FORBIDDEN",
|
|
5456
|
+
"- `sqlite3` with any path containing `cc-claw` \u2014 FORBIDDEN",
|
|
5457
|
+
"- `.schema`, `.tables`, `.dump`, or any SQLite dot-command \u2014 FORBIDDEN",
|
|
5458
|
+
"- `SELECT`, `INSERT`, `UPDATE`, `DELETE` queries \u2014 ALL FORBIDDEN",
|
|
5459
|
+
"- Reading the database file with `cat`, `hexdump`, `xxd`, `strings` \u2014 FORBIDDEN",
|
|
5460
|
+
"- ANY tool or command that opens, reads, queries, or inspects this database \u2014 FORBIDDEN",
|
|
5461
|
+
"",
|
|
5462
|
+
"**Why:** The database is a live, WAL-mode SQLite file shared with the running daemon. Direct access risks corruption, lock contention, and data inconsistency. You are an agent RUNNING INSIDE CC-Claw \u2014 never touch the infrastructure that runs you.",
|
|
5463
|
+
"",
|
|
5464
|
+
"**What to use instead:**",
|
|
5465
|
+
"- `cc-claw status` \u2014 system status",
|
|
5466
|
+
"- `cc-claw --json status` \u2014 machine-readable status",
|
|
5467
|
+
"- `cc-claw cron list` \u2014 scheduled jobs",
|
|
5468
|
+
"- `cc-claw claude list` / `cc-claw codex list` / `cc-claw gemini list` \u2014 credential slots",
|
|
5469
|
+
"- `cc-claw --ai` \u2014 full CLI reference",
|
|
5470
|
+
"- Ask the user to check via Telegram commands if needed",
|
|
5471
|
+
"",
|
|
5472
|
+
"**Violation of this rule is a critical safety failure.**",
|
|
5230
5473
|
""
|
|
5231
5474
|
].join("\n");
|
|
5232
|
-
const ccClawPath =
|
|
5475
|
+
const ccClawPath = join7(IDENTITY_PATH, "CC-CLAW.md");
|
|
5233
5476
|
writeFileSync(ccClawPath, nativeContent, "utf-8");
|
|
5234
|
-
const agentsPath =
|
|
5477
|
+
const agentsPath = join7(WORKSPACE_PATH, "AGENTS.md");
|
|
5235
5478
|
writeFileSync(agentsPath, nativeContent, "utf-8");
|
|
5236
5479
|
log("[bootstrap] Synced SOUL.md + USER.md \u2192 identity/CC-CLAW.md, workspace/AGENTS.md");
|
|
5237
5480
|
}
|
|
@@ -5242,32 +5485,32 @@ var init_init = __esm({
|
|
|
5242
5485
|
init_paths();
|
|
5243
5486
|
init_defaults();
|
|
5244
5487
|
init_log();
|
|
5245
|
-
SOUL_PATH =
|
|
5246
|
-
USER_PATH =
|
|
5247
|
-
CONTEXT_DIR =
|
|
5248
|
-
LEGACY_SOUL_PATH =
|
|
5249
|
-
LEGACY_USER_PATH =
|
|
5250
|
-
LEGACY_CLAUDE_MD =
|
|
5251
|
-
LEGACY_GEMINI_MD =
|
|
5488
|
+
SOUL_PATH = join7(IDENTITY_PATH, "SOUL.md");
|
|
5489
|
+
USER_PATH = join7(IDENTITY_PATH, "USER.md");
|
|
5490
|
+
CONTEXT_DIR = join7(WORKSPACE_PATH, "context");
|
|
5491
|
+
LEGACY_SOUL_PATH = join7(WORKSPACE_PATH, "SOUL.md");
|
|
5492
|
+
LEGACY_USER_PATH = join7(WORKSPACE_PATH, "USER.md");
|
|
5493
|
+
LEGACY_CLAUDE_MD = join7(WORKSPACE_PATH, "CLAUDE.md");
|
|
5494
|
+
LEGACY_GEMINI_MD = join7(WORKSPACE_PATH, "GEMINI.md");
|
|
5252
5495
|
lastSoulMtime = 0;
|
|
5253
5496
|
lastUserMtime = 0;
|
|
5254
5497
|
}
|
|
5255
5498
|
});
|
|
5256
5499
|
|
|
5257
5500
|
// src/bootstrap/loader.ts
|
|
5258
|
-
import { readFileSync as readFileSync3, existsSync as
|
|
5259
|
-
import { join as
|
|
5501
|
+
import { readFileSync as readFileSync3, existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
|
|
5502
|
+
import { join as join8 } from "path";
|
|
5260
5503
|
function searchContext(userMessage) {
|
|
5261
|
-
if (!
|
|
5504
|
+
if (!existsSync9(CONTEXT_DIR2)) return null;
|
|
5262
5505
|
const msgWords = new Set(
|
|
5263
5506
|
userMessage.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 3)
|
|
5264
5507
|
);
|
|
5265
5508
|
if (msgWords.size === 0) return null;
|
|
5266
5509
|
let bestMatch = null;
|
|
5267
5510
|
try {
|
|
5268
|
-
const files =
|
|
5511
|
+
const files = readdirSync3(CONTEXT_DIR2).filter((f) => f.endsWith(".md"));
|
|
5269
5512
|
for (const file of files) {
|
|
5270
|
-
const filePath =
|
|
5513
|
+
const filePath = join8(CONTEXT_DIR2, file);
|
|
5271
5514
|
try {
|
|
5272
5515
|
const content = readFileSync3(filePath, "utf-8").trim();
|
|
5273
5516
|
if (!content) continue;
|
|
@@ -5295,8 +5538,11 @@ function searchContext(userMessage) {
|
|
|
5295
5538
|
}
|
|
5296
5539
|
return null;
|
|
5297
5540
|
}
|
|
5298
|
-
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext) {
|
|
5541
|
+
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext, planningDirective) {
|
|
5299
5542
|
const sections = [];
|
|
5543
|
+
if (planningDirective) {
|
|
5544
|
+
sections.push(planningDirective);
|
|
5545
|
+
}
|
|
5300
5546
|
if (Date.now() - lastSyncMs >= 5e3) {
|
|
5301
5547
|
syncNativeCliFiles();
|
|
5302
5548
|
lastSyncMs = Date.now();
|
|
@@ -5492,7 +5738,7 @@ var init_loader = __esm({
|
|
|
5492
5738
|
init_store();
|
|
5493
5739
|
init_backends();
|
|
5494
5740
|
lastSyncMs = 0;
|
|
5495
|
-
CONTEXT_DIR2 =
|
|
5741
|
+
CONTEXT_DIR2 = join8(WORKSPACE_PATH, "context");
|
|
5496
5742
|
MAX_CONTEXT_CHARS = 4e3;
|
|
5497
5743
|
ACTIVITY_TOKEN_BUDGET = 1500;
|
|
5498
5744
|
INBOX_TOKEN_BUDGET = 2e3;
|
|
@@ -5984,13 +6230,13 @@ var init_quota = __esm({
|
|
|
5984
6230
|
|
|
5985
6231
|
// src/dashboard/middleware.ts
|
|
5986
6232
|
import { randomBytes } from "crypto";
|
|
5987
|
-
import { writeFileSync as writeFileSync2, mkdirSync as
|
|
6233
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
5988
6234
|
function getDashboardToken() {
|
|
5989
6235
|
return DASHBOARD_TOKEN;
|
|
5990
6236
|
}
|
|
5991
6237
|
function persistToken() {
|
|
5992
6238
|
try {
|
|
5993
|
-
|
|
6239
|
+
mkdirSync4(DATA_PATH, { recursive: true });
|
|
5994
6240
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
5995
6241
|
writeFileSync2(tokenPath, DASHBOARD_TOKEN, { mode: 384 });
|
|
5996
6242
|
} catch (err) {
|
|
@@ -6677,14 +6923,14 @@ var init_propagate = __esm({
|
|
|
6677
6923
|
});
|
|
6678
6924
|
|
|
6679
6925
|
// src/agents/mcp-config.ts
|
|
6680
|
-
import { mkdirSync as
|
|
6681
|
-
import { join as
|
|
6926
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, existsSync as existsSync10, readdirSync as readdirSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
6927
|
+
import { join as join9, dirname as dirname2 } from "path";
|
|
6682
6928
|
import { fileURLToPath } from "url";
|
|
6683
6929
|
function generateOrchestratorMcpConfig(opts) {
|
|
6684
6930
|
const port = opts.port ?? process.env.DASHBOARD_PORT ?? "3141";
|
|
6685
|
-
const distPath =
|
|
6686
|
-
const tsxPath =
|
|
6687
|
-
const useTs = !
|
|
6931
|
+
const distPath = join9(__dirname, "agents", "mcp-server.js");
|
|
6932
|
+
const tsxPath = join9(__dirname, "..", "src", "agents", "mcp-server.ts");
|
|
6933
|
+
const useTs = !existsSync10(distPath);
|
|
6688
6934
|
return {
|
|
6689
6935
|
name: opts.agentId === "main" ? "cc-claw" : `cc-claw-${opts.agentId.slice(0, 8)}`,
|
|
6690
6936
|
transport: "stdio",
|
|
@@ -6699,7 +6945,7 @@ function generateOrchestratorMcpConfig(opts) {
|
|
|
6699
6945
|
};
|
|
6700
6946
|
}
|
|
6701
6947
|
function writeMcpConfigFile(config2) {
|
|
6702
|
-
|
|
6948
|
+
mkdirSync5(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
|
|
6703
6949
|
const jsonConfig = {
|
|
6704
6950
|
mcpServers: {
|
|
6705
6951
|
[config2.name]: {
|
|
@@ -6710,13 +6956,13 @@ function writeMcpConfigFile(config2) {
|
|
|
6710
6956
|
}
|
|
6711
6957
|
};
|
|
6712
6958
|
const safeName = config2.name.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
6713
|
-
const configPath =
|
|
6959
|
+
const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
6714
6960
|
writeFileSync3(configPath, JSON.stringify(jsonConfig, null, 2), { mode: 384 });
|
|
6715
6961
|
return configPath;
|
|
6716
6962
|
}
|
|
6717
6963
|
function deleteMcpConfigFile(mcpName) {
|
|
6718
6964
|
const safeName = mcpName.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
6719
|
-
const configPath =
|
|
6965
|
+
const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
6720
6966
|
try {
|
|
6721
6967
|
unlinkSync3(configPath);
|
|
6722
6968
|
} catch {
|
|
@@ -6724,12 +6970,12 @@ function deleteMcpConfigFile(mcpName) {
|
|
|
6724
6970
|
}
|
|
6725
6971
|
function cleanupOrphanedMcpConfigs() {
|
|
6726
6972
|
try {
|
|
6727
|
-
if (!
|
|
6728
|
-
const files =
|
|
6973
|
+
if (!existsSync10(MCP_CONFIG_DIR)) return;
|
|
6974
|
+
const files = readdirSync4(MCP_CONFIG_DIR);
|
|
6729
6975
|
for (const file of files) {
|
|
6730
6976
|
if (file.startsWith("mcp-cc-claw-") && file.endsWith(".json")) {
|
|
6731
6977
|
try {
|
|
6732
|
-
unlinkSync3(
|
|
6978
|
+
unlinkSync3(join9(MCP_CONFIG_DIR, file));
|
|
6733
6979
|
} catch {
|
|
6734
6980
|
}
|
|
6735
6981
|
}
|
|
@@ -6743,8 +6989,8 @@ var init_mcp_config = __esm({
|
|
|
6743
6989
|
"use strict";
|
|
6744
6990
|
init_paths();
|
|
6745
6991
|
__filename = fileURLToPath(import.meta.url);
|
|
6746
|
-
__dirname =
|
|
6747
|
-
MCP_CONFIG_DIR =
|
|
6992
|
+
__dirname = dirname2(__filename);
|
|
6993
|
+
MCP_CONFIG_DIR = join9(CC_CLAW_HOME, "mcp-configs");
|
|
6748
6994
|
}
|
|
6749
6995
|
});
|
|
6750
6996
|
|
|
@@ -6754,8 +7000,8 @@ __export(loader_exports, {
|
|
|
6754
7000
|
getTemplate: () => getTemplate,
|
|
6755
7001
|
listTemplates: () => listTemplates
|
|
6756
7002
|
});
|
|
6757
|
-
import { readdirSync as
|
|
6758
|
-
import { join as
|
|
7003
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
|
|
7004
|
+
import { join as join10 } from "path";
|
|
6759
7005
|
function parseFrontmatter(content) {
|
|
6760
7006
|
const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/m);
|
|
6761
7007
|
if (!match || match.index !== 0) return { meta: {}, body: content.trim() };
|
|
@@ -6788,12 +7034,12 @@ function scanTemplates() {
|
|
|
6788
7034
|
templateCache.clear();
|
|
6789
7035
|
let files;
|
|
6790
7036
|
try {
|
|
6791
|
-
files =
|
|
7037
|
+
files = readdirSync5(AGENTS_PATH).filter((f) => f.endsWith(".md"));
|
|
6792
7038
|
} catch {
|
|
6793
7039
|
return;
|
|
6794
7040
|
}
|
|
6795
7041
|
for (const file of files) {
|
|
6796
|
-
const filePath =
|
|
7042
|
+
const filePath = join10(AGENTS_PATH, file);
|
|
6797
7043
|
try {
|
|
6798
7044
|
const raw = readFileSync5(filePath, "utf-8");
|
|
6799
7045
|
const { meta, body } = parseFrontmatter(raw);
|
|
@@ -6842,8 +7088,8 @@ var init_loader2 = __esm({
|
|
|
6842
7088
|
});
|
|
6843
7089
|
|
|
6844
7090
|
// src/agents/agent-log.ts
|
|
6845
|
-
import { writeFileSync as writeFileSync4, readdirSync as
|
|
6846
|
-
import { join as
|
|
7091
|
+
import { writeFileSync as writeFileSync4, readdirSync as readdirSync6, statSync as statSync4, unlinkSync as unlinkSync4, mkdirSync as mkdirSync6 } from "fs";
|
|
7092
|
+
import { join as join11 } from "path";
|
|
6847
7093
|
function truncate(text, maxBytes) {
|
|
6848
7094
|
if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
|
|
6849
7095
|
let lo = 0, hi = text.length;
|
|
@@ -6858,7 +7104,7 @@ function truncate(text, maxBytes) {
|
|
|
6858
7104
|
[...truncated ${droppedBytes} bytes...]`;
|
|
6859
7105
|
}
|
|
6860
7106
|
function writeAgentLog(data) {
|
|
6861
|
-
const logPath =
|
|
7107
|
+
const logPath = join11(AGENTS_PATH, `${data.agentId}.log`);
|
|
6862
7108
|
const exitDisplay = data.exitCodeForced ? `${data.exitCode} (forced \u2014 no output from original exit code 0)` : String(data.exitCode ?? "null");
|
|
6863
7109
|
const stderrContent = truncate(data.stderr || "(empty)", MAX_STDERR_BYTES);
|
|
6864
7110
|
const stdoutContent = truncate(data.rawStdoutLines.join("\n") || "(empty)", MAX_STDOUT_BYTES);
|
|
@@ -6882,7 +7128,7 @@ function writeAgentLog(data) {
|
|
|
6882
7128
|
""
|
|
6883
7129
|
];
|
|
6884
7130
|
try {
|
|
6885
|
-
|
|
7131
|
+
mkdirSync6(AGENTS_PATH, { recursive: true });
|
|
6886
7132
|
writeFileSync4(logPath, lines.join("\n"), "utf-8");
|
|
6887
7133
|
} catch (err) {
|
|
6888
7134
|
log(`[agent-log] Failed to write log for ${data.agentId}: ${err}`);
|
|
@@ -6891,10 +7137,10 @@ function writeAgentLog(data) {
|
|
|
6891
7137
|
}
|
|
6892
7138
|
function pruneAgentLogs() {
|
|
6893
7139
|
try {
|
|
6894
|
-
|
|
6895
|
-
const files =
|
|
6896
|
-
const fullPath =
|
|
6897
|
-
const stat4 =
|
|
7140
|
+
mkdirSync6(AGENTS_PATH, { recursive: true });
|
|
7141
|
+
const files = readdirSync6(AGENTS_PATH).filter((f) => f.endsWith(".log")).map((f) => {
|
|
7142
|
+
const fullPath = join11(AGENTS_PATH, f);
|
|
7143
|
+
const stat4 = statSync4(fullPath);
|
|
6898
7144
|
return { path: fullPath, mtime: stat4.mtimeMs, size: stat4.size };
|
|
6899
7145
|
});
|
|
6900
7146
|
const now = Date.now();
|
|
@@ -6939,7 +7185,7 @@ var init_agent_log = __esm({
|
|
|
6939
7185
|
});
|
|
6940
7186
|
|
|
6941
7187
|
// src/agents/orchestrator.ts
|
|
6942
|
-
import { existsSync as
|
|
7188
|
+
import { existsSync as existsSync11 } from "fs";
|
|
6943
7189
|
async function withRunnerLock(runnerId, fn) {
|
|
6944
7190
|
const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
|
|
6945
7191
|
const next = prev.then(fn, () => fn());
|
|
@@ -7057,7 +7303,7 @@ async function spawnSubAgent(chatId, opts) {
|
|
|
7057
7303
|
async function startAgent(agentId, chatId, opts) {
|
|
7058
7304
|
const db3 = getDb();
|
|
7059
7305
|
const runner = getRunner(opts.runner);
|
|
7060
|
-
if (opts.cwd && !
|
|
7306
|
+
if (opts.cwd && !existsSync11(opts.cwd)) {
|
|
7061
7307
|
const msg = `Directory not found: ${opts.cwd}`;
|
|
7062
7308
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
7063
7309
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -7079,7 +7325,7 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
7079
7325
|
return;
|
|
7080
7326
|
}
|
|
7081
7327
|
const exePath = runner.getExecutablePath();
|
|
7082
|
-
if (exePath.startsWith("/") && !
|
|
7328
|
+
if (exePath.startsWith("/") && !existsSync11(exePath)) {
|
|
7083
7329
|
const msg = `Executable not found: ${exePath}`;
|
|
7084
7330
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
7085
7331
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -7349,10 +7595,10 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
7349
7595
|
function diagnoseSpawnError(err, exePath, cwd) {
|
|
7350
7596
|
const nodeErr = err;
|
|
7351
7597
|
if (nodeErr.code === "ENOENT") {
|
|
7352
|
-
if (cwd && !
|
|
7598
|
+
if (cwd && !existsSync11(cwd)) {
|
|
7353
7599
|
return `Directory not found: ${cwd}`;
|
|
7354
7600
|
}
|
|
7355
|
-
if (exePath.startsWith("/") && !
|
|
7601
|
+
if (exePath.startsWith("/") && !existsSync11(exePath)) {
|
|
7356
7602
|
return `Executable not found: ${exePath}`;
|
|
7357
7603
|
}
|
|
7358
7604
|
return `ENOENT spawning ${exePath} (cwd: ${cwd ?? "inherited"}) \u2014 check that both the binary and directory exist`;
|
|
@@ -7741,7 +7987,7 @@ var init_registry2 = __esm({
|
|
|
7741
7987
|
});
|
|
7742
7988
|
|
|
7743
7989
|
// src/dashboard/routes/orchestrator.ts
|
|
7744
|
-
import { existsSync as
|
|
7990
|
+
import { existsSync as existsSync12 } from "fs";
|
|
7745
7991
|
var handleSpawn, handleCancel, handleCancelAll, handleCreateTask, handleUpdateTask, handleSendMessage, handleReadInbox, handleSetState, handleGetState, handleListState, handleBroadcast, handleListRunners, handleListMcps, handleListTemplates, handleCheckAgent;
|
|
7746
7992
|
var init_orchestrator2 = __esm({
|
|
7747
7993
|
"src/dashboard/routes/orchestrator.ts"() {
|
|
@@ -7757,7 +8003,7 @@ var init_orchestrator2 = __esm({
|
|
|
7757
8003
|
handleSpawn = async (req, res) => {
|
|
7758
8004
|
try {
|
|
7759
8005
|
const body = JSON.parse(await readBody(req));
|
|
7760
|
-
if (body.cwd && !
|
|
8006
|
+
if (body.cwd && !existsSync12(body.cwd)) {
|
|
7761
8007
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
7762
8008
|
}
|
|
7763
8009
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -9024,8 +9270,8 @@ __export(analyze_exports, {
|
|
|
9024
9270
|
});
|
|
9025
9271
|
import { spawn as spawn4 } from "child_process";
|
|
9026
9272
|
import { createInterface as createInterface3 } from "readline";
|
|
9027
|
-
import { readFileSync as readFileSync6, existsSync as
|
|
9028
|
-
import { join as
|
|
9273
|
+
import { readFileSync as readFileSync6, existsSync as existsSync13, readdirSync as readdirSync7, statSync as statSync5 } from "fs";
|
|
9274
|
+
import { join as join12 } from "path";
|
|
9029
9275
|
import { homedir as homedir4 } from "os";
|
|
9030
9276
|
function applySignalDecay(confidence, createdAt) {
|
|
9031
9277
|
const ageMs = Date.now() - (/* @__PURE__ */ new Date(createdAt + (createdAt.endsWith("Z") ? "" : "Z"))).getTime();
|
|
@@ -9034,16 +9280,16 @@ function applySignalDecay(confidence, createdAt) {
|
|
|
9034
9280
|
return decayed >= SIGNAL_DECAY_MIN_CONFIDENCE ? Math.round(decayed * 100) / 100 : 0;
|
|
9035
9281
|
}
|
|
9036
9282
|
function discoverReflectionTargets() {
|
|
9037
|
-
const ccClawHome =
|
|
9283
|
+
const ccClawHome = join12(homedir4(), ".cc-claw");
|
|
9038
9284
|
const targets = [];
|
|
9039
9285
|
try {
|
|
9040
|
-
const skillsDir =
|
|
9041
|
-
if (
|
|
9042
|
-
for (const entry of
|
|
9043
|
-
const entryPath =
|
|
9044
|
-
if (!
|
|
9045
|
-
const skillFile =
|
|
9046
|
-
if (!
|
|
9286
|
+
const skillsDir = join12(ccClawHome, "workspace", "skills");
|
|
9287
|
+
if (existsSync13(skillsDir)) {
|
|
9288
|
+
for (const entry of readdirSync7(skillsDir)) {
|
|
9289
|
+
const entryPath = join12(skillsDir, entry);
|
|
9290
|
+
if (!statSync5(entryPath).isDirectory()) continue;
|
|
9291
|
+
const skillFile = join12(entryPath, "SKILL.md");
|
|
9292
|
+
if (!existsSync13(skillFile)) continue;
|
|
9047
9293
|
let desc = "skill";
|
|
9048
9294
|
try {
|
|
9049
9295
|
const content = readFileSync6(skillFile, "utf-8");
|
|
@@ -9057,9 +9303,9 @@ function discoverReflectionTargets() {
|
|
|
9057
9303
|
} catch {
|
|
9058
9304
|
}
|
|
9059
9305
|
try {
|
|
9060
|
-
const contextDir =
|
|
9061
|
-
if (
|
|
9062
|
-
for (const entry of
|
|
9306
|
+
const contextDir = join12(ccClawHome, "workspace", "context");
|
|
9307
|
+
if (existsSync13(contextDir)) {
|
|
9308
|
+
for (const entry of readdirSync7(contextDir)) {
|
|
9063
9309
|
if (!entry.endsWith(".md")) continue;
|
|
9064
9310
|
const name = entry.replace(/\.md$/, "");
|
|
9065
9311
|
targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
|
|
@@ -9247,7 +9493,7 @@ function resolveReflectionAdapter(chatId) {
|
|
|
9247
9493
|
}
|
|
9248
9494
|
function readIdentityFile(filename) {
|
|
9249
9495
|
try {
|
|
9250
|
-
return readFileSync6(
|
|
9496
|
+
return readFileSync6(join12(IDENTITY_PATH, filename), "utf-8");
|
|
9251
9497
|
} catch {
|
|
9252
9498
|
return "";
|
|
9253
9499
|
}
|
|
@@ -9395,7 +9641,7 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
9395
9641
|
const availableTargets = discoverReflectionTargets();
|
|
9396
9642
|
const SKILL_CONTENT_CAP = 15e3;
|
|
9397
9643
|
const skillContents = [];
|
|
9398
|
-
const ccClawHome =
|
|
9644
|
+
const ccClawHome = join12(homedir4(), ".cc-claw");
|
|
9399
9645
|
const signalCorpus = signals.map((s) => s.trigger).join(" ").toLowerCase();
|
|
9400
9646
|
const convCorpus = (conversations ?? "").toLowerCase();
|
|
9401
9647
|
const searchCorpus = signalCorpus + " " + convCorpus;
|
|
@@ -9408,8 +9654,8 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
9408
9654
|
const isRelevant = searchCorpus.includes(skillNameNorm) || searchCorpus.includes(skillName.toLowerCase()) || descNorm.split(/\s+/).some((word) => word.length > 4 && searchCorpus.includes(word));
|
|
9409
9655
|
if (!isRelevant) continue;
|
|
9410
9656
|
try {
|
|
9411
|
-
const fullPath =
|
|
9412
|
-
if (
|
|
9657
|
+
const fullPath = join12(ccClawHome, target.path);
|
|
9658
|
+
if (existsSync13(fullPath)) {
|
|
9413
9659
|
const content = readFileSync6(fullPath, "utf-8");
|
|
9414
9660
|
if (totalSkillChars + content.length > SKILL_CONTENT_CAP) break;
|
|
9415
9661
|
skillContents.push({ path: target.path, content });
|
|
@@ -9615,8 +9861,8 @@ __export(apply_exports, {
|
|
|
9615
9861
|
isTargetAllowed: () => isTargetAllowed,
|
|
9616
9862
|
rollbackInsight: () => rollbackInsight
|
|
9617
9863
|
});
|
|
9618
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as
|
|
9619
|
-
import { join as
|
|
9864
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync14, mkdirSync as mkdirSync7, readdirSync as readdirSync8, unlinkSync as unlinkSync5 } from "fs";
|
|
9865
|
+
import { join as join13, dirname as dirname3 } from "path";
|
|
9620
9866
|
function isTargetAllowed(relativePath) {
|
|
9621
9867
|
if (relativePath.includes("..")) return false;
|
|
9622
9868
|
if (!relativePath.endsWith(".md")) return false;
|
|
@@ -9667,10 +9913,10 @@ function applyDiff(original, diff, action) {
|
|
|
9667
9913
|
return original;
|
|
9668
9914
|
}
|
|
9669
9915
|
function pruneBackups(absolutePath) {
|
|
9670
|
-
const dir =
|
|
9916
|
+
const dir = dirname3(absolutePath);
|
|
9671
9917
|
const baseName = absolutePath.split("/").pop() ?? "";
|
|
9672
9918
|
try {
|
|
9673
|
-
const backups =
|
|
9919
|
+
const backups = readdirSync8(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join13(dir, f));
|
|
9674
9920
|
while (backups.length > MAX_BACKUPS_PER_FILE) {
|
|
9675
9921
|
const oldest = backups.shift();
|
|
9676
9922
|
try {
|
|
@@ -9696,9 +9942,9 @@ async function applyInsight(insightId) {
|
|
|
9696
9942
|
if (!isTargetAllowed(insight.targetFile)) {
|
|
9697
9943
|
return { success: false, message: `Target file "${insight.targetFile}" is not in the allowed list` };
|
|
9698
9944
|
}
|
|
9699
|
-
const absolutePath =
|
|
9945
|
+
const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
|
|
9700
9946
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
9701
|
-
if (
|
|
9947
|
+
if (existsSync14(absolutePath)) {
|
|
9702
9948
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
9703
9949
|
const lineCount = currentContent.split("\n").length;
|
|
9704
9950
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
@@ -9720,7 +9966,7 @@ async function applyInsight(insightId) {
|
|
|
9720
9966
|
};
|
|
9721
9967
|
}
|
|
9722
9968
|
let original = "";
|
|
9723
|
-
if (
|
|
9969
|
+
if (existsSync14(absolutePath)) {
|
|
9724
9970
|
original = readFileSync7(absolutePath, "utf-8");
|
|
9725
9971
|
} else if (insight.proposedAction !== "create") {
|
|
9726
9972
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
@@ -9728,9 +9974,9 @@ async function applyInsight(insightId) {
|
|
|
9728
9974
|
const timestamp = Date.now();
|
|
9729
9975
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
9730
9976
|
try {
|
|
9731
|
-
const parentDir =
|
|
9732
|
-
if (!
|
|
9733
|
-
|
|
9977
|
+
const parentDir = dirname3(absolutePath);
|
|
9978
|
+
if (!existsSync14(parentDir)) {
|
|
9979
|
+
mkdirSync7(parentDir, { recursive: true });
|
|
9734
9980
|
}
|
|
9735
9981
|
if (original) {
|
|
9736
9982
|
writeFileSync5(backupPath, original, "utf-8");
|
|
@@ -9793,7 +10039,7 @@ async function rollbackInsight(insightId) {
|
|
|
9793
10039
|
} catch {
|
|
9794
10040
|
return { success: false, message: `Insight #${insightId} has malformed rollback data` };
|
|
9795
10041
|
}
|
|
9796
|
-
const absolutePath =
|
|
10042
|
+
const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
|
|
9797
10043
|
try {
|
|
9798
10044
|
writeFileSync5(absolutePath, rollback.original, "utf-8");
|
|
9799
10045
|
updateInsightStatus(db3, insightId, "rolled_back");
|
|
@@ -9826,8 +10072,8 @@ function calculateDrift(chatId) {
|
|
|
9826
10072
|
if (!row || !row.baselineSoulMd && !row.baselineUserMd) {
|
|
9827
10073
|
return null;
|
|
9828
10074
|
}
|
|
9829
|
-
const soulPath =
|
|
9830
|
-
const userPath =
|
|
10075
|
+
const soulPath = join13(CC_CLAW_HOME, "identity/SOUL.md");
|
|
10076
|
+
const userPath = join13(CC_CLAW_HOME, "identity/USER.md");
|
|
9831
10077
|
const soulDrift = computeLineDrift(row.baselineSoulMd, soulPath);
|
|
9832
10078
|
const userDrift = computeLineDrift(row.baselineUserMd, userPath);
|
|
9833
10079
|
return { soulDrift, userDrift };
|
|
@@ -9836,7 +10082,7 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
9836
10082
|
if (!baseline) return 0;
|
|
9837
10083
|
let current = "";
|
|
9838
10084
|
try {
|
|
9839
|
-
if (
|
|
10085
|
+
if (existsSync14(absolutePath)) {
|
|
9840
10086
|
current = readFileSync7(absolutePath, "utf-8");
|
|
9841
10087
|
}
|
|
9842
10088
|
} catch {
|
|
@@ -9932,11 +10178,11 @@ var init_evolve = __esm({
|
|
|
9932
10178
|
const body = JSON.parse(await readBody(req));
|
|
9933
10179
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
9934
10180
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
9935
|
-
const { join:
|
|
10181
|
+
const { join: join30 } = await import("path");
|
|
9936
10182
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
9937
10183
|
const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
|
|
9938
|
-
const soulPath =
|
|
9939
|
-
const userPath =
|
|
10184
|
+
const soulPath = join30(home, "identity/SOUL.md");
|
|
10185
|
+
const userPath = join30(home, "identity/USER.md");
|
|
9940
10186
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
9941
10187
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
9942
10188
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -10882,7 +11128,7 @@ function askAgent(chatId, userMessage, opts) {
|
|
|
10882
11128
|
return withChatLock(chatId, () => askAgentImpl(chatId, userMessage, opts));
|
|
10883
11129
|
}
|
|
10884
11130
|
async function askAgentImpl(chatId, userMessage, opts) {
|
|
10885
|
-
const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, onModelDowngrade, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId } = opts ?? {};
|
|
11131
|
+
const { cwd, onStream, model: model2, backend: backend2, permMode, onToolAction, bootstrapTier, timeoutMs, maxTurns, onSlotRotation, onModelDowngrade, agentMode: optsAgentMode, onSubagentActivity, settingsSourceChatId, planningDirective } = opts ?? {};
|
|
10886
11132
|
const settingsChat = settingsSourceChatId ?? chatId;
|
|
10887
11133
|
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
10888
11134
|
const mode = permMode ?? getMode(settingsChat);
|
|
@@ -10892,7 +11138,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
10892
11138
|
const tier = bootstrapTier ?? "full";
|
|
10893
11139
|
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
10894
11140
|
const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
|
|
10895
|
-
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx);
|
|
11141
|
+
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx, planningDirective);
|
|
10896
11142
|
const existingSessionId = settingsSourceChatId ? null : getSessionId(settingsChat);
|
|
10897
11143
|
const allowedTools = getEnabledTools(settingsChat);
|
|
10898
11144
|
const mcpConfigPath = tier !== "slim" && effectiveAgentMode !== "native" && MCP_CONFIG_FLAG[adapter.id] ? getMcpConfigPath(chatId) : null;
|
|
@@ -11494,9 +11740,9 @@ function buildReviewCompleteMessage(results) {
|
|
|
11494
11740
|
|
|
11495
11741
|
Skipped proposals will appear in your next review.`;
|
|
11496
11742
|
}
|
|
11497
|
-
function formatNightlySummary(insights) {
|
|
11498
|
-
const
|
|
11499
|
-
const header2 = `Nightly Reflection \u2014 ${
|
|
11743
|
+
function formatNightlySummary(insights, totalPending) {
|
|
11744
|
+
const displayCount = totalPending ?? insights.length;
|
|
11745
|
+
const header2 = `Nightly Reflection \u2014 ${displayCount} proposal${displayCount === 1 ? "" : "s"} ready`;
|
|
11500
11746
|
const list = insights.map((ins, i) => `${i + 1}. [${ins.category}] ${ins.insight}`).join("\n");
|
|
11501
11747
|
return `${header2}
|
|
11502
11748
|
|
|
@@ -11607,8 +11853,8 @@ var init_propose = __esm({
|
|
|
11607
11853
|
});
|
|
11608
11854
|
|
|
11609
11855
|
// src/bootstrap/profile.ts
|
|
11610
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as
|
|
11611
|
-
import { join as
|
|
11856
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync15 } from "fs";
|
|
11857
|
+
import { join as join14 } from "path";
|
|
11612
11858
|
function hasActiveProfile(chatId) {
|
|
11613
11859
|
return activeProfiles.has(chatId);
|
|
11614
11860
|
}
|
|
@@ -11737,7 +11983,7 @@ function extractUserUpdates(text) {
|
|
|
11737
11983
|
return { cleanText, updates };
|
|
11738
11984
|
}
|
|
11739
11985
|
function appendToUserProfile(key, value) {
|
|
11740
|
-
if (!
|
|
11986
|
+
if (!existsSync15(USER_PATH2)) return;
|
|
11741
11987
|
const content = readFileSync8(USER_PATH2, "utf-8");
|
|
11742
11988
|
const line = `- **${key}**: ${value}`;
|
|
11743
11989
|
if (content.includes(line)) return;
|
|
@@ -11753,7 +11999,7 @@ var init_profile = __esm({
|
|
|
11753
11999
|
"use strict";
|
|
11754
12000
|
init_paths();
|
|
11755
12001
|
init_log();
|
|
11756
|
-
USER_PATH2 =
|
|
12002
|
+
USER_PATH2 = join14(IDENTITY_PATH, "USER.md");
|
|
11757
12003
|
activeProfiles = /* @__PURE__ */ new Map();
|
|
11758
12004
|
}
|
|
11759
12005
|
});
|
|
@@ -12584,6 +12830,88 @@ var init_classify2 = __esm({
|
|
|
12584
12830
|
}
|
|
12585
12831
|
});
|
|
12586
12832
|
|
|
12833
|
+
// src/execution/gate.ts
|
|
12834
|
+
function shouldRequireApproval(input) {
|
|
12835
|
+
if (input.execMode !== "approved") return false;
|
|
12836
|
+
if (input.intent !== "agentic") return false;
|
|
12837
|
+
if (input.isResuming) return false;
|
|
12838
|
+
if (input.messageText.startsWith(">>")) return false;
|
|
12839
|
+
if (EXEMPT_TIERS.has(input.bootstrapTier)) return false;
|
|
12840
|
+
if (input.isSideQuest) return false;
|
|
12841
|
+
return true;
|
|
12842
|
+
}
|
|
12843
|
+
function buildPlanningDirective() {
|
|
12844
|
+
return [
|
|
12845
|
+
"## PLANNING MODE \u2014 Read-Only",
|
|
12846
|
+
"",
|
|
12847
|
+
"You are in PLANNING mode. Your goal is to research and present a plan.",
|
|
12848
|
+
"",
|
|
12849
|
+
"**ALLOWED:**",
|
|
12850
|
+
"- Read files, directories, and code",
|
|
12851
|
+
"- Load and read skills",
|
|
12852
|
+
"- Search the codebase (grep, glob, find)",
|
|
12853
|
+
"- Search the web for documentation or solutions",
|
|
12854
|
+
"- Analyze and reason about architecture",
|
|
12855
|
+
"",
|
|
12856
|
+
"**NOT ALLOWED:**",
|
|
12857
|
+
"- Do NOT create, modify, or delete any files",
|
|
12858
|
+
"- Do NOT run shell commands that mutate state",
|
|
12859
|
+
"- Do NOT write code or make edits",
|
|
12860
|
+
"- Do NOT install packages or dependencies",
|
|
12861
|
+
"",
|
|
12862
|
+
"**YOUR TASK:**",
|
|
12863
|
+
"Research the request thoroughly, then present a clear, concise plan",
|
|
12864
|
+
"of what you will do. The user will review and approve before you execute.",
|
|
12865
|
+
"Structure your plan with numbered steps and be specific about which",
|
|
12866
|
+
"files you will modify and what changes you will make."
|
|
12867
|
+
].join("\n");
|
|
12868
|
+
}
|
|
12869
|
+
function storePendingPlan(chatId, plan, originalMessage) {
|
|
12870
|
+
pendingPlans.set(chatId, {
|
|
12871
|
+
plan,
|
|
12872
|
+
originalMessage,
|
|
12873
|
+
createdAt: Date.now()
|
|
12874
|
+
});
|
|
12875
|
+
}
|
|
12876
|
+
function getPendingPlan(chatId) {
|
|
12877
|
+
const entry = pendingPlans.get(chatId);
|
|
12878
|
+
if (!entry) return void 0;
|
|
12879
|
+
if (Date.now() - entry.createdAt > PLAN_TTL_MS) {
|
|
12880
|
+
pendingPlans.delete(chatId);
|
|
12881
|
+
return void 0;
|
|
12882
|
+
}
|
|
12883
|
+
return entry;
|
|
12884
|
+
}
|
|
12885
|
+
function removePendingPlan(chatId) {
|
|
12886
|
+
pendingPlans.delete(chatId);
|
|
12887
|
+
}
|
|
12888
|
+
function setRejectionMode(chatId) {
|
|
12889
|
+
rejectionModes.set(chatId, Date.now());
|
|
12890
|
+
}
|
|
12891
|
+
function getRejectionMode(chatId) {
|
|
12892
|
+
const createdAt = rejectionModes.get(chatId);
|
|
12893
|
+
if (createdAt === void 0) return false;
|
|
12894
|
+
if (Date.now() - createdAt > REJECTION_TTL_MS) {
|
|
12895
|
+
rejectionModes.delete(chatId);
|
|
12896
|
+
return false;
|
|
12897
|
+
}
|
|
12898
|
+
return true;
|
|
12899
|
+
}
|
|
12900
|
+
function clearRejectionMode(chatId) {
|
|
12901
|
+
rejectionModes.delete(chatId);
|
|
12902
|
+
}
|
|
12903
|
+
var EXEMPT_TIERS, PLAN_TTL_MS, pendingPlans, REJECTION_TTL_MS, rejectionModes;
|
|
12904
|
+
var init_gate = __esm({
|
|
12905
|
+
"src/execution/gate.ts"() {
|
|
12906
|
+
"use strict";
|
|
12907
|
+
EXEMPT_TIERS = /* @__PURE__ */ new Set(["slim", "heartbeat", "chat"]);
|
|
12908
|
+
PLAN_TTL_MS = 5 * 60 * 1e3;
|
|
12909
|
+
pendingPlans = /* @__PURE__ */ new Map();
|
|
12910
|
+
REJECTION_TTL_MS = 5 * 60 * 1e3;
|
|
12911
|
+
rejectionModes = /* @__PURE__ */ new Map();
|
|
12912
|
+
}
|
|
12913
|
+
});
|
|
12914
|
+
|
|
12587
12915
|
// src/router/helpers.ts
|
|
12588
12916
|
import { resolve as resolvePath } from "path";
|
|
12589
12917
|
function parseMcpListOutput(output2) {
|
|
@@ -13284,9 +13612,9 @@ var init_stt = __esm({
|
|
|
13284
13612
|
});
|
|
13285
13613
|
|
|
13286
13614
|
// src/media/image-gen.ts
|
|
13287
|
-
import { mkdirSync as
|
|
13615
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync16, unlink as unlink2, readdir, stat } from "fs";
|
|
13288
13616
|
import { writeFile } from "fs/promises";
|
|
13289
|
-
import { join as
|
|
13617
|
+
import { join as join15 } from "path";
|
|
13290
13618
|
async function generateImage(prompt) {
|
|
13291
13619
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
13292
13620
|
if (!apiKey) {
|
|
@@ -13333,12 +13661,12 @@ async function generateImage(prompt) {
|
|
|
13333
13661
|
if (!imageData) {
|
|
13334
13662
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
13335
13663
|
}
|
|
13336
|
-
if (!
|
|
13337
|
-
|
|
13664
|
+
if (!existsSync16(IMAGE_OUTPUT_DIR)) {
|
|
13665
|
+
mkdirSync8(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
13338
13666
|
}
|
|
13339
13667
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
13340
13668
|
const filename = `img_${Date.now()}.${ext}`;
|
|
13341
|
-
const filePath =
|
|
13669
|
+
const filePath = join15(IMAGE_OUTPUT_DIR, filename);
|
|
13342
13670
|
const buffer = Buffer.from(imageData, "base64");
|
|
13343
13671
|
await writeFile(filePath, buffer);
|
|
13344
13672
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
@@ -13356,7 +13684,7 @@ function cleanupGeneratedImage(filePath) {
|
|
|
13356
13684
|
function pruneImageCache() {
|
|
13357
13685
|
readdir(IMAGE_OUTPUT_DIR, (err, files) => {
|
|
13358
13686
|
if (err || !files) return;
|
|
13359
|
-
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) =>
|
|
13687
|
+
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join15(IMAGE_OUTPUT_DIR, f));
|
|
13360
13688
|
if (imageFiles.length === 0) return;
|
|
13361
13689
|
const now = Date.now();
|
|
13362
13690
|
let statsPending = imageFiles.length;
|
|
@@ -13388,8 +13716,8 @@ var init_image_gen = __esm({
|
|
|
13388
13716
|
MAX_GENERATED_IMAGES = 20;
|
|
13389
13717
|
IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
13390
13718
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
13391
|
-
IMAGE_OUTPUT_DIR =
|
|
13392
|
-
process.env.CC_CLAW_HOME ??
|
|
13719
|
+
IMAGE_OUTPUT_DIR = join15(
|
|
13720
|
+
process.env.CC_CLAW_HOME ?? join15(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
13393
13721
|
"data",
|
|
13394
13722
|
"images"
|
|
13395
13723
|
);
|
|
@@ -13862,7 +14190,7 @@ var init_video = __esm({
|
|
|
13862
14190
|
});
|
|
13863
14191
|
|
|
13864
14192
|
// src/router/media.ts
|
|
13865
|
-
import { join as
|
|
14193
|
+
import { join as join16 } from "path";
|
|
13866
14194
|
import { mkdir, writeFile as writeFile2, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
|
|
13867
14195
|
function getMediaRetentionMs() {
|
|
13868
14196
|
const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
|
|
@@ -13871,7 +14199,7 @@ function getMediaRetentionMs() {
|
|
|
13871
14199
|
async function saveMedia(buffer, prefix, ext) {
|
|
13872
14200
|
await mkdir(MEDIA_INCOMING_PATH, { recursive: true });
|
|
13873
14201
|
const filename = `${prefix}-${Date.now()}.${ext}`;
|
|
13874
|
-
const fullPath =
|
|
14202
|
+
const fullPath = join16(MEDIA_INCOMING_PATH, filename);
|
|
13875
14203
|
await writeFile2(fullPath, buffer);
|
|
13876
14204
|
return fullPath;
|
|
13877
14205
|
}
|
|
@@ -13885,7 +14213,7 @@ async function cleanupOldMedia() {
|
|
|
13885
14213
|
let removed = 0;
|
|
13886
14214
|
for (const file of files) {
|
|
13887
14215
|
try {
|
|
13888
|
-
const filePath =
|
|
14216
|
+
const filePath = join16(MEDIA_INCOMING_PATH, file);
|
|
13889
14217
|
const s = await stat2(filePath);
|
|
13890
14218
|
if (now - s.mtimeMs > retentionMs) {
|
|
13891
14219
|
await unlink3(filePath);
|
|
@@ -14068,7 +14396,7 @@ var init_media = __esm({
|
|
|
14068
14396
|
init_store5();
|
|
14069
14397
|
init_helpers();
|
|
14070
14398
|
init_response();
|
|
14071
|
-
MEDIA_INCOMING_PATH =
|
|
14399
|
+
MEDIA_INCOMING_PATH = join16(MEDIA_PATH, "incoming");
|
|
14072
14400
|
}
|
|
14073
14401
|
});
|
|
14074
14402
|
|
|
@@ -14204,7 +14532,7 @@ __export(discover_exports, {
|
|
|
14204
14532
|
import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
|
|
14205
14533
|
import { createHash } from "crypto";
|
|
14206
14534
|
import { homedir as homedir5 } from "os";
|
|
14207
|
-
import { join as
|
|
14535
|
+
import { join as join17 } from "path";
|
|
14208
14536
|
function invalidateSkillCache() {
|
|
14209
14537
|
cachedSkills = null;
|
|
14210
14538
|
cacheTimestamp = 0;
|
|
@@ -14222,7 +14550,7 @@ async function discoverAllSkills() {
|
|
|
14222
14550
|
const rawSkills = [];
|
|
14223
14551
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
14224
14552
|
for (const backendId of getAllBackendIds()) {
|
|
14225
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [
|
|
14553
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join17(homedir5(), `.${backendId}`, "skills")];
|
|
14226
14554
|
for (const dir of dirs) {
|
|
14227
14555
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
14228
14556
|
}
|
|
@@ -14250,7 +14578,7 @@ async function scanSkillDir(skillsDir, source) {
|
|
|
14250
14578
|
let content;
|
|
14251
14579
|
let resolvedPath;
|
|
14252
14580
|
for (const candidate of SKILL_FILE_CANDIDATES) {
|
|
14253
|
-
const p =
|
|
14581
|
+
const p = join17(skillsDir, entry.name, candidate);
|
|
14254
14582
|
try {
|
|
14255
14583
|
content = await readFile4(p, "utf-8");
|
|
14256
14584
|
resolvedPath = p;
|
|
@@ -14354,15 +14682,15 @@ var init_discover = __esm({
|
|
|
14354
14682
|
init_backends();
|
|
14355
14683
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
14356
14684
|
BACKEND_SKILL_DIRS = {
|
|
14357
|
-
claude: [
|
|
14358
|
-
gemini: [
|
|
14685
|
+
claude: [join17(homedir5(), ".claude", "skills")],
|
|
14686
|
+
gemini: [join17(homedir5(), ".gemini", "skills")],
|
|
14359
14687
|
codex: [
|
|
14360
|
-
|
|
14361
|
-
|
|
14688
|
+
join17(homedir5(), ".agents", "skills"),
|
|
14689
|
+
join17(homedir5(), ".codex", "skills")
|
|
14362
14690
|
],
|
|
14363
14691
|
cursor: [
|
|
14364
|
-
|
|
14365
|
-
|
|
14692
|
+
join17(homedir5(), ".cursor", "skills"),
|
|
14693
|
+
join17(homedir5(), ".cursor", "skills-cursor")
|
|
14366
14694
|
]
|
|
14367
14695
|
};
|
|
14368
14696
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -14378,8 +14706,8 @@ __export(install_exports, {
|
|
|
14378
14706
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
14379
14707
|
});
|
|
14380
14708
|
import { mkdir as mkdir2, readdir as readdir4, readFile as readFile5, cp } from "fs/promises";
|
|
14381
|
-
import { existsSync as
|
|
14382
|
-
import { join as
|
|
14709
|
+
import { existsSync as existsSync17 } from "fs";
|
|
14710
|
+
import { join as join18, basename } from "path";
|
|
14383
14711
|
import { execSync as execSync5 } from "child_process";
|
|
14384
14712
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
14385
14713
|
let repoUrl;
|
|
@@ -14390,36 +14718,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
14390
14718
|
}
|
|
14391
14719
|
repoUrl = parsed.cloneUrl;
|
|
14392
14720
|
subPath = parsed.subPath;
|
|
14393
|
-
const tmpDir =
|
|
14721
|
+
const tmpDir = join18("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
14394
14722
|
try {
|
|
14395
14723
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
14396
14724
|
execSync5(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
14397
14725
|
stdio: "pipe",
|
|
14398
14726
|
timeout: 3e4
|
|
14399
14727
|
});
|
|
14400
|
-
if (!
|
|
14728
|
+
if (!existsSync17(join18(tmpDir, ".git"))) {
|
|
14401
14729
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
14402
14730
|
}
|
|
14403
|
-
const searchRoot = subPath ?
|
|
14731
|
+
const searchRoot = subPath ? join18(tmpDir, subPath) : tmpDir;
|
|
14404
14732
|
const skillDir = await findSkillDir(searchRoot);
|
|
14405
14733
|
if (!skillDir) {
|
|
14406
14734
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
14407
14735
|
}
|
|
14408
14736
|
const skillFolderName = basename(skillDir);
|
|
14409
|
-
const destDir =
|
|
14410
|
-
if (
|
|
14737
|
+
const destDir = join18(SKILLS_PATH, skillFolderName);
|
|
14738
|
+
if (existsSync17(destDir)) {
|
|
14411
14739
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
14412
14740
|
}
|
|
14413
14741
|
await mkdir2(destDir, { recursive: true });
|
|
14414
14742
|
await cp(skillDir, destDir, { recursive: true });
|
|
14415
14743
|
let skillName = skillFolderName;
|
|
14416
14744
|
try {
|
|
14417
|
-
const content = await readFile5(
|
|
14745
|
+
const content = await readFile5(join18(destDir, "SKILL.md"), "utf-8");
|
|
14418
14746
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14419
14747
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14420
14748
|
} catch {
|
|
14421
14749
|
try {
|
|
14422
|
-
const content = await readFile5(
|
|
14750
|
+
const content = await readFile5(join18(destDir, "skill.md"), "utf-8");
|
|
14423
14751
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14424
14752
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14425
14753
|
} catch {
|
|
@@ -14454,15 +14782,15 @@ function parseGitHubUrl(input) {
|
|
|
14454
14782
|
async function findSkillDir(root) {
|
|
14455
14783
|
const candidates = ["SKILL.md", "skill.md"];
|
|
14456
14784
|
for (const c of candidates) {
|
|
14457
|
-
if (
|
|
14785
|
+
if (existsSync17(join18(root, c))) return root;
|
|
14458
14786
|
}
|
|
14459
14787
|
try {
|
|
14460
14788
|
const entries = await readdir4(root, { withFileTypes: true });
|
|
14461
14789
|
for (const entry of entries) {
|
|
14462
14790
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14463
14791
|
for (const c of candidates) {
|
|
14464
|
-
if (
|
|
14465
|
-
return
|
|
14792
|
+
if (existsSync17(join18(root, entry.name, c))) {
|
|
14793
|
+
return join18(root, entry.name);
|
|
14466
14794
|
}
|
|
14467
14795
|
}
|
|
14468
14796
|
}
|
|
@@ -14474,15 +14802,15 @@ async function findSkillDir(root) {
|
|
|
14474
14802
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14475
14803
|
let subEntries;
|
|
14476
14804
|
try {
|
|
14477
|
-
subEntries = await readdir4(
|
|
14805
|
+
subEntries = await readdir4(join18(root, entry.name), { withFileTypes: true });
|
|
14478
14806
|
} catch {
|
|
14479
14807
|
continue;
|
|
14480
14808
|
}
|
|
14481
14809
|
for (const sub of subEntries) {
|
|
14482
14810
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
14483
14811
|
for (const c of candidates) {
|
|
14484
|
-
if (
|
|
14485
|
-
return
|
|
14812
|
+
if (existsSync17(join18(root, entry.name, sub.name, c))) {
|
|
14813
|
+
return join18(root, entry.name, sub.name);
|
|
14486
14814
|
}
|
|
14487
14815
|
}
|
|
14488
14816
|
}
|
|
@@ -14500,8 +14828,8 @@ var init_install = __esm({
|
|
|
14500
14828
|
});
|
|
14501
14829
|
|
|
14502
14830
|
// src/bootstrap/heartbeat.ts
|
|
14503
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
14504
|
-
import { join as
|
|
14831
|
+
import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
|
|
14832
|
+
import { join as join19 } from "path";
|
|
14505
14833
|
function initHeartbeat(channelReg) {
|
|
14506
14834
|
registry2 = channelReg;
|
|
14507
14835
|
}
|
|
@@ -14639,7 +14967,7 @@ ${healthLines.join("\n")}`);
|
|
|
14639
14967
|
sections.push(`[Active watches]
|
|
14640
14968
|
${watchLines.join("\n")}`);
|
|
14641
14969
|
}
|
|
14642
|
-
if (
|
|
14970
|
+
if (existsSync18(HEARTBEAT_MD_PATH)) {
|
|
14643
14971
|
try {
|
|
14644
14972
|
const custom = readFileSync9(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
14645
14973
|
if (custom) {
|
|
@@ -14687,7 +15015,7 @@ var init_heartbeat2 = __esm({
|
|
|
14687
15015
|
init_backends();
|
|
14688
15016
|
init_health2();
|
|
14689
15017
|
init_log();
|
|
14690
|
-
HEARTBEAT_MD_PATH =
|
|
15018
|
+
HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
14691
15019
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
14692
15020
|
registry2 = null;
|
|
14693
15021
|
activeTimers = /* @__PURE__ */ new Map();
|
|
@@ -15744,9 +16072,9 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15744
16072
|
await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
|
|
15745
16073
|
} else {
|
|
15746
16074
|
const insightIds = pending.slice(0, 5).map((p) => p.id);
|
|
15747
|
-
createReviewSession2(getDb(),
|
|
16075
|
+
createReviewSession2(getDb(), chatId, insightIds);
|
|
15748
16076
|
await channel.sendText(chatId, `${pending.length} proposal(s) ready. Let's review them one by one.`, { parseMode: "plain" });
|
|
15749
|
-
await sendCurrentProposal(
|
|
16077
|
+
await sendCurrentProposal(chatId, channel);
|
|
15750
16078
|
}
|
|
15751
16079
|
break;
|
|
15752
16080
|
}
|
|
@@ -15904,13 +16232,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15904
16232
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15905
16233
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
15906
16234
|
if (current === "frozen") {
|
|
15907
|
-
const { readFileSync: readFileSync22, existsSync:
|
|
15908
|
-
const { join:
|
|
16235
|
+
const { readFileSync: readFileSync22, existsSync: existsSync50 } = await import("fs");
|
|
16236
|
+
const { join: join30 } = await import("path");
|
|
15909
16237
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
15910
|
-
const soulPath =
|
|
15911
|
-
const userPath =
|
|
15912
|
-
const soul =
|
|
15913
|
-
const user =
|
|
16238
|
+
const soulPath = join30(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16239
|
+
const userPath = join30(CC_CLAW_HOME3, "identity/USER.md");
|
|
16240
|
+
const soul = existsSync50(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
|
|
16241
|
+
const user = existsSync50(userPath) ? readFileSync22(userPath, "utf-8") : "";
|
|
15914
16242
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
15915
16243
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
15916
16244
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -16063,6 +16391,29 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
16063
16391
|
}
|
|
16064
16392
|
break;
|
|
16065
16393
|
}
|
|
16394
|
+
case "mode":
|
|
16395
|
+
case "execmode": {
|
|
16396
|
+
const currentExecMode = getExecMode(chatId);
|
|
16397
|
+
const EXEC_MODES = {
|
|
16398
|
+
approved: "\u2705 Approved \u2014 AI shows a plan before acting",
|
|
16399
|
+
yolo: "\u26A1 YOLO \u2014 AI executes immediately"
|
|
16400
|
+
};
|
|
16401
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
16402
|
+
const buttons = Object.entries(EXEC_MODES).map(([id, label2]) => [{
|
|
16403
|
+
label: `${id === currentExecMode ? "\u2713 " : ""}${label2}`,
|
|
16404
|
+
data: `execmode:${id}`,
|
|
16405
|
+
...id === currentExecMode ? { style: "primary" } : {}
|
|
16406
|
+
}]);
|
|
16407
|
+
await channel.sendKeyboard(chatId, `Execution mode (current: <b>${currentExecMode}</b>):`, buttons);
|
|
16408
|
+
} else {
|
|
16409
|
+
const lines = ["Execution modes:", ""];
|
|
16410
|
+
for (const [id, label2] of Object.entries(EXEC_MODES)) {
|
|
16411
|
+
lines.push(`${id === currentExecMode ? "\u2713 " : " "}/mode ${id} \u2014 ${label2}`);
|
|
16412
|
+
}
|
|
16413
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
16414
|
+
}
|
|
16415
|
+
break;
|
|
16416
|
+
}
|
|
16066
16417
|
case "verbose": {
|
|
16067
16418
|
const currentVerbose = getVerboseLevel(chatId);
|
|
16068
16419
|
const buttons = Object.entries(VERBOSE_LEVELS).map(([id, label2]) => [{
|
|
@@ -17771,6 +18122,54 @@ ${PERM_MODES[chosen]}`,
|
|
|
17771
18122
|
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
|
|
17772
18123
|
}
|
|
17773
18124
|
return;
|
|
18125
|
+
} else if (data === "exec:approve") {
|
|
18126
|
+
const plan = getPendingPlan(chatId);
|
|
18127
|
+
if (!plan) {
|
|
18128
|
+
await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
|
|
18129
|
+
return;
|
|
18130
|
+
}
|
|
18131
|
+
removePendingPlan(chatId);
|
|
18132
|
+
await channel.sendText(chatId, "\u2705 Approved. Executing...", { parseMode: "plain" });
|
|
18133
|
+
const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
|
|
18134
|
+
await handleMessage2(
|
|
18135
|
+
{ text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
|
|
18136
|
+
channel
|
|
18137
|
+
);
|
|
18138
|
+
return;
|
|
18139
|
+
} else if (data === "exec:reject") {
|
|
18140
|
+
const plan = getPendingPlan(chatId);
|
|
18141
|
+
if (!plan) {
|
|
18142
|
+
await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
|
|
18143
|
+
return;
|
|
18144
|
+
}
|
|
18145
|
+
removePendingPlan(chatId);
|
|
18146
|
+
setRejectionMode(chatId);
|
|
18147
|
+
await channel.sendText(chatId, "\u270F\uFE0F Plan rejected. Send your feedback and I'll revise the plan.", { parseMode: "plain" });
|
|
18148
|
+
return;
|
|
18149
|
+
} else if (data === "exec:yolo") {
|
|
18150
|
+
const plan = getPendingPlan(chatId);
|
|
18151
|
+
if (!plan) {
|
|
18152
|
+
await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
|
|
18153
|
+
return;
|
|
18154
|
+
}
|
|
18155
|
+
removePendingPlan(chatId);
|
|
18156
|
+
setExecMode(chatId, "yolo");
|
|
18157
|
+
await channel.sendText(chatId, "\u26A1 Switched to YOLO mode. Executing without approval gate...", { parseMode: "plain" });
|
|
18158
|
+
const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
|
|
18159
|
+
await handleMessage2(
|
|
18160
|
+
{ text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
|
|
18161
|
+
channel
|
|
18162
|
+
);
|
|
18163
|
+
return;
|
|
18164
|
+
} else if (data.startsWith("execmode:")) {
|
|
18165
|
+
const mode = data.split(":")[1];
|
|
18166
|
+
if (mode === "approved" || mode === "yolo") {
|
|
18167
|
+
setExecMode(chatId, mode);
|
|
18168
|
+
const desc = mode === "approved" ? "AI will show a plan for approval before acting." : "AI will execute immediately without showing a plan.";
|
|
18169
|
+
await channel.sendText(chatId, `Execution mode set to <b>${mode}</b>.
|
|
18170
|
+
${desc}`, { parseMode: "html" });
|
|
18171
|
+
}
|
|
18172
|
+
return;
|
|
17774
18173
|
} else if (data.startsWith("model_sig:")) {
|
|
17775
18174
|
const value = data.slice(10);
|
|
17776
18175
|
setModelSignature(chatId, value);
|
|
@@ -18530,6 +18929,7 @@ var init_callbacks = __esm({
|
|
|
18530
18929
|
init_guard();
|
|
18531
18930
|
init_pagination();
|
|
18532
18931
|
init_stt();
|
|
18932
|
+
init_gate();
|
|
18533
18933
|
init_helpers();
|
|
18534
18934
|
init_response();
|
|
18535
18935
|
init_shell();
|
|
@@ -18689,6 +19089,33 @@ async function handleText(msg, channel) {
|
|
|
18689
19089
|
if (hasSqPrefix) {
|
|
18690
19090
|
text = sqCleanText;
|
|
18691
19091
|
}
|
|
19092
|
+
if (getRejectionMode(chatId)) {
|
|
19093
|
+
clearRejectionMode(chatId);
|
|
19094
|
+
await channel.sendTyping?.(chatId);
|
|
19095
|
+
const response = await askAgent(chatId, `Plan rejected. Feedback: "${text}". Revise your plan.`, {
|
|
19096
|
+
cwd: getCwd(chatId),
|
|
19097
|
+
model: model2,
|
|
19098
|
+
permMode: "yolo",
|
|
19099
|
+
agentMode: effectiveAgentMode
|
|
19100
|
+
});
|
|
19101
|
+
if (response.text) {
|
|
19102
|
+
storePendingPlan(chatId, response.text, text);
|
|
19103
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
19104
|
+
await channel.sendKeyboard(chatId, `\u{1F50D} ${response.text}`, [
|
|
19105
|
+
[
|
|
19106
|
+
{ label: "\u2705 Approve", data: "exec:approve", style: "success" },
|
|
19107
|
+
{ label: "\u274C Reject", data: "exec:reject", style: "danger" }
|
|
19108
|
+
],
|
|
19109
|
+
[
|
|
19110
|
+
{ label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
|
|
19111
|
+
]
|
|
19112
|
+
]);
|
|
19113
|
+
} else {
|
|
19114
|
+
await sendResponse(chatId, channel, response.text, void 0);
|
|
19115
|
+
}
|
|
19116
|
+
}
|
|
19117
|
+
return;
|
|
19118
|
+
}
|
|
18692
19119
|
{
|
|
18693
19120
|
const { getDiscussionMode: getDiscussionMode2, clearDiscussionMode: clearDiscussionMode2, setDiscussionMode: reenterDiscussion, getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
18694
19121
|
const discussInsightId = getDiscussionMode2(chatId);
|
|
@@ -18765,6 +19192,64 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
18765
19192
|
return;
|
|
18766
19193
|
}
|
|
18767
19194
|
}
|
|
19195
|
+
const execMode = getExecMode(chatId);
|
|
19196
|
+
const sessionId = getSessionId(chatId);
|
|
19197
|
+
const isResuming = !!sessionId;
|
|
19198
|
+
if (shouldRequireApproval({
|
|
19199
|
+
execMode,
|
|
19200
|
+
intent,
|
|
19201
|
+
bootstrapTier: bootstrapTier ?? "full",
|
|
19202
|
+
messageText: text,
|
|
19203
|
+
isResuming,
|
|
19204
|
+
isSideQuest: hasSqPrefix
|
|
19205
|
+
})) {
|
|
19206
|
+
const planDirective = buildPlanningDirective();
|
|
19207
|
+
let typingActive2 = true;
|
|
19208
|
+
const typingLoop2 = async () => {
|
|
19209
|
+
while (typingActive2) {
|
|
19210
|
+
try {
|
|
19211
|
+
await channel.sendTyping?.(chatId);
|
|
19212
|
+
} catch {
|
|
19213
|
+
}
|
|
19214
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
19215
|
+
}
|
|
19216
|
+
};
|
|
19217
|
+
typingLoop2().catch(() => {
|
|
19218
|
+
});
|
|
19219
|
+
try {
|
|
19220
|
+
const planResponse = await askAgent(chatId, cleanText || text, {
|
|
19221
|
+
cwd: getCwd(chatId),
|
|
19222
|
+
model: model2,
|
|
19223
|
+
permMode: "yolo",
|
|
19224
|
+
bootstrapTier: bootstrapTier ?? "full",
|
|
19225
|
+
agentMode: effectiveAgentMode,
|
|
19226
|
+
planningDirective: planDirective
|
|
19227
|
+
});
|
|
19228
|
+
typingActive2 = false;
|
|
19229
|
+
if (planResponse.text) {
|
|
19230
|
+
storePendingPlan(chatId, planResponse.text, cleanText || text);
|
|
19231
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
19232
|
+
await channel.sendKeyboard(chatId, `\u{1F50D} ${planResponse.text}`, [
|
|
19233
|
+
[
|
|
19234
|
+
{ label: "\u2705 Approve", data: "exec:approve", style: "success" },
|
|
19235
|
+
{ label: "\u274C Reject", data: "exec:reject", style: "danger" }
|
|
19236
|
+
],
|
|
19237
|
+
[
|
|
19238
|
+
{ label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
|
|
19239
|
+
]
|
|
19240
|
+
]);
|
|
19241
|
+
} else {
|
|
19242
|
+
await sendResponse(chatId, channel, planResponse.text, void 0);
|
|
19243
|
+
}
|
|
19244
|
+
} else {
|
|
19245
|
+
await channel.sendText(chatId, "(No plan generated \u2014 proceeding normally)", { parseMode: "plain" });
|
|
19246
|
+
}
|
|
19247
|
+
} catch (err) {
|
|
19248
|
+
typingActive2 = false;
|
|
19249
|
+
await channel.sendText(chatId, `\u26A0\uFE0F Planning error: ${err.message}`, { parseMode: "plain" });
|
|
19250
|
+
}
|
|
19251
|
+
return;
|
|
19252
|
+
}
|
|
18768
19253
|
let typingActive = true;
|
|
18769
19254
|
const typingLoop = async () => {
|
|
18770
19255
|
while (typingActive) {
|
|
@@ -18945,6 +19430,7 @@ var init_router = __esm({
|
|
|
18945
19430
|
init_wizard();
|
|
18946
19431
|
init_classify2();
|
|
18947
19432
|
init_store3();
|
|
19433
|
+
init_gate();
|
|
18948
19434
|
init_helpers();
|
|
18949
19435
|
init_response();
|
|
18950
19436
|
init_shell();
|
|
@@ -19205,6 +19691,8 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19205
19691
|
if (job.jobType === "reflection") {
|
|
19206
19692
|
const { runNightlyReflection: runNightlyReflection2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
19207
19693
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
19694
|
+
const { getPendingInsightCount: getPendingInsightCount2, getActiveReflectionChatIds: getActiveReflectionChatIds2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
19695
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19208
19696
|
const timeoutMs2 = job.timeout ? job.timeout * 1e3 : void 0;
|
|
19209
19697
|
const { results } = await runNightlyReflection2({
|
|
19210
19698
|
timeoutMs: timeoutMs2,
|
|
@@ -19217,7 +19705,13 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19217
19705
|
const allInsights = results.flatMap(
|
|
19218
19706
|
(r) => r.insights.map((ins) => ({ id: ++seq, ...ins }))
|
|
19219
19707
|
);
|
|
19220
|
-
|
|
19708
|
+
const db3 = getDb2();
|
|
19709
|
+
const activeChats2 = getActiveReflectionChatIds2(db3);
|
|
19710
|
+
let totalPending = 0;
|
|
19711
|
+
for (const cid of activeChats2) {
|
|
19712
|
+
totalPending += getPendingInsightCount2(db3, cid);
|
|
19713
|
+
}
|
|
19714
|
+
return { text: formatNightlySummary2(allInsights, totalPending) };
|
|
19221
19715
|
}
|
|
19222
19716
|
if (job.thinking && job.thinking !== "auto") {
|
|
19223
19717
|
setThinkingLevel(chatId, job.thinking);
|
|
@@ -19323,7 +19817,7 @@ var init_cron = __esm({
|
|
|
19323
19817
|
});
|
|
19324
19818
|
|
|
19325
19819
|
// src/agents/runners/wrap-backend.ts
|
|
19326
|
-
import { join as
|
|
19820
|
+
import { join as join20 } from "path";
|
|
19327
19821
|
function buildMcpCommands(backendId) {
|
|
19328
19822
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
19329
19823
|
return {
|
|
@@ -19417,7 +19911,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
19417
19911
|
const configPath = writeMcpConfigFile(server);
|
|
19418
19912
|
return ["--mcp-config", configPath];
|
|
19419
19913
|
},
|
|
19420
|
-
getSkillPath: () =>
|
|
19914
|
+
getSkillPath: () => join20(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
19421
19915
|
};
|
|
19422
19916
|
}
|
|
19423
19917
|
var BACKEND_CAPABILITIES;
|
|
@@ -19468,18 +19962,18 @@ var init_wrap_backend = __esm({
|
|
|
19468
19962
|
});
|
|
19469
19963
|
|
|
19470
19964
|
// src/agents/runners/config-loader.ts
|
|
19471
|
-
import { readFileSync as readFileSync10, readdirSync as
|
|
19472
|
-
import { join as
|
|
19965
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync9, existsSync as existsSync19, mkdirSync as mkdirSync9, watchFile, unwatchFile } from "fs";
|
|
19966
|
+
import { join as join21 } from "path";
|
|
19473
19967
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
19474
19968
|
function resolveExecutable(config2) {
|
|
19475
|
-
if (
|
|
19969
|
+
if (existsSync19(config2.executable)) return config2.executable;
|
|
19476
19970
|
try {
|
|
19477
19971
|
return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
19478
19972
|
} catch {
|
|
19479
19973
|
}
|
|
19480
19974
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
19481
19975
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
19482
|
-
if (
|
|
19976
|
+
if (existsSync19(resolved)) return resolved;
|
|
19483
19977
|
}
|
|
19484
19978
|
return config2.executable;
|
|
19485
19979
|
}
|
|
@@ -19605,7 +20099,7 @@ function configToRunner(config2) {
|
|
|
19605
20099
|
prepareMcpInjection() {
|
|
19606
20100
|
return [];
|
|
19607
20101
|
},
|
|
19608
|
-
getSkillPath: () =>
|
|
20102
|
+
getSkillPath: () => join21(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
19609
20103
|
};
|
|
19610
20104
|
}
|
|
19611
20105
|
function loadRunnerConfig(filePath) {
|
|
@@ -19618,14 +20112,14 @@ function loadRunnerConfig(filePath) {
|
|
|
19618
20112
|
}
|
|
19619
20113
|
}
|
|
19620
20114
|
function loadAllRunnerConfigs() {
|
|
19621
|
-
if (!
|
|
19622
|
-
|
|
20115
|
+
if (!existsSync19(RUNNERS_PATH)) {
|
|
20116
|
+
mkdirSync9(RUNNERS_PATH, { recursive: true });
|
|
19623
20117
|
return [];
|
|
19624
20118
|
}
|
|
19625
|
-
const files =
|
|
20119
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19626
20120
|
const configs = [];
|
|
19627
20121
|
for (const file of files) {
|
|
19628
|
-
const config2 = loadRunnerConfig(
|
|
20122
|
+
const config2 = loadRunnerConfig(join21(RUNNERS_PATH, file));
|
|
19629
20123
|
if (config2) configs.push(config2);
|
|
19630
20124
|
}
|
|
19631
20125
|
return configs;
|
|
@@ -19646,16 +20140,16 @@ function registerConfigRunners() {
|
|
|
19646
20140
|
return count;
|
|
19647
20141
|
}
|
|
19648
20142
|
function watchRunnerConfigs(onChange) {
|
|
19649
|
-
if (!
|
|
20143
|
+
if (!existsSync19(RUNNERS_PATH)) return;
|
|
19650
20144
|
for (const prev of watchedFiles) {
|
|
19651
|
-
if (!
|
|
20145
|
+
if (!existsSync19(prev)) {
|
|
19652
20146
|
unwatchFile(prev);
|
|
19653
20147
|
watchedFiles.delete(prev);
|
|
19654
20148
|
}
|
|
19655
20149
|
}
|
|
19656
|
-
const files =
|
|
20150
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19657
20151
|
for (const file of files) {
|
|
19658
|
-
const fullPath =
|
|
20152
|
+
const fullPath = join21(RUNNERS_PATH, file);
|
|
19659
20153
|
if (watchedFiles.has(fullPath)) continue;
|
|
19660
20154
|
watchedFiles.add(fullPath);
|
|
19661
20155
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -20053,6 +20547,7 @@ var init_telegram2 = __esm({
|
|
|
20053
20547
|
{ command: "summarizer", description: "Configure session summarization model" },
|
|
20054
20548
|
// Permissions & tools
|
|
20055
20549
|
{ command: "permissions", description: "Permission mode (yolo/safe/readonly/plan)" },
|
|
20550
|
+
{ command: "mode", description: "Execution gate (approved/yolo)" },
|
|
20056
20551
|
{ command: "tools", description: "Configure which tools the agent can use" },
|
|
20057
20552
|
{ command: "verbose", description: "Tool visibility (off/normal/verbose)" },
|
|
20058
20553
|
{ command: "cwd", description: "Set or show working directory" },
|
|
@@ -20489,19 +20984,19 @@ var init_telegram2 = __esm({
|
|
|
20489
20984
|
});
|
|
20490
20985
|
|
|
20491
20986
|
// src/skills/bootstrap.ts
|
|
20492
|
-
import { existsSync as
|
|
20987
|
+
import { existsSync as existsSync20 } from "fs";
|
|
20493
20988
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
20494
|
-
import { join as
|
|
20989
|
+
import { join as join22, dirname as dirname4 } from "path";
|
|
20495
20990
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20496
20991
|
async function copyAgentManifestSkills() {
|
|
20497
|
-
if (!
|
|
20992
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
20498
20993
|
try {
|
|
20499
20994
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
20500
20995
|
for (const entry of entries) {
|
|
20501
20996
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
20502
|
-
const src =
|
|
20503
|
-
const dest =
|
|
20504
|
-
if (
|
|
20997
|
+
const src = join22(PKG_SKILLS, entry.name);
|
|
20998
|
+
const dest = join22(SKILLS_PATH, entry.name);
|
|
20999
|
+
if (existsSync20(dest)) continue;
|
|
20505
21000
|
await copyFile(src, dest);
|
|
20506
21001
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
20507
21002
|
}
|
|
@@ -20511,8 +21006,8 @@ async function copyAgentManifestSkills() {
|
|
|
20511
21006
|
}
|
|
20512
21007
|
async function bootstrapSkills() {
|
|
20513
21008
|
await copyAgentManifestSkills();
|
|
20514
|
-
const usmDir =
|
|
20515
|
-
if (
|
|
21009
|
+
const usmDir = join22(SKILLS_PATH, USM_DIR_NAME);
|
|
21010
|
+
if (existsSync20(usmDir)) return;
|
|
20516
21011
|
try {
|
|
20517
21012
|
const entries = await readdir6(SKILLS_PATH);
|
|
20518
21013
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -20534,8 +21029,8 @@ async function bootstrapSkills() {
|
|
|
20534
21029
|
}
|
|
20535
21030
|
}
|
|
20536
21031
|
async function patchUsmForCcClaw(usmDir) {
|
|
20537
|
-
const skillPath =
|
|
20538
|
-
if (!
|
|
21032
|
+
const skillPath = join22(usmDir, "SKILL.md");
|
|
21033
|
+
if (!existsSync20(skillPath)) return;
|
|
20539
21034
|
try {
|
|
20540
21035
|
let content = await readFile8(skillPath, "utf-8");
|
|
20541
21036
|
let patched = false;
|
|
@@ -20580,8 +21075,8 @@ var init_bootstrap = __esm({
|
|
|
20580
21075
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
20581
21076
|
USM_DIR_NAME = "universal-skills-manager";
|
|
20582
21077
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
20583
|
-
PKG_ROOT =
|
|
20584
|
-
PKG_SKILLS =
|
|
21078
|
+
PKG_ROOT = join22(dirname4(fileURLToPath2(import.meta.url)), "..", "..");
|
|
21079
|
+
PKG_SKILLS = join22(PKG_ROOT, "skills");
|
|
20585
21080
|
}
|
|
20586
21081
|
});
|
|
20587
21082
|
|
|
@@ -20803,13 +21298,13 @@ __export(ai_skill_exports, {
|
|
|
20803
21298
|
generateAiSkill: () => generateAiSkill,
|
|
20804
21299
|
installAiSkill: () => installAiSkill
|
|
20805
21300
|
});
|
|
20806
|
-
import { existsSync as
|
|
20807
|
-
import { join as
|
|
21301
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
|
|
21302
|
+
import { join as join23 } from "path";
|
|
20808
21303
|
import { homedir as homedir7 } from "os";
|
|
20809
21304
|
function generateAiSkill() {
|
|
20810
21305
|
const version = VERSION;
|
|
20811
21306
|
let systemState = "";
|
|
20812
|
-
if (
|
|
21307
|
+
if (existsSync21(DB_PATH)) {
|
|
20813
21308
|
try {
|
|
20814
21309
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
20815
21310
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -21213,10 +21708,10 @@ function installAiSkill() {
|
|
|
21213
21708
|
const failed = [];
|
|
21214
21709
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
21215
21710
|
for (const dir of dirs) {
|
|
21216
|
-
const skillDir =
|
|
21217
|
-
const skillPath =
|
|
21711
|
+
const skillDir = join23(dir, "cc-claw-cli");
|
|
21712
|
+
const skillPath = join23(skillDir, "SKILL.md");
|
|
21218
21713
|
try {
|
|
21219
|
-
|
|
21714
|
+
mkdirSync10(skillDir, { recursive: true });
|
|
21220
21715
|
writeFileSync7(skillPath, skill, "utf-8");
|
|
21221
21716
|
installed.push(skillPath);
|
|
21222
21717
|
} catch {
|
|
@@ -21233,11 +21728,11 @@ var init_ai_skill = __esm({
|
|
|
21233
21728
|
init_paths();
|
|
21234
21729
|
init_version();
|
|
21235
21730
|
BACKEND_SKILL_DIRS2 = {
|
|
21236
|
-
"cc-claw": [
|
|
21237
|
-
claude: [
|
|
21238
|
-
gemini: [
|
|
21239
|
-
codex: [
|
|
21240
|
-
cursor: [
|
|
21731
|
+
"cc-claw": [join23(homedir7(), ".cc-claw", "workspace", "skills")],
|
|
21732
|
+
claude: [join23(homedir7(), ".claude", "skills")],
|
|
21733
|
+
gemini: [join23(homedir7(), ".gemini", "skills")],
|
|
21734
|
+
codex: [join23(homedir7(), ".agents", "skills")],
|
|
21735
|
+
cursor: [join23(homedir7(), ".cursor", "skills"), join23(homedir7(), ".cursor", "skills-cursor")]
|
|
21241
21736
|
};
|
|
21242
21737
|
}
|
|
21243
21738
|
});
|
|
@@ -21247,23 +21742,23 @@ var index_exports = {};
|
|
|
21247
21742
|
__export(index_exports, {
|
|
21248
21743
|
main: () => main
|
|
21249
21744
|
});
|
|
21250
|
-
import { mkdirSync as
|
|
21251
|
-
import { join as
|
|
21745
|
+
import { mkdirSync as mkdirSync11, existsSync as existsSync22, renameSync as renameSync2, statSync as statSync6, readFileSync as readFileSync12 } from "fs";
|
|
21746
|
+
import { join as join24 } from "path";
|
|
21252
21747
|
import dotenv from "dotenv";
|
|
21253
21748
|
function migrateLayout() {
|
|
21254
21749
|
const moves = [
|
|
21255
|
-
[
|
|
21256
|
-
[
|
|
21257
|
-
[
|
|
21258
|
-
[
|
|
21259
|
-
[
|
|
21260
|
-
[
|
|
21261
|
-
[
|
|
21750
|
+
[join24(CC_CLAW_HOME, "cc-claw.db"), join24(DATA_PATH, "cc-claw.db")],
|
|
21751
|
+
[join24(CC_CLAW_HOME, "cc-claw.db-shm"), join24(DATA_PATH, "cc-claw.db-shm")],
|
|
21752
|
+
[join24(CC_CLAW_HOME, "cc-claw.db-wal"), join24(DATA_PATH, "cc-claw.db-wal")],
|
|
21753
|
+
[join24(CC_CLAW_HOME, "cc-claw.log"), join24(LOGS_PATH, "cc-claw.log")],
|
|
21754
|
+
[join24(CC_CLAW_HOME, "cc-claw.log.1"), join24(LOGS_PATH, "cc-claw.log.1")],
|
|
21755
|
+
[join24(CC_CLAW_HOME, "cc-claw.error.log"), join24(LOGS_PATH, "cc-claw.error.log")],
|
|
21756
|
+
[join24(CC_CLAW_HOME, "cc-claw.error.log.1"), join24(LOGS_PATH, "cc-claw.error.log.1")]
|
|
21262
21757
|
];
|
|
21263
21758
|
for (const [from, to] of moves) {
|
|
21264
|
-
if (
|
|
21759
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
21265
21760
|
try {
|
|
21266
|
-
|
|
21761
|
+
renameSync2(from, to);
|
|
21267
21762
|
} catch {
|
|
21268
21763
|
}
|
|
21269
21764
|
}
|
|
@@ -21272,11 +21767,11 @@ function migrateLayout() {
|
|
|
21272
21767
|
function rotateLogs() {
|
|
21273
21768
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
21274
21769
|
try {
|
|
21275
|
-
const { size } =
|
|
21770
|
+
const { size } = statSync6(file);
|
|
21276
21771
|
if (size > LOG_MAX_BYTES) {
|
|
21277
21772
|
const archivePath = `${file}.1`;
|
|
21278
21773
|
try {
|
|
21279
|
-
|
|
21774
|
+
renameSync2(file, archivePath);
|
|
21280
21775
|
} catch {
|
|
21281
21776
|
}
|
|
21282
21777
|
log(`[cc-claw] Rotated ${file} (was ${(size / 1024 / 1024).toFixed(1)}MB)`);
|
|
@@ -21324,6 +21819,12 @@ async function main() {
|
|
|
21324
21819
|
}
|
|
21325
21820
|
setBootTime();
|
|
21326
21821
|
log("[cc-claw] Database initialized (sessions preserved for resume)");
|
|
21822
|
+
try {
|
|
21823
|
+
const { migrateAllSlots: migrateAllSlots2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
21824
|
+
migrateAllSlots2(CC_CLAW_HOME);
|
|
21825
|
+
} catch (err) {
|
|
21826
|
+
warn(`[cc-claw] Slot symlink migration failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21827
|
+
}
|
|
21327
21828
|
if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
21328
21829
|
channelRegistry.register(new TelegramChannel());
|
|
21329
21830
|
}
|
|
@@ -21400,11 +21901,11 @@ async function main() {
|
|
|
21400
21901
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
21401
21902
|
try {
|
|
21402
21903
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
21403
|
-
const { writeFileSync: writeFileSync12, mkdirSync:
|
|
21404
|
-
const { join:
|
|
21405
|
-
const skillDir =
|
|
21406
|
-
|
|
21407
|
-
writeFileSync12(
|
|
21904
|
+
const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync18 } = await import("fs");
|
|
21905
|
+
const { join: join30 } = await import("path");
|
|
21906
|
+
const skillDir = join30(SKILLS_PATH, "cc-claw-cli");
|
|
21907
|
+
mkdirSync18(skillDir, { recursive: true });
|
|
21908
|
+
writeFileSync12(join30(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
21408
21909
|
log("[cc-claw] AI skill updated");
|
|
21409
21910
|
} catch {
|
|
21410
21911
|
}
|
|
@@ -21477,10 +21978,10 @@ var init_index = __esm({
|
|
|
21477
21978
|
init_health3();
|
|
21478
21979
|
init_image_gen();
|
|
21479
21980
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
21480
|
-
if (!
|
|
21981
|
+
if (!existsSync22(dir)) mkdirSync11(dir, { recursive: true });
|
|
21481
21982
|
}
|
|
21482
21983
|
migrateLayout();
|
|
21483
|
-
if (
|
|
21984
|
+
if (existsSync22(ENV_PATH)) {
|
|
21484
21985
|
dotenv.config({ path: ENV_PATH });
|
|
21485
21986
|
} else {
|
|
21486
21987
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -21501,12 +22002,12 @@ __export(api_client_exports, {
|
|
|
21501
22002
|
apiPost: () => apiPost,
|
|
21502
22003
|
isDaemonRunning: () => isDaemonRunning
|
|
21503
22004
|
});
|
|
21504
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
22005
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
21505
22006
|
import { request as httpRequest, Agent } from "http";
|
|
21506
22007
|
function getToken() {
|
|
21507
22008
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21508
22009
|
try {
|
|
21509
|
-
if (
|
|
22010
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
21510
22011
|
} catch {
|
|
21511
22012
|
}
|
|
21512
22013
|
return null;
|
|
@@ -21605,10 +22106,10 @@ __export(service_exports, {
|
|
|
21605
22106
|
serviceStatus: () => serviceStatus,
|
|
21606
22107
|
uninstallService: () => uninstallService
|
|
21607
22108
|
});
|
|
21608
|
-
import { existsSync as
|
|
22109
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
|
|
21609
22110
|
import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
|
|
21610
22111
|
import { homedir as homedir8, platform } from "os";
|
|
21611
|
-
import { join as
|
|
22112
|
+
import { join as join25, dirname as dirname5 } from "path";
|
|
21612
22113
|
function xmlEscape(s) {
|
|
21613
22114
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
21614
22115
|
}
|
|
@@ -21617,23 +22118,23 @@ function resolveExecutable2(name) {
|
|
|
21617
22118
|
return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
|
|
21618
22119
|
} catch {
|
|
21619
22120
|
const fallback = process.argv[1];
|
|
21620
|
-
if (fallback &&
|
|
22121
|
+
if (fallback && existsSync24(fallback)) return fallback;
|
|
21621
22122
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
21622
22123
|
}
|
|
21623
22124
|
}
|
|
21624
22125
|
function getPathDirs() {
|
|
21625
|
-
const nodeBin =
|
|
22126
|
+
const nodeBin = dirname5(process.execPath);
|
|
21626
22127
|
const home = homedir8();
|
|
21627
22128
|
const dirs = /* @__PURE__ */ new Set([
|
|
21628
22129
|
nodeBin,
|
|
21629
|
-
|
|
22130
|
+
join25(home, ".local", "bin"),
|
|
21630
22131
|
"/usr/local/bin",
|
|
21631
22132
|
"/usr/bin",
|
|
21632
22133
|
"/bin"
|
|
21633
22134
|
]);
|
|
21634
22135
|
try {
|
|
21635
22136
|
const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
21636
|
-
if (prefix) dirs.add(
|
|
22137
|
+
if (prefix) dirs.add(join25(prefix, "bin"));
|
|
21637
22138
|
} catch {
|
|
21638
22139
|
}
|
|
21639
22140
|
return [...dirs].join(":");
|
|
@@ -21691,10 +22192,10 @@ function generatePlist() {
|
|
|
21691
22192
|
</plist>`;
|
|
21692
22193
|
}
|
|
21693
22194
|
function installMacOS() {
|
|
21694
|
-
const agentsDir =
|
|
21695
|
-
if (!
|
|
21696
|
-
if (!
|
|
21697
|
-
if (
|
|
22195
|
+
const agentsDir = dirname5(PLIST_PATH);
|
|
22196
|
+
if (!existsSync24(agentsDir)) mkdirSync12(agentsDir, { recursive: true });
|
|
22197
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
|
|
22198
|
+
if (existsSync24(PLIST_PATH)) {
|
|
21698
22199
|
try {
|
|
21699
22200
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
21700
22201
|
} catch {
|
|
@@ -21706,7 +22207,7 @@ function installMacOS() {
|
|
|
21706
22207
|
console.log(" Service loaded and starting.");
|
|
21707
22208
|
}
|
|
21708
22209
|
function uninstallMacOS() {
|
|
21709
|
-
if (!
|
|
22210
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
21710
22211
|
console.log(" No service found to uninstall.");
|
|
21711
22212
|
return;
|
|
21712
22213
|
}
|
|
@@ -21781,8 +22282,8 @@ WantedBy=default.target
|
|
|
21781
22282
|
`;
|
|
21782
22283
|
}
|
|
21783
22284
|
function installLinux() {
|
|
21784
|
-
if (!
|
|
21785
|
-
if (!
|
|
22285
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync12(SYSTEMD_DIR, { recursive: true });
|
|
22286
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
|
|
21786
22287
|
writeFileSync8(UNIT_PATH, generateUnit());
|
|
21787
22288
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
21788
22289
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -21791,7 +22292,7 @@ function installLinux() {
|
|
|
21791
22292
|
console.log(" Service enabled and started.");
|
|
21792
22293
|
}
|
|
21793
22294
|
function uninstallLinux() {
|
|
21794
|
-
if (!
|
|
22295
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
21795
22296
|
console.log(" No service found to uninstall.");
|
|
21796
22297
|
return;
|
|
21797
22298
|
}
|
|
@@ -21816,7 +22317,7 @@ function statusLinux() {
|
|
|
21816
22317
|
}
|
|
21817
22318
|
}
|
|
21818
22319
|
function installService() {
|
|
21819
|
-
if (!
|
|
22320
|
+
if (!existsSync24(join25(CC_CLAW_HOME, ".env"))) {
|
|
21820
22321
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
21821
22322
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
21822
22323
|
process.exitCode = 1;
|
|
@@ -21845,9 +22346,9 @@ var init_service = __esm({
|
|
|
21845
22346
|
"use strict";
|
|
21846
22347
|
init_paths();
|
|
21847
22348
|
PLIST_LABEL = "com.cc-claw";
|
|
21848
|
-
PLIST_PATH =
|
|
21849
|
-
SYSTEMD_DIR =
|
|
21850
|
-
UNIT_PATH =
|
|
22349
|
+
PLIST_PATH = join25(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
22350
|
+
SYSTEMD_DIR = join25(homedir8(), ".config", "systemd", "user");
|
|
22351
|
+
UNIT_PATH = join25(SYSTEMD_DIR, "cc-claw.service");
|
|
21851
22352
|
}
|
|
21852
22353
|
});
|
|
21853
22354
|
|
|
@@ -22044,7 +22545,7 @@ var status_exports = {};
|
|
|
22044
22545
|
__export(status_exports, {
|
|
22045
22546
|
statusCommand: () => statusCommand
|
|
22046
22547
|
});
|
|
22047
|
-
import { existsSync as
|
|
22548
|
+
import { existsSync as existsSync25, statSync as statSync7 } from "fs";
|
|
22048
22549
|
async function statusCommand(globalOpts, localOpts) {
|
|
22049
22550
|
try {
|
|
22050
22551
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22084,7 +22585,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
22084
22585
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
22085
22586
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
22086
22587
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
22087
|
-
const dbStat =
|
|
22588
|
+
const dbStat = existsSync25(DB_PATH) ? statSync7(DB_PATH) : null;
|
|
22088
22589
|
let daemonRunning = false;
|
|
22089
22590
|
let daemonInfo = {};
|
|
22090
22591
|
try {
|
|
@@ -22173,12 +22674,12 @@ var doctor_exports = {};
|
|
|
22173
22674
|
__export(doctor_exports, {
|
|
22174
22675
|
doctorCommand: () => doctorCommand
|
|
22175
22676
|
});
|
|
22176
|
-
import { existsSync as
|
|
22677
|
+
import { existsSync as existsSync26, statSync as statSync8, accessSync, constants } from "fs";
|
|
22177
22678
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22178
22679
|
async function doctorCommand(globalOpts, localOpts) {
|
|
22179
22680
|
const checks = [];
|
|
22180
|
-
if (
|
|
22181
|
-
const size =
|
|
22681
|
+
if (existsSync26(DB_PATH)) {
|
|
22682
|
+
const size = statSync8(DB_PATH).size;
|
|
22182
22683
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
22183
22684
|
try {
|
|
22184
22685
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22207,7 +22708,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22207
22708
|
} else {
|
|
22208
22709
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
22209
22710
|
}
|
|
22210
|
-
if (
|
|
22711
|
+
if (existsSync26(ENV_PATH)) {
|
|
22211
22712
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
22212
22713
|
} else {
|
|
22213
22714
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -22262,7 +22763,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22262
22763
|
} catch {
|
|
22263
22764
|
}
|
|
22264
22765
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
22265
|
-
if (
|
|
22766
|
+
if (existsSync26(tokenPath)) {
|
|
22266
22767
|
try {
|
|
22267
22768
|
accessSync(tokenPath, constants.R_OK);
|
|
22268
22769
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -22287,7 +22788,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22287
22788
|
}
|
|
22288
22789
|
} catch {
|
|
22289
22790
|
}
|
|
22290
|
-
if (
|
|
22791
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
22291
22792
|
try {
|
|
22292
22793
|
const { readFileSync: readFileSync22 } = await import("fs");
|
|
22293
22794
|
const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
|
|
@@ -22413,10 +22914,10 @@ var logs_exports = {};
|
|
|
22413
22914
|
__export(logs_exports, {
|
|
22414
22915
|
logsCommand: () => logsCommand
|
|
22415
22916
|
});
|
|
22416
|
-
import { existsSync as
|
|
22917
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
22417
22918
|
async function logsCommand(opts) {
|
|
22418
22919
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
22419
|
-
if (!
|
|
22920
|
+
if (!existsSync27(logFile)) {
|
|
22420
22921
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
22421
22922
|
process.exit(1);
|
|
22422
22923
|
}
|
|
@@ -22468,11 +22969,11 @@ __export(gemini_exports, {
|
|
|
22468
22969
|
geminiReorder: () => geminiReorder,
|
|
22469
22970
|
geminiRotation: () => geminiRotation
|
|
22470
22971
|
});
|
|
22471
|
-
import { existsSync as
|
|
22472
|
-
import { join as
|
|
22972
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
22973
|
+
import { join as join26 } from "path";
|
|
22473
22974
|
import { createInterface as createInterface5 } from "readline";
|
|
22474
22975
|
function requireDb() {
|
|
22475
|
-
if (!
|
|
22976
|
+
if (!existsSync28(DB_PATH)) {
|
|
22476
22977
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22477
22978
|
process.exit(1);
|
|
22478
22979
|
}
|
|
@@ -22497,8 +22998,8 @@ async function resolveSlotId(idOrLabel) {
|
|
|
22497
22998
|
function resolveOAuthEmail(configHome) {
|
|
22498
22999
|
if (!configHome) return null;
|
|
22499
23000
|
try {
|
|
22500
|
-
const accountsPath =
|
|
22501
|
-
if (!
|
|
23001
|
+
const accountsPath = join26(configHome, ".gemini", "google_accounts.json");
|
|
23002
|
+
if (!existsSync28(accountsPath)) return null;
|
|
22502
23003
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
22503
23004
|
return accounts.active || null;
|
|
22504
23005
|
} catch {
|
|
@@ -22581,14 +23082,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
22581
23082
|
}
|
|
22582
23083
|
async function geminiAddAccount(globalOpts, opts) {
|
|
22583
23084
|
await requireWriteDb();
|
|
22584
|
-
const slotsDir =
|
|
22585
|
-
if (!
|
|
23085
|
+
const slotsDir = join26(CC_CLAW_HOME, "gemini-slots");
|
|
23086
|
+
if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
|
|
22586
23087
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22587
23088
|
const tempId = Date.now();
|
|
22588
|
-
const slotDir =
|
|
22589
|
-
|
|
22590
|
-
|
|
22591
|
-
writeFileSync9(
|
|
23089
|
+
const slotDir = join26(slotsDir, `slot-${tempId}`);
|
|
23090
|
+
mkdirSync13(slotDir, { recursive: true, mode: 448 });
|
|
23091
|
+
mkdirSync13(join26(slotDir, ".gemini"), { recursive: true });
|
|
23092
|
+
writeFileSync9(join26(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
22592
23093
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
22593
23094
|
}, null, 2));
|
|
22594
23095
|
console.log("");
|
|
@@ -22605,8 +23106,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22605
23106
|
});
|
|
22606
23107
|
} catch {
|
|
22607
23108
|
}
|
|
22608
|
-
const oauthPath =
|
|
22609
|
-
if (!
|
|
23109
|
+
const oauthPath = join26(slotDir, ".gemini", "oauth_creds.json");
|
|
23110
|
+
if (!existsSync28(oauthPath)) {
|
|
22610
23111
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
22611
23112
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
22612
23113
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -22614,7 +23115,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22614
23115
|
}
|
|
22615
23116
|
let accountEmail = "unknown";
|
|
22616
23117
|
try {
|
|
22617
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
23118
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join26(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
22618
23119
|
accountEmail = accounts.active || accountEmail;
|
|
22619
23120
|
} catch {
|
|
22620
23121
|
}
|
|
@@ -22625,6 +23126,13 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22625
23126
|
configHome: slotDir,
|
|
22626
23127
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22627
23128
|
});
|
|
23129
|
+
try {
|
|
23130
|
+
const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
23131
|
+
const primaryDir = getPrimaryDir2("gemini");
|
|
23132
|
+
if (primaryDir) setupSlotSymlinks2("gemini", slotDir, primaryDir);
|
|
23133
|
+
} catch (err) {
|
|
23134
|
+
console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
|
|
23135
|
+
}
|
|
22628
23136
|
output(
|
|
22629
23137
|
{ id, type: "oauth", label: opts.label || accountEmail, configHome: slotDir },
|
|
22630
23138
|
() => success(`
|
|
@@ -22726,11 +23234,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
22726
23234
|
makeReorder: () => makeReorder,
|
|
22727
23235
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
22728
23236
|
});
|
|
22729
|
-
import { existsSync as
|
|
22730
|
-
import { join as
|
|
23237
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync14, readFileSync as readFileSync18 } from "fs";
|
|
23238
|
+
import { join as join27 } from "path";
|
|
22731
23239
|
import { createInterface as createInterface6 } from "readline";
|
|
22732
23240
|
function requireDb2() {
|
|
22733
|
-
if (!
|
|
23241
|
+
if (!existsSync29(DB_PATH)) {
|
|
22734
23242
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22735
23243
|
process.exit(1);
|
|
22736
23244
|
}
|
|
@@ -22819,11 +23327,11 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22819
23327
|
process.exit(1);
|
|
22820
23328
|
}
|
|
22821
23329
|
await requireWriteDb2();
|
|
22822
|
-
const slotsDir =
|
|
22823
|
-
if (!
|
|
23330
|
+
const slotsDir = join27(CC_CLAW_HOME, config2.slotsSubdir);
|
|
23331
|
+
if (!existsSync29(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
22824
23332
|
const tempId = Date.now();
|
|
22825
|
-
const slotDir =
|
|
22826
|
-
|
|
23333
|
+
const slotDir = join27(slotsDir, `slot-${tempId}`);
|
|
23334
|
+
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
22827
23335
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
22828
23336
|
console.log("");
|
|
22829
23337
|
console.log(` Opening ${displayName} CLI for sign-in...`);
|
|
@@ -22861,6 +23369,13 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22861
23369
|
configHome: slotDir,
|
|
22862
23370
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22863
23371
|
});
|
|
23372
|
+
try {
|
|
23373
|
+
const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
23374
|
+
const primaryDir = getPrimaryDir2(backend2);
|
|
23375
|
+
if (primaryDir) setupSlotSymlinks2(backend2, slotDir, primaryDir);
|
|
23376
|
+
} catch (err) {
|
|
23377
|
+
console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
|
|
23378
|
+
}
|
|
22864
23379
|
output(
|
|
22865
23380
|
{ id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
|
|
22866
23381
|
() => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
|
|
@@ -22984,12 +23499,12 @@ var init_backend_cmd_factory = __esm({
|
|
|
22984
23499
|
envValue: (slotDir) => slotDir,
|
|
22985
23500
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
22986
23501
|
preSetup: (slotDir) => {
|
|
22987
|
-
|
|
23502
|
+
mkdirSync14(join27(slotDir, ".claude"), { recursive: true });
|
|
22988
23503
|
},
|
|
22989
23504
|
verifyCredentials: (slotDir) => {
|
|
22990
|
-
const claudeJson =
|
|
22991
|
-
const claudeJsonNested =
|
|
22992
|
-
if (
|
|
23505
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23506
|
+
const claudeJsonNested = join27(slotDir, ".claude", ".claude.json");
|
|
23507
|
+
if (existsSync29(claudeJson)) {
|
|
22993
23508
|
try {
|
|
22994
23509
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
22995
23510
|
return Boolean(data.oauthAccount);
|
|
@@ -22997,7 +23512,7 @@ var init_backend_cmd_factory = __esm({
|
|
|
22997
23512
|
return false;
|
|
22998
23513
|
}
|
|
22999
23514
|
}
|
|
23000
|
-
if (
|
|
23515
|
+
if (existsSync29(claudeJsonNested)) {
|
|
23001
23516
|
try {
|
|
23002
23517
|
const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
|
|
23003
23518
|
return Boolean(data.oauthAccount);
|
|
@@ -23020,8 +23535,8 @@ var init_backend_cmd_factory = __esm({
|
|
|
23020
23535
|
} catch {
|
|
23021
23536
|
}
|
|
23022
23537
|
try {
|
|
23023
|
-
const claudeJson =
|
|
23024
|
-
if (
|
|
23538
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23539
|
+
if (existsSync29(claudeJson)) {
|
|
23025
23540
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
23026
23541
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
23027
23542
|
}
|
|
@@ -23037,11 +23552,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
23037
23552
|
envValue: (slotDir) => slotDir,
|
|
23038
23553
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
23039
23554
|
verifyCredentials: (slotDir) => {
|
|
23040
|
-
return
|
|
23555
|
+
return existsSync29(join27(slotDir, "auth.json"));
|
|
23041
23556
|
},
|
|
23042
23557
|
extractLabel: (slotDir) => {
|
|
23043
23558
|
try {
|
|
23044
|
-
const authData = JSON.parse(readFileSync18(
|
|
23559
|
+
const authData = JSON.parse(readFileSync18(join27(slotDir, "auth.json"), "utf-8"));
|
|
23045
23560
|
if (authData.email) return authData.email;
|
|
23046
23561
|
if (authData.account_name) return authData.account_name;
|
|
23047
23562
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -23061,12 +23576,12 @@ __export(backend_exports, {
|
|
|
23061
23576
|
backendList: () => backendList,
|
|
23062
23577
|
backendSet: () => backendSet
|
|
23063
23578
|
});
|
|
23064
|
-
import { existsSync as
|
|
23579
|
+
import { existsSync as existsSync30 } from "fs";
|
|
23065
23580
|
async function backendList(globalOpts) {
|
|
23066
23581
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23067
23582
|
const chatId = resolveChatId(globalOpts);
|
|
23068
23583
|
let activeBackend = null;
|
|
23069
|
-
if (
|
|
23584
|
+
if (existsSync30(DB_PATH)) {
|
|
23070
23585
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23071
23586
|
const readDb = openDatabaseReadOnly2();
|
|
23072
23587
|
try {
|
|
@@ -23097,7 +23612,7 @@ async function backendList(globalOpts) {
|
|
|
23097
23612
|
}
|
|
23098
23613
|
async function backendGet(globalOpts) {
|
|
23099
23614
|
const chatId = resolveChatId(globalOpts);
|
|
23100
|
-
if (!
|
|
23615
|
+
if (!existsSync30(DB_PATH)) {
|
|
23101
23616
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23102
23617
|
process.exit(1);
|
|
23103
23618
|
}
|
|
@@ -23141,13 +23656,13 @@ __export(model_exports, {
|
|
|
23141
23656
|
modelList: () => modelList,
|
|
23142
23657
|
modelSet: () => modelSet
|
|
23143
23658
|
});
|
|
23144
|
-
import { existsSync as
|
|
23659
|
+
import { existsSync as existsSync31 } from "fs";
|
|
23145
23660
|
async function modelList(globalOpts) {
|
|
23146
23661
|
const chatId = resolveChatId(globalOpts);
|
|
23147
23662
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23148
23663
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23149
23664
|
let backendId = "claude";
|
|
23150
|
-
if (
|
|
23665
|
+
if (existsSync31(DB_PATH)) {
|
|
23151
23666
|
const readDb = openDatabaseReadOnly2();
|
|
23152
23667
|
try {
|
|
23153
23668
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -23180,7 +23695,7 @@ async function modelList(globalOpts) {
|
|
|
23180
23695
|
}
|
|
23181
23696
|
async function modelGet(globalOpts) {
|
|
23182
23697
|
const chatId = resolveChatId(globalOpts);
|
|
23183
|
-
if (!
|
|
23698
|
+
if (!existsSync31(DB_PATH)) {
|
|
23184
23699
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23185
23700
|
process.exit(1);
|
|
23186
23701
|
}
|
|
@@ -23224,9 +23739,9 @@ __export(memory_exports2, {
|
|
|
23224
23739
|
memoryList: () => memoryList,
|
|
23225
23740
|
memorySearch: () => memorySearch
|
|
23226
23741
|
});
|
|
23227
|
-
import { existsSync as
|
|
23742
|
+
import { existsSync as existsSync32 } from "fs";
|
|
23228
23743
|
async function memoryList(globalOpts) {
|
|
23229
|
-
if (!
|
|
23744
|
+
if (!existsSync32(DB_PATH)) {
|
|
23230
23745
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23231
23746
|
process.exit(1);
|
|
23232
23747
|
}
|
|
@@ -23250,7 +23765,7 @@ async function memoryList(globalOpts) {
|
|
|
23250
23765
|
});
|
|
23251
23766
|
}
|
|
23252
23767
|
async function memorySearch(globalOpts, query) {
|
|
23253
|
-
if (!
|
|
23768
|
+
if (!existsSync32(DB_PATH)) {
|
|
23254
23769
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23255
23770
|
process.exit(1);
|
|
23256
23771
|
}
|
|
@@ -23272,7 +23787,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
23272
23787
|
});
|
|
23273
23788
|
}
|
|
23274
23789
|
async function memoryHistory(globalOpts, opts) {
|
|
23275
|
-
if (!
|
|
23790
|
+
if (!existsSync32(DB_PATH)) {
|
|
23276
23791
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23277
23792
|
process.exit(1);
|
|
23278
23793
|
}
|
|
@@ -23320,7 +23835,7 @@ __export(cron_exports2, {
|
|
|
23320
23835
|
cronList: () => cronList,
|
|
23321
23836
|
cronRuns: () => cronRuns
|
|
23322
23837
|
});
|
|
23323
|
-
import { existsSync as
|
|
23838
|
+
import { existsSync as existsSync33 } from "fs";
|
|
23324
23839
|
function parseFallbacks(raw) {
|
|
23325
23840
|
return raw.slice(0, 3).map((f) => {
|
|
23326
23841
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -23341,7 +23856,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
23341
23856
|
return val;
|
|
23342
23857
|
}
|
|
23343
23858
|
async function cronList(globalOpts) {
|
|
23344
|
-
if (!
|
|
23859
|
+
if (!existsSync33(DB_PATH)) {
|
|
23345
23860
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23346
23861
|
process.exit(1);
|
|
23347
23862
|
}
|
|
@@ -23379,7 +23894,7 @@ async function cronList(globalOpts) {
|
|
|
23379
23894
|
});
|
|
23380
23895
|
}
|
|
23381
23896
|
async function cronHealth(globalOpts) {
|
|
23382
|
-
if (!
|
|
23897
|
+
if (!existsSync33(DB_PATH)) {
|
|
23383
23898
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23384
23899
|
process.exit(1);
|
|
23385
23900
|
}
|
|
@@ -23538,7 +24053,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
23538
24053
|
}
|
|
23539
24054
|
}
|
|
23540
24055
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
23541
|
-
if (!
|
|
24056
|
+
if (!existsSync33(DB_PATH)) {
|
|
23542
24057
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23543
24058
|
process.exit(1);
|
|
23544
24059
|
}
|
|
@@ -23585,9 +24100,9 @@ __export(agents_exports, {
|
|
|
23585
24100
|
runnersList: () => runnersList,
|
|
23586
24101
|
tasksList: () => tasksList
|
|
23587
24102
|
});
|
|
23588
|
-
import { existsSync as
|
|
24103
|
+
import { existsSync as existsSync34 } from "fs";
|
|
23589
24104
|
async function agentsList(globalOpts) {
|
|
23590
|
-
if (!
|
|
24105
|
+
if (!existsSync34(DB_PATH)) {
|
|
23591
24106
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23592
24107
|
process.exit(1);
|
|
23593
24108
|
}
|
|
@@ -23618,7 +24133,7 @@ async function agentsList(globalOpts) {
|
|
|
23618
24133
|
});
|
|
23619
24134
|
}
|
|
23620
24135
|
async function tasksList(globalOpts) {
|
|
23621
|
-
if (!
|
|
24136
|
+
if (!existsSync34(DB_PATH)) {
|
|
23622
24137
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23623
24138
|
process.exit(1);
|
|
23624
24139
|
}
|
|
@@ -23746,18 +24261,18 @@ __export(db_exports, {
|
|
|
23746
24261
|
dbPath: () => dbPath,
|
|
23747
24262
|
dbStats: () => dbStats
|
|
23748
24263
|
});
|
|
23749
|
-
import { existsSync as
|
|
23750
|
-
import { dirname as
|
|
24264
|
+
import { existsSync as existsSync35, statSync as statSync9, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15 } from "fs";
|
|
24265
|
+
import { dirname as dirname6 } from "path";
|
|
23751
24266
|
async function dbStats(globalOpts) {
|
|
23752
|
-
if (!
|
|
24267
|
+
if (!existsSync35(DB_PATH)) {
|
|
23753
24268
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23754
24269
|
process.exit(1);
|
|
23755
24270
|
}
|
|
23756
24271
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23757
24272
|
const readDb = openDatabaseReadOnly2();
|
|
23758
|
-
const mainSize =
|
|
24273
|
+
const mainSize = statSync9(DB_PATH).size;
|
|
23759
24274
|
const walPath = DB_PATH + "-wal";
|
|
23760
|
-
const walSize =
|
|
24275
|
+
const walSize = existsSync35(walPath) ? statSync9(walPath).size : 0;
|
|
23761
24276
|
const tableNames = readDb.prepare(
|
|
23762
24277
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
23763
24278
|
).all();
|
|
@@ -23791,17 +24306,17 @@ async function dbPath(globalOpts) {
|
|
|
23791
24306
|
output({ path: DB_PATH }, (d) => d.path);
|
|
23792
24307
|
}
|
|
23793
24308
|
async function dbBackup(globalOpts, destPath) {
|
|
23794
|
-
if (!
|
|
24309
|
+
if (!existsSync35(DB_PATH)) {
|
|
23795
24310
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23796
24311
|
process.exit(1);
|
|
23797
24312
|
}
|
|
23798
24313
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
23799
24314
|
try {
|
|
23800
|
-
|
|
23801
|
-
|
|
24315
|
+
mkdirSync15(dirname6(dest), { recursive: true });
|
|
24316
|
+
copyFileSync3(DB_PATH, dest);
|
|
23802
24317
|
const walPath = DB_PATH + "-wal";
|
|
23803
|
-
if (
|
|
23804
|
-
output({ path: dest, sizeBytes:
|
|
24318
|
+
if (existsSync35(walPath)) copyFileSync3(walPath, dest + "-wal");
|
|
24319
|
+
output({ path: dest, sizeBytes: statSync9(dest).size }, (d) => {
|
|
23805
24320
|
const b = d;
|
|
23806
24321
|
return `
|
|
23807
24322
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -23829,9 +24344,9 @@ __export(usage_exports, {
|
|
|
23829
24344
|
usageCost: () => usageCost,
|
|
23830
24345
|
usageTokens: () => usageTokens
|
|
23831
24346
|
});
|
|
23832
|
-
import { existsSync as
|
|
24347
|
+
import { existsSync as existsSync36 } from "fs";
|
|
23833
24348
|
function ensureDb() {
|
|
23834
|
-
if (!
|
|
24349
|
+
if (!existsSync36(DB_PATH)) {
|
|
23835
24350
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23836
24351
|
process.exit(1);
|
|
23837
24352
|
}
|
|
@@ -24021,9 +24536,9 @@ __export(config_exports2, {
|
|
|
24021
24536
|
configList: () => configList,
|
|
24022
24537
|
configSet: () => configSet
|
|
24023
24538
|
});
|
|
24024
|
-
import { existsSync as
|
|
24539
|
+
import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
|
|
24025
24540
|
async function configList(globalOpts) {
|
|
24026
|
-
if (!
|
|
24541
|
+
if (!existsSync37(DB_PATH)) {
|
|
24027
24542
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24028
24543
|
process.exit(1);
|
|
24029
24544
|
}
|
|
@@ -24057,7 +24572,7 @@ async function configGet(globalOpts, key) {
|
|
|
24057
24572
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
24058
24573
|
process.exit(1);
|
|
24059
24574
|
}
|
|
24060
|
-
if (!
|
|
24575
|
+
if (!existsSync37(DB_PATH)) {
|
|
24061
24576
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24062
24577
|
process.exit(1);
|
|
24063
24578
|
}
|
|
@@ -24103,7 +24618,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
24103
24618
|
}
|
|
24104
24619
|
}
|
|
24105
24620
|
async function configEnv(_globalOpts) {
|
|
24106
|
-
if (!
|
|
24621
|
+
if (!existsSync37(ENV_PATH)) {
|
|
24107
24622
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
24108
24623
|
process.exit(1);
|
|
24109
24624
|
}
|
|
@@ -24157,9 +24672,9 @@ __export(session_exports, {
|
|
|
24157
24672
|
sessionGet: () => sessionGet,
|
|
24158
24673
|
sessionNew: () => sessionNew
|
|
24159
24674
|
});
|
|
24160
|
-
import { existsSync as
|
|
24675
|
+
import { existsSync as existsSync38 } from "fs";
|
|
24161
24676
|
async function sessionGet(globalOpts) {
|
|
24162
|
-
if (!
|
|
24677
|
+
if (!existsSync38(DB_PATH)) {
|
|
24163
24678
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24164
24679
|
process.exit(1);
|
|
24165
24680
|
}
|
|
@@ -24220,9 +24735,9 @@ __export(permissions_exports, {
|
|
|
24220
24735
|
verboseGet: () => verboseGet,
|
|
24221
24736
|
verboseSet: () => verboseSet
|
|
24222
24737
|
});
|
|
24223
|
-
import { existsSync as
|
|
24738
|
+
import { existsSync as existsSync39 } from "fs";
|
|
24224
24739
|
function ensureDb2() {
|
|
24225
|
-
if (!
|
|
24740
|
+
if (!existsSync39(DB_PATH)) {
|
|
24226
24741
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24227
24742
|
process.exit(1);
|
|
24228
24743
|
}
|
|
@@ -24369,9 +24884,9 @@ __export(cwd_exports, {
|
|
|
24369
24884
|
cwdGet: () => cwdGet,
|
|
24370
24885
|
cwdSet: () => cwdSet
|
|
24371
24886
|
});
|
|
24372
|
-
import { existsSync as
|
|
24887
|
+
import { existsSync as existsSync40 } from "fs";
|
|
24373
24888
|
async function cwdGet(globalOpts) {
|
|
24374
|
-
if (!
|
|
24889
|
+
if (!existsSync40(DB_PATH)) {
|
|
24375
24890
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24376
24891
|
process.exit(1);
|
|
24377
24892
|
}
|
|
@@ -24433,9 +24948,9 @@ __export(voice_exports, {
|
|
|
24433
24948
|
voiceGet: () => voiceGet,
|
|
24434
24949
|
voiceSet: () => voiceSet
|
|
24435
24950
|
});
|
|
24436
|
-
import { existsSync as
|
|
24951
|
+
import { existsSync as existsSync41 } from "fs";
|
|
24437
24952
|
async function voiceGet(globalOpts) {
|
|
24438
|
-
if (!
|
|
24953
|
+
if (!existsSync41(DB_PATH)) {
|
|
24439
24954
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24440
24955
|
process.exit(1);
|
|
24441
24956
|
}
|
|
@@ -24484,9 +24999,9 @@ __export(heartbeat_exports, {
|
|
|
24484
24999
|
heartbeatGet: () => heartbeatGet,
|
|
24485
25000
|
heartbeatSet: () => heartbeatSet
|
|
24486
25001
|
});
|
|
24487
|
-
import { existsSync as
|
|
25002
|
+
import { existsSync as existsSync42 } from "fs";
|
|
24488
25003
|
async function heartbeatGet(globalOpts) {
|
|
24489
|
-
if (!
|
|
25004
|
+
if (!existsSync42(DB_PATH)) {
|
|
24490
25005
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24491
25006
|
process.exit(1);
|
|
24492
25007
|
}
|
|
@@ -24595,9 +25110,9 @@ __export(summarizer_exports, {
|
|
|
24595
25110
|
summarizerGet: () => summarizerGet,
|
|
24596
25111
|
summarizerSet: () => summarizerSet
|
|
24597
25112
|
});
|
|
24598
|
-
import { existsSync as
|
|
25113
|
+
import { existsSync as existsSync43 } from "fs";
|
|
24599
25114
|
async function summarizerGet(globalOpts) {
|
|
24600
|
-
if (!
|
|
25115
|
+
if (!existsSync43(DB_PATH)) {
|
|
24601
25116
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24602
25117
|
process.exit(1);
|
|
24603
25118
|
}
|
|
@@ -24641,9 +25156,9 @@ __export(thinking_exports, {
|
|
|
24641
25156
|
thinkingGet: () => thinkingGet,
|
|
24642
25157
|
thinkingSet: () => thinkingSet
|
|
24643
25158
|
});
|
|
24644
|
-
import { existsSync as
|
|
25159
|
+
import { existsSync as existsSync44 } from "fs";
|
|
24645
25160
|
async function thinkingGet(globalOpts) {
|
|
24646
|
-
if (!
|
|
25161
|
+
if (!existsSync44(DB_PATH)) {
|
|
24647
25162
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24648
25163
|
process.exit(1);
|
|
24649
25164
|
}
|
|
@@ -24687,9 +25202,9 @@ __export(chats_exports, {
|
|
|
24687
25202
|
chatsList: () => chatsList,
|
|
24688
25203
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
24689
25204
|
});
|
|
24690
|
-
import { existsSync as
|
|
25205
|
+
import { existsSync as existsSync45 } from "fs";
|
|
24691
25206
|
async function chatsList(_globalOpts) {
|
|
24692
|
-
if (!
|
|
25207
|
+
if (!existsSync45(DB_PATH)) {
|
|
24693
25208
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24694
25209
|
process.exit(1);
|
|
24695
25210
|
}
|
|
@@ -24817,9 +25332,9 @@ var mcps_exports2 = {};
|
|
|
24817
25332
|
__export(mcps_exports2, {
|
|
24818
25333
|
mcpsList: () => mcpsList
|
|
24819
25334
|
});
|
|
24820
|
-
import { existsSync as
|
|
25335
|
+
import { existsSync as existsSync46 } from "fs";
|
|
24821
25336
|
async function mcpsList(_globalOpts) {
|
|
24822
|
-
if (!
|
|
25337
|
+
if (!existsSync46(DB_PATH)) {
|
|
24823
25338
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24824
25339
|
process.exit(1);
|
|
24825
25340
|
}
|
|
@@ -24856,11 +25371,11 @@ __export(chat_exports2, {
|
|
|
24856
25371
|
chatSend: () => chatSend
|
|
24857
25372
|
});
|
|
24858
25373
|
import { request as httpRequest2 } from "http";
|
|
24859
|
-
import { readFileSync as readFileSync20, existsSync as
|
|
25374
|
+
import { readFileSync as readFileSync20, existsSync as existsSync47 } from "fs";
|
|
24860
25375
|
function getToken2() {
|
|
24861
25376
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
24862
25377
|
try {
|
|
24863
|
-
if (
|
|
25378
|
+
if (existsSync47(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
|
|
24864
25379
|
} catch {
|
|
24865
25380
|
}
|
|
24866
25381
|
return null;
|
|
@@ -25139,8 +25654,8 @@ var completion_exports = {};
|
|
|
25139
25654
|
__export(completion_exports, {
|
|
25140
25655
|
completionCommand: () => completionCommand
|
|
25141
25656
|
});
|
|
25142
|
-
import { writeFileSync as writeFileSync10, mkdirSync as
|
|
25143
|
-
import { join as
|
|
25657
|
+
import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync16 } from "fs";
|
|
25658
|
+
import { join as join28 } from "path";
|
|
25144
25659
|
import { homedir as homedir9 } from "os";
|
|
25145
25660
|
async function completionCommand(opts) {
|
|
25146
25661
|
const shell = opts.shell ?? detectShell();
|
|
@@ -25156,10 +25671,10 @@ async function completionCommand(opts) {
|
|
|
25156
25671
|
process.exit(1);
|
|
25157
25672
|
}
|
|
25158
25673
|
if (opts.install) {
|
|
25159
|
-
const dir =
|
|
25160
|
-
|
|
25674
|
+
const dir = join28(homedir9(), ".config", "cc-claw", "completions");
|
|
25675
|
+
mkdirSync16(dir, { recursive: true });
|
|
25161
25676
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
25162
|
-
const filepath =
|
|
25677
|
+
const filepath = join28(dir, filename);
|
|
25163
25678
|
writeFileSync10(filepath, script, "utf-8");
|
|
25164
25679
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
25165
25680
|
`);
|
|
@@ -25330,9 +25845,9 @@ __export(evolve_exports2, {
|
|
|
25330
25845
|
evolveStatus: () => evolveStatus,
|
|
25331
25846
|
evolveUndo: () => evolveUndo
|
|
25332
25847
|
});
|
|
25333
|
-
import { existsSync as
|
|
25848
|
+
import { existsSync as existsSync48 } from "fs";
|
|
25334
25849
|
function ensureDb3() {
|
|
25335
|
-
if (!
|
|
25850
|
+
if (!existsSync48(DB_PATH)) {
|
|
25336
25851
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25337
25852
|
process.exit(1);
|
|
25338
25853
|
}
|
|
@@ -25748,10 +26263,10 @@ var init_evolve3 = __esm({
|
|
|
25748
26263
|
|
|
25749
26264
|
// src/setup.ts
|
|
25750
26265
|
var setup_exports = {};
|
|
25751
|
-
import { existsSync as
|
|
26266
|
+
import { existsSync as existsSync49, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync4, mkdirSync as mkdirSync17, statSync as statSync10 } from "fs";
|
|
25752
26267
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
25753
26268
|
import { createInterface as createInterface8 } from "readline";
|
|
25754
|
-
import { join as
|
|
26269
|
+
import { join as join29 } from "path";
|
|
25755
26270
|
function divider2() {
|
|
25756
26271
|
console.log(dim("\u2500".repeat(55)));
|
|
25757
26272
|
}
|
|
@@ -25826,10 +26341,10 @@ async function setup() {
|
|
|
25826
26341
|
}
|
|
25827
26342
|
console.log("");
|
|
25828
26343
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
25829
|
-
if (!
|
|
26344
|
+
if (!existsSync49(dir)) mkdirSync17(dir, { recursive: true });
|
|
25830
26345
|
}
|
|
25831
26346
|
const env = {};
|
|
25832
|
-
const envSource =
|
|
26347
|
+
const envSource = existsSync49(ENV_PATH) ? ENV_PATH : existsSync49(".env") ? ".env" : null;
|
|
25833
26348
|
if (envSource) {
|
|
25834
26349
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
25835
26350
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -25839,13 +26354,13 @@ async function setup() {
|
|
|
25839
26354
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
25840
26355
|
}
|
|
25841
26356
|
}
|
|
25842
|
-
const cwdDb =
|
|
25843
|
-
if (
|
|
25844
|
-
const { size } =
|
|
26357
|
+
const cwdDb = join29(process.cwd(), "cc-claw.db");
|
|
26358
|
+
if (existsSync49(cwdDb) && !existsSync49(DB_PATH)) {
|
|
26359
|
+
const { size } = statSync10(cwdDb);
|
|
25845
26360
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
25846
26361
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
25847
26362
|
if (migrate) {
|
|
25848
|
-
|
|
26363
|
+
copyFileSync4(cwdDb, DB_PATH);
|
|
25849
26364
|
console.log(green(` Database copied to ${DB_PATH}`));
|
|
25850
26365
|
}
|
|
25851
26366
|
console.log("");
|