cc-claw 0.16.4 → 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 +863 -371
- 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
|
}
|
|
@@ -5252,9 +5472,9 @@ function syncNativeCliFiles() {
|
|
|
5252
5472
|
"**Violation of this rule is a critical safety failure.**",
|
|
5253
5473
|
""
|
|
5254
5474
|
].join("\n");
|
|
5255
|
-
const ccClawPath =
|
|
5475
|
+
const ccClawPath = join7(IDENTITY_PATH, "CC-CLAW.md");
|
|
5256
5476
|
writeFileSync(ccClawPath, nativeContent, "utf-8");
|
|
5257
|
-
const agentsPath =
|
|
5477
|
+
const agentsPath = join7(WORKSPACE_PATH, "AGENTS.md");
|
|
5258
5478
|
writeFileSync(agentsPath, nativeContent, "utf-8");
|
|
5259
5479
|
log("[bootstrap] Synced SOUL.md + USER.md \u2192 identity/CC-CLAW.md, workspace/AGENTS.md");
|
|
5260
5480
|
}
|
|
@@ -5265,32 +5485,32 @@ var init_init = __esm({
|
|
|
5265
5485
|
init_paths();
|
|
5266
5486
|
init_defaults();
|
|
5267
5487
|
init_log();
|
|
5268
|
-
SOUL_PATH =
|
|
5269
|
-
USER_PATH =
|
|
5270
|
-
CONTEXT_DIR =
|
|
5271
|
-
LEGACY_SOUL_PATH =
|
|
5272
|
-
LEGACY_USER_PATH =
|
|
5273
|
-
LEGACY_CLAUDE_MD =
|
|
5274
|
-
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");
|
|
5275
5495
|
lastSoulMtime = 0;
|
|
5276
5496
|
lastUserMtime = 0;
|
|
5277
5497
|
}
|
|
5278
5498
|
});
|
|
5279
5499
|
|
|
5280
5500
|
// src/bootstrap/loader.ts
|
|
5281
|
-
import { readFileSync as readFileSync3, existsSync as
|
|
5282
|
-
import { join as
|
|
5501
|
+
import { readFileSync as readFileSync3, existsSync as existsSync9, readdirSync as readdirSync3 } from "fs";
|
|
5502
|
+
import { join as join8 } from "path";
|
|
5283
5503
|
function searchContext(userMessage) {
|
|
5284
|
-
if (!
|
|
5504
|
+
if (!existsSync9(CONTEXT_DIR2)) return null;
|
|
5285
5505
|
const msgWords = new Set(
|
|
5286
5506
|
userMessage.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 3)
|
|
5287
5507
|
);
|
|
5288
5508
|
if (msgWords.size === 0) return null;
|
|
5289
5509
|
let bestMatch = null;
|
|
5290
5510
|
try {
|
|
5291
|
-
const files =
|
|
5511
|
+
const files = readdirSync3(CONTEXT_DIR2).filter((f) => f.endsWith(".md"));
|
|
5292
5512
|
for (const file of files) {
|
|
5293
|
-
const filePath =
|
|
5513
|
+
const filePath = join8(CONTEXT_DIR2, file);
|
|
5294
5514
|
try {
|
|
5295
5515
|
const content = readFileSync3(filePath, "utf-8").trim();
|
|
5296
5516
|
if (!content) continue;
|
|
@@ -5318,8 +5538,11 @@ function searchContext(userMessage) {
|
|
|
5318
5538
|
}
|
|
5319
5539
|
return null;
|
|
5320
5540
|
}
|
|
5321
|
-
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext) {
|
|
5541
|
+
async function assembleBootstrapPrompt(userMessage, tier = "full", chatId, permMode, responseStyle, agentMode, sideQuestContext, planningDirective) {
|
|
5322
5542
|
const sections = [];
|
|
5543
|
+
if (planningDirective) {
|
|
5544
|
+
sections.push(planningDirective);
|
|
5545
|
+
}
|
|
5323
5546
|
if (Date.now() - lastSyncMs >= 5e3) {
|
|
5324
5547
|
syncNativeCliFiles();
|
|
5325
5548
|
lastSyncMs = Date.now();
|
|
@@ -5515,7 +5738,7 @@ var init_loader = __esm({
|
|
|
5515
5738
|
init_store();
|
|
5516
5739
|
init_backends();
|
|
5517
5740
|
lastSyncMs = 0;
|
|
5518
|
-
CONTEXT_DIR2 =
|
|
5741
|
+
CONTEXT_DIR2 = join8(WORKSPACE_PATH, "context");
|
|
5519
5742
|
MAX_CONTEXT_CHARS = 4e3;
|
|
5520
5743
|
ACTIVITY_TOKEN_BUDGET = 1500;
|
|
5521
5744
|
INBOX_TOKEN_BUDGET = 2e3;
|
|
@@ -6007,13 +6230,13 @@ var init_quota = __esm({
|
|
|
6007
6230
|
|
|
6008
6231
|
// src/dashboard/middleware.ts
|
|
6009
6232
|
import { randomBytes } from "crypto";
|
|
6010
|
-
import { writeFileSync as writeFileSync2, mkdirSync as
|
|
6233
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
|
|
6011
6234
|
function getDashboardToken() {
|
|
6012
6235
|
return DASHBOARD_TOKEN;
|
|
6013
6236
|
}
|
|
6014
6237
|
function persistToken() {
|
|
6015
6238
|
try {
|
|
6016
|
-
|
|
6239
|
+
mkdirSync4(DATA_PATH, { recursive: true });
|
|
6017
6240
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
6018
6241
|
writeFileSync2(tokenPath, DASHBOARD_TOKEN, { mode: 384 });
|
|
6019
6242
|
} catch (err) {
|
|
@@ -6700,14 +6923,14 @@ var init_propagate = __esm({
|
|
|
6700
6923
|
});
|
|
6701
6924
|
|
|
6702
6925
|
// src/agents/mcp-config.ts
|
|
6703
|
-
import { mkdirSync as
|
|
6704
|
-
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";
|
|
6705
6928
|
import { fileURLToPath } from "url";
|
|
6706
6929
|
function generateOrchestratorMcpConfig(opts) {
|
|
6707
6930
|
const port = opts.port ?? process.env.DASHBOARD_PORT ?? "3141";
|
|
6708
|
-
const distPath =
|
|
6709
|
-
const tsxPath =
|
|
6710
|
-
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);
|
|
6711
6934
|
return {
|
|
6712
6935
|
name: opts.agentId === "main" ? "cc-claw" : `cc-claw-${opts.agentId.slice(0, 8)}`,
|
|
6713
6936
|
transport: "stdio",
|
|
@@ -6722,7 +6945,7 @@ function generateOrchestratorMcpConfig(opts) {
|
|
|
6722
6945
|
};
|
|
6723
6946
|
}
|
|
6724
6947
|
function writeMcpConfigFile(config2) {
|
|
6725
|
-
|
|
6948
|
+
mkdirSync5(MCP_CONFIG_DIR, { recursive: true, mode: 448 });
|
|
6726
6949
|
const jsonConfig = {
|
|
6727
6950
|
mcpServers: {
|
|
6728
6951
|
[config2.name]: {
|
|
@@ -6733,13 +6956,13 @@ function writeMcpConfigFile(config2) {
|
|
|
6733
6956
|
}
|
|
6734
6957
|
};
|
|
6735
6958
|
const safeName = config2.name.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
6736
|
-
const configPath =
|
|
6959
|
+
const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
6737
6960
|
writeFileSync3(configPath, JSON.stringify(jsonConfig, null, 2), { mode: 384 });
|
|
6738
6961
|
return configPath;
|
|
6739
6962
|
}
|
|
6740
6963
|
function deleteMcpConfigFile(mcpName) {
|
|
6741
6964
|
const safeName = mcpName.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
6742
|
-
const configPath =
|
|
6965
|
+
const configPath = join9(MCP_CONFIG_DIR, `mcp-${safeName}.json`);
|
|
6743
6966
|
try {
|
|
6744
6967
|
unlinkSync3(configPath);
|
|
6745
6968
|
} catch {
|
|
@@ -6747,12 +6970,12 @@ function deleteMcpConfigFile(mcpName) {
|
|
|
6747
6970
|
}
|
|
6748
6971
|
function cleanupOrphanedMcpConfigs() {
|
|
6749
6972
|
try {
|
|
6750
|
-
if (!
|
|
6751
|
-
const files =
|
|
6973
|
+
if (!existsSync10(MCP_CONFIG_DIR)) return;
|
|
6974
|
+
const files = readdirSync4(MCP_CONFIG_DIR);
|
|
6752
6975
|
for (const file of files) {
|
|
6753
6976
|
if (file.startsWith("mcp-cc-claw-") && file.endsWith(".json")) {
|
|
6754
6977
|
try {
|
|
6755
|
-
unlinkSync3(
|
|
6978
|
+
unlinkSync3(join9(MCP_CONFIG_DIR, file));
|
|
6756
6979
|
} catch {
|
|
6757
6980
|
}
|
|
6758
6981
|
}
|
|
@@ -6766,8 +6989,8 @@ var init_mcp_config = __esm({
|
|
|
6766
6989
|
"use strict";
|
|
6767
6990
|
init_paths();
|
|
6768
6991
|
__filename = fileURLToPath(import.meta.url);
|
|
6769
|
-
__dirname =
|
|
6770
|
-
MCP_CONFIG_DIR =
|
|
6992
|
+
__dirname = dirname2(__filename);
|
|
6993
|
+
MCP_CONFIG_DIR = join9(CC_CLAW_HOME, "mcp-configs");
|
|
6771
6994
|
}
|
|
6772
6995
|
});
|
|
6773
6996
|
|
|
@@ -6777,8 +7000,8 @@ __export(loader_exports, {
|
|
|
6777
7000
|
getTemplate: () => getTemplate,
|
|
6778
7001
|
listTemplates: () => listTemplates
|
|
6779
7002
|
});
|
|
6780
|
-
import { readdirSync as
|
|
6781
|
-
import { join as
|
|
7003
|
+
import { readdirSync as readdirSync5, readFileSync as readFileSync5 } from "fs";
|
|
7004
|
+
import { join as join10 } from "path";
|
|
6782
7005
|
function parseFrontmatter(content) {
|
|
6783
7006
|
const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/m);
|
|
6784
7007
|
if (!match || match.index !== 0) return { meta: {}, body: content.trim() };
|
|
@@ -6811,12 +7034,12 @@ function scanTemplates() {
|
|
|
6811
7034
|
templateCache.clear();
|
|
6812
7035
|
let files;
|
|
6813
7036
|
try {
|
|
6814
|
-
files =
|
|
7037
|
+
files = readdirSync5(AGENTS_PATH).filter((f) => f.endsWith(".md"));
|
|
6815
7038
|
} catch {
|
|
6816
7039
|
return;
|
|
6817
7040
|
}
|
|
6818
7041
|
for (const file of files) {
|
|
6819
|
-
const filePath =
|
|
7042
|
+
const filePath = join10(AGENTS_PATH, file);
|
|
6820
7043
|
try {
|
|
6821
7044
|
const raw = readFileSync5(filePath, "utf-8");
|
|
6822
7045
|
const { meta, body } = parseFrontmatter(raw);
|
|
@@ -6865,8 +7088,8 @@ var init_loader2 = __esm({
|
|
|
6865
7088
|
});
|
|
6866
7089
|
|
|
6867
7090
|
// src/agents/agent-log.ts
|
|
6868
|
-
import { writeFileSync as writeFileSync4, readdirSync as
|
|
6869
|
-
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";
|
|
6870
7093
|
function truncate(text, maxBytes) {
|
|
6871
7094
|
if (Buffer.byteLength(text, "utf-8") <= maxBytes) return text;
|
|
6872
7095
|
let lo = 0, hi = text.length;
|
|
@@ -6881,7 +7104,7 @@ function truncate(text, maxBytes) {
|
|
|
6881
7104
|
[...truncated ${droppedBytes} bytes...]`;
|
|
6882
7105
|
}
|
|
6883
7106
|
function writeAgentLog(data) {
|
|
6884
|
-
const logPath =
|
|
7107
|
+
const logPath = join11(AGENTS_PATH, `${data.agentId}.log`);
|
|
6885
7108
|
const exitDisplay = data.exitCodeForced ? `${data.exitCode} (forced \u2014 no output from original exit code 0)` : String(data.exitCode ?? "null");
|
|
6886
7109
|
const stderrContent = truncate(data.stderr || "(empty)", MAX_STDERR_BYTES);
|
|
6887
7110
|
const stdoutContent = truncate(data.rawStdoutLines.join("\n") || "(empty)", MAX_STDOUT_BYTES);
|
|
@@ -6905,7 +7128,7 @@ function writeAgentLog(data) {
|
|
|
6905
7128
|
""
|
|
6906
7129
|
];
|
|
6907
7130
|
try {
|
|
6908
|
-
|
|
7131
|
+
mkdirSync6(AGENTS_PATH, { recursive: true });
|
|
6909
7132
|
writeFileSync4(logPath, lines.join("\n"), "utf-8");
|
|
6910
7133
|
} catch (err) {
|
|
6911
7134
|
log(`[agent-log] Failed to write log for ${data.agentId}: ${err}`);
|
|
@@ -6914,10 +7137,10 @@ function writeAgentLog(data) {
|
|
|
6914
7137
|
}
|
|
6915
7138
|
function pruneAgentLogs() {
|
|
6916
7139
|
try {
|
|
6917
|
-
|
|
6918
|
-
const files =
|
|
6919
|
-
const fullPath =
|
|
6920
|
-
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);
|
|
6921
7144
|
return { path: fullPath, mtime: stat4.mtimeMs, size: stat4.size };
|
|
6922
7145
|
});
|
|
6923
7146
|
const now = Date.now();
|
|
@@ -6962,7 +7185,7 @@ var init_agent_log = __esm({
|
|
|
6962
7185
|
});
|
|
6963
7186
|
|
|
6964
7187
|
// src/agents/orchestrator.ts
|
|
6965
|
-
import { existsSync as
|
|
7188
|
+
import { existsSync as existsSync11 } from "fs";
|
|
6966
7189
|
async function withRunnerLock(runnerId, fn) {
|
|
6967
7190
|
const prev = runnerLocks.get(runnerId) ?? Promise.resolve();
|
|
6968
7191
|
const next = prev.then(fn, () => fn());
|
|
@@ -7080,7 +7303,7 @@ async function spawnSubAgent(chatId, opts) {
|
|
|
7080
7303
|
async function startAgent(agentId, chatId, opts) {
|
|
7081
7304
|
const db3 = getDb();
|
|
7082
7305
|
const runner = getRunner(opts.runner);
|
|
7083
|
-
if (opts.cwd && !
|
|
7306
|
+
if (opts.cwd && !existsSync11(opts.cwd)) {
|
|
7084
7307
|
const msg = `Directory not found: ${opts.cwd}`;
|
|
7085
7308
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
7086
7309
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -7102,7 +7325,7 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
7102
7325
|
return;
|
|
7103
7326
|
}
|
|
7104
7327
|
const exePath = runner.getExecutablePath();
|
|
7105
|
-
if (exePath.startsWith("/") && !
|
|
7328
|
+
if (exePath.startsWith("/") && !existsSync11(exePath)) {
|
|
7106
7329
|
const msg = `Executable not found: ${exePath}`;
|
|
7107
7330
|
error(`[orchestrator] Agent ${agentId}: ${msg}`);
|
|
7108
7331
|
updateAgentStatus(db3, agentId, "failed");
|
|
@@ -7372,10 +7595,10 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
7372
7595
|
function diagnoseSpawnError(err, exePath, cwd) {
|
|
7373
7596
|
const nodeErr = err;
|
|
7374
7597
|
if (nodeErr.code === "ENOENT") {
|
|
7375
|
-
if (cwd && !
|
|
7598
|
+
if (cwd && !existsSync11(cwd)) {
|
|
7376
7599
|
return `Directory not found: ${cwd}`;
|
|
7377
7600
|
}
|
|
7378
|
-
if (exePath.startsWith("/") && !
|
|
7601
|
+
if (exePath.startsWith("/") && !existsSync11(exePath)) {
|
|
7379
7602
|
return `Executable not found: ${exePath}`;
|
|
7380
7603
|
}
|
|
7381
7604
|
return `ENOENT spawning ${exePath} (cwd: ${cwd ?? "inherited"}) \u2014 check that both the binary and directory exist`;
|
|
@@ -7764,7 +7987,7 @@ var init_registry2 = __esm({
|
|
|
7764
7987
|
});
|
|
7765
7988
|
|
|
7766
7989
|
// src/dashboard/routes/orchestrator.ts
|
|
7767
|
-
import { existsSync as
|
|
7990
|
+
import { existsSync as existsSync12 } from "fs";
|
|
7768
7991
|
var handleSpawn, handleCancel, handleCancelAll, handleCreateTask, handleUpdateTask, handleSendMessage, handleReadInbox, handleSetState, handleGetState, handleListState, handleBroadcast, handleListRunners, handleListMcps, handleListTemplates, handleCheckAgent;
|
|
7769
7992
|
var init_orchestrator2 = __esm({
|
|
7770
7993
|
"src/dashboard/routes/orchestrator.ts"() {
|
|
@@ -7780,7 +8003,7 @@ var init_orchestrator2 = __esm({
|
|
|
7780
8003
|
handleSpawn = async (req, res) => {
|
|
7781
8004
|
try {
|
|
7782
8005
|
const body = JSON.parse(await readBody(req));
|
|
7783
|
-
if (body.cwd && !
|
|
8006
|
+
if (body.cwd && !existsSync12(body.cwd)) {
|
|
7784
8007
|
return jsonResponse(res, { error: `Directory not found: ${body.cwd}` }, 400);
|
|
7785
8008
|
}
|
|
7786
8009
|
if (!body.permMode || body.permMode === "inherit") {
|
|
@@ -9047,8 +9270,8 @@ __export(analyze_exports, {
|
|
|
9047
9270
|
});
|
|
9048
9271
|
import { spawn as spawn4 } from "child_process";
|
|
9049
9272
|
import { createInterface as createInterface3 } from "readline";
|
|
9050
|
-
import { readFileSync as readFileSync6, existsSync as
|
|
9051
|
-
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";
|
|
9052
9275
|
import { homedir as homedir4 } from "os";
|
|
9053
9276
|
function applySignalDecay(confidence, createdAt) {
|
|
9054
9277
|
const ageMs = Date.now() - (/* @__PURE__ */ new Date(createdAt + (createdAt.endsWith("Z") ? "" : "Z"))).getTime();
|
|
@@ -9057,16 +9280,16 @@ function applySignalDecay(confidence, createdAt) {
|
|
|
9057
9280
|
return decayed >= SIGNAL_DECAY_MIN_CONFIDENCE ? Math.round(decayed * 100) / 100 : 0;
|
|
9058
9281
|
}
|
|
9059
9282
|
function discoverReflectionTargets() {
|
|
9060
|
-
const ccClawHome =
|
|
9283
|
+
const ccClawHome = join12(homedir4(), ".cc-claw");
|
|
9061
9284
|
const targets = [];
|
|
9062
9285
|
try {
|
|
9063
|
-
const skillsDir =
|
|
9064
|
-
if (
|
|
9065
|
-
for (const entry of
|
|
9066
|
-
const entryPath =
|
|
9067
|
-
if (!
|
|
9068
|
-
const skillFile =
|
|
9069
|
-
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;
|
|
9070
9293
|
let desc = "skill";
|
|
9071
9294
|
try {
|
|
9072
9295
|
const content = readFileSync6(skillFile, "utf-8");
|
|
@@ -9080,9 +9303,9 @@ function discoverReflectionTargets() {
|
|
|
9080
9303
|
} catch {
|
|
9081
9304
|
}
|
|
9082
9305
|
try {
|
|
9083
|
-
const contextDir =
|
|
9084
|
-
if (
|
|
9085
|
-
for (const entry of
|
|
9306
|
+
const contextDir = join12(ccClawHome, "workspace", "context");
|
|
9307
|
+
if (existsSync13(contextDir)) {
|
|
9308
|
+
for (const entry of readdirSync7(contextDir)) {
|
|
9086
9309
|
if (!entry.endsWith(".md")) continue;
|
|
9087
9310
|
const name = entry.replace(/\.md$/, "");
|
|
9088
9311
|
targets.push({ path: `workspace/context/${entry}`, description: `context file: ${name}` });
|
|
@@ -9270,7 +9493,7 @@ function resolveReflectionAdapter(chatId) {
|
|
|
9270
9493
|
}
|
|
9271
9494
|
function readIdentityFile(filename) {
|
|
9272
9495
|
try {
|
|
9273
|
-
return readFileSync6(
|
|
9496
|
+
return readFileSync6(join12(IDENTITY_PATH, filename), "utf-8");
|
|
9274
9497
|
} catch {
|
|
9275
9498
|
return "";
|
|
9276
9499
|
}
|
|
@@ -9418,7 +9641,7 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
9418
9641
|
const availableTargets = discoverReflectionTargets();
|
|
9419
9642
|
const SKILL_CONTENT_CAP = 15e3;
|
|
9420
9643
|
const skillContents = [];
|
|
9421
|
-
const ccClawHome =
|
|
9644
|
+
const ccClawHome = join12(homedir4(), ".cc-claw");
|
|
9422
9645
|
const signalCorpus = signals.map((s) => s.trigger).join(" ").toLowerCase();
|
|
9423
9646
|
const convCorpus = (conversations ?? "").toLowerCase();
|
|
9424
9647
|
const searchCorpus = signalCorpus + " " + convCorpus;
|
|
@@ -9431,8 +9654,8 @@ async function runAnalysisImpl(chatId, opts) {
|
|
|
9431
9654
|
const isRelevant = searchCorpus.includes(skillNameNorm) || searchCorpus.includes(skillName.toLowerCase()) || descNorm.split(/\s+/).some((word) => word.length > 4 && searchCorpus.includes(word));
|
|
9432
9655
|
if (!isRelevant) continue;
|
|
9433
9656
|
try {
|
|
9434
|
-
const fullPath =
|
|
9435
|
-
if (
|
|
9657
|
+
const fullPath = join12(ccClawHome, target.path);
|
|
9658
|
+
if (existsSync13(fullPath)) {
|
|
9436
9659
|
const content = readFileSync6(fullPath, "utf-8");
|
|
9437
9660
|
if (totalSkillChars + content.length > SKILL_CONTENT_CAP) break;
|
|
9438
9661
|
skillContents.push({ path: target.path, content });
|
|
@@ -9638,8 +9861,8 @@ __export(apply_exports, {
|
|
|
9638
9861
|
isTargetAllowed: () => isTargetAllowed,
|
|
9639
9862
|
rollbackInsight: () => rollbackInsight
|
|
9640
9863
|
});
|
|
9641
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as
|
|
9642
|
-
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";
|
|
9643
9866
|
function isTargetAllowed(relativePath) {
|
|
9644
9867
|
if (relativePath.includes("..")) return false;
|
|
9645
9868
|
if (!relativePath.endsWith(".md")) return false;
|
|
@@ -9690,10 +9913,10 @@ function applyDiff(original, diff, action) {
|
|
|
9690
9913
|
return original;
|
|
9691
9914
|
}
|
|
9692
9915
|
function pruneBackups(absolutePath) {
|
|
9693
|
-
const dir =
|
|
9916
|
+
const dir = dirname3(absolutePath);
|
|
9694
9917
|
const baseName = absolutePath.split("/").pop() ?? "";
|
|
9695
9918
|
try {
|
|
9696
|
-
const backups =
|
|
9919
|
+
const backups = readdirSync8(dir).filter((f) => f.startsWith(baseName + ".bak.")).sort().map((f) => join13(dir, f));
|
|
9697
9920
|
while (backups.length > MAX_BACKUPS_PER_FILE) {
|
|
9698
9921
|
const oldest = backups.shift();
|
|
9699
9922
|
try {
|
|
@@ -9719,9 +9942,9 @@ async function applyInsight(insightId) {
|
|
|
9719
9942
|
if (!isTargetAllowed(insight.targetFile)) {
|
|
9720
9943
|
return { success: false, message: `Target file "${insight.targetFile}" is not in the allowed list` };
|
|
9721
9944
|
}
|
|
9722
|
-
const absolutePath =
|
|
9945
|
+
const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
|
|
9723
9946
|
if (insight.proposedAction === "append" && insight.targetFile === "identity/SOUL.md") {
|
|
9724
|
-
if (
|
|
9947
|
+
if (existsSync14(absolutePath)) {
|
|
9725
9948
|
const currentContent = readFileSync7(absolutePath, "utf-8");
|
|
9726
9949
|
const lineCount = currentContent.split("\n").length;
|
|
9727
9950
|
if (lineCount >= SOUL_LINE_CAP) {
|
|
@@ -9743,7 +9966,7 @@ async function applyInsight(insightId) {
|
|
|
9743
9966
|
};
|
|
9744
9967
|
}
|
|
9745
9968
|
let original = "";
|
|
9746
|
-
if (
|
|
9969
|
+
if (existsSync14(absolutePath)) {
|
|
9747
9970
|
original = readFileSync7(absolutePath, "utf-8");
|
|
9748
9971
|
} else if (insight.proposedAction !== "create") {
|
|
9749
9972
|
return { success: false, message: `Target file "${insight.targetFile}" does not exist` };
|
|
@@ -9751,9 +9974,9 @@ async function applyInsight(insightId) {
|
|
|
9751
9974
|
const timestamp = Date.now();
|
|
9752
9975
|
const backupPath = absolutePath + `.bak.${timestamp}`;
|
|
9753
9976
|
try {
|
|
9754
|
-
const parentDir =
|
|
9755
|
-
if (!
|
|
9756
|
-
|
|
9977
|
+
const parentDir = dirname3(absolutePath);
|
|
9978
|
+
if (!existsSync14(parentDir)) {
|
|
9979
|
+
mkdirSync7(parentDir, { recursive: true });
|
|
9757
9980
|
}
|
|
9758
9981
|
if (original) {
|
|
9759
9982
|
writeFileSync5(backupPath, original, "utf-8");
|
|
@@ -9816,7 +10039,7 @@ async function rollbackInsight(insightId) {
|
|
|
9816
10039
|
} catch {
|
|
9817
10040
|
return { success: false, message: `Insight #${insightId} has malformed rollback data` };
|
|
9818
10041
|
}
|
|
9819
|
-
const absolutePath =
|
|
10042
|
+
const absolutePath = join13(CC_CLAW_HOME, insight.targetFile);
|
|
9820
10043
|
try {
|
|
9821
10044
|
writeFileSync5(absolutePath, rollback.original, "utf-8");
|
|
9822
10045
|
updateInsightStatus(db3, insightId, "rolled_back");
|
|
@@ -9849,8 +10072,8 @@ function calculateDrift(chatId) {
|
|
|
9849
10072
|
if (!row || !row.baselineSoulMd && !row.baselineUserMd) {
|
|
9850
10073
|
return null;
|
|
9851
10074
|
}
|
|
9852
|
-
const soulPath =
|
|
9853
|
-
const userPath =
|
|
10075
|
+
const soulPath = join13(CC_CLAW_HOME, "identity/SOUL.md");
|
|
10076
|
+
const userPath = join13(CC_CLAW_HOME, "identity/USER.md");
|
|
9854
10077
|
const soulDrift = computeLineDrift(row.baselineSoulMd, soulPath);
|
|
9855
10078
|
const userDrift = computeLineDrift(row.baselineUserMd, userPath);
|
|
9856
10079
|
return { soulDrift, userDrift };
|
|
@@ -9859,7 +10082,7 @@ function computeLineDrift(baseline, absolutePath) {
|
|
|
9859
10082
|
if (!baseline) return 0;
|
|
9860
10083
|
let current = "";
|
|
9861
10084
|
try {
|
|
9862
|
-
if (
|
|
10085
|
+
if (existsSync14(absolutePath)) {
|
|
9863
10086
|
current = readFileSync7(absolutePath, "utf-8");
|
|
9864
10087
|
}
|
|
9865
10088
|
} catch {
|
|
@@ -9955,11 +10178,11 @@ var init_evolve = __esm({
|
|
|
9955
10178
|
const body = JSON.parse(await readBody(req));
|
|
9956
10179
|
const { setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
9957
10180
|
const { existsSync: fileExists, readFileSync: fileRead } = await import("fs");
|
|
9958
|
-
const { join:
|
|
10181
|
+
const { join: join30 } = await import("path");
|
|
9959
10182
|
const { CC_CLAW_HOME: home } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
9960
10183
|
const chatId = body.chatId || (process.env.ALLOWED_CHAT_ID ?? "").split(",")[0]?.trim() || "default";
|
|
9961
|
-
const soulPath =
|
|
9962
|
-
const userPath =
|
|
10184
|
+
const soulPath = join30(home, "identity/SOUL.md");
|
|
10185
|
+
const userPath = join30(home, "identity/USER.md");
|
|
9963
10186
|
const soul = fileExists(soulPath) ? fileRead(soulPath, "utf-8") : "";
|
|
9964
10187
|
const user = fileExists(userPath) ? fileRead(userPath, "utf-8") : "";
|
|
9965
10188
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
@@ -10905,7 +11128,7 @@ function askAgent(chatId, userMessage, opts) {
|
|
|
10905
11128
|
return withChatLock(chatId, () => askAgentImpl(chatId, userMessage, opts));
|
|
10906
11129
|
}
|
|
10907
11130
|
async function askAgentImpl(chatId, userMessage, opts) {
|
|
10908
|
-
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 ?? {};
|
|
10909
11132
|
const settingsChat = settingsSourceChatId ?? chatId;
|
|
10910
11133
|
const adapter = backend2 ? getAdapter(backend2) : getAdapterForChat(settingsChat);
|
|
10911
11134
|
const mode = permMode ?? getMode(settingsChat);
|
|
@@ -10915,7 +11138,7 @@ async function askAgentImpl(chatId, userMessage, opts) {
|
|
|
10915
11138
|
const tier = bootstrapTier ?? "full";
|
|
10916
11139
|
const effectiveAgentMode = optsAgentMode ?? getAgentMode(settingsChat);
|
|
10917
11140
|
const sideQuestCtx = settingsSourceChatId ? { parentChatId: settingsSourceChatId, actualChatId: chatId } : void 0;
|
|
10918
|
-
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx);
|
|
11141
|
+
const fullPrompt = await assembleBootstrapPrompt(userMessage, tier, settingsChat, mode, responseStyle, effectiveAgentMode, sideQuestCtx, planningDirective);
|
|
10919
11142
|
const existingSessionId = settingsSourceChatId ? null : getSessionId(settingsChat);
|
|
10920
11143
|
const allowedTools = getEnabledTools(settingsChat);
|
|
10921
11144
|
const mcpConfigPath = tier !== "slim" && effectiveAgentMode !== "native" && MCP_CONFIG_FLAG[adapter.id] ? getMcpConfigPath(chatId) : null;
|
|
@@ -11517,9 +11740,9 @@ function buildReviewCompleteMessage(results) {
|
|
|
11517
11740
|
|
|
11518
11741
|
Skipped proposals will appear in your next review.`;
|
|
11519
11742
|
}
|
|
11520
|
-
function formatNightlySummary(insights) {
|
|
11521
|
-
const
|
|
11522
|
-
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`;
|
|
11523
11746
|
const list = insights.map((ins, i) => `${i + 1}. [${ins.category}] ${ins.insight}`).join("\n");
|
|
11524
11747
|
return `${header2}
|
|
11525
11748
|
|
|
@@ -11630,8 +11853,8 @@ var init_propose = __esm({
|
|
|
11630
11853
|
});
|
|
11631
11854
|
|
|
11632
11855
|
// src/bootstrap/profile.ts
|
|
11633
|
-
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as
|
|
11634
|
-
import { join as
|
|
11856
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, existsSync as existsSync15 } from "fs";
|
|
11857
|
+
import { join as join14 } from "path";
|
|
11635
11858
|
function hasActiveProfile(chatId) {
|
|
11636
11859
|
return activeProfiles.has(chatId);
|
|
11637
11860
|
}
|
|
@@ -11760,7 +11983,7 @@ function extractUserUpdates(text) {
|
|
|
11760
11983
|
return { cleanText, updates };
|
|
11761
11984
|
}
|
|
11762
11985
|
function appendToUserProfile(key, value) {
|
|
11763
|
-
if (!
|
|
11986
|
+
if (!existsSync15(USER_PATH2)) return;
|
|
11764
11987
|
const content = readFileSync8(USER_PATH2, "utf-8");
|
|
11765
11988
|
const line = `- **${key}**: ${value}`;
|
|
11766
11989
|
if (content.includes(line)) return;
|
|
@@ -11776,7 +11999,7 @@ var init_profile = __esm({
|
|
|
11776
11999
|
"use strict";
|
|
11777
12000
|
init_paths();
|
|
11778
12001
|
init_log();
|
|
11779
|
-
USER_PATH2 =
|
|
12002
|
+
USER_PATH2 = join14(IDENTITY_PATH, "USER.md");
|
|
11780
12003
|
activeProfiles = /* @__PURE__ */ new Map();
|
|
11781
12004
|
}
|
|
11782
12005
|
});
|
|
@@ -12607,6 +12830,88 @@ var init_classify2 = __esm({
|
|
|
12607
12830
|
}
|
|
12608
12831
|
});
|
|
12609
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
|
+
|
|
12610
12915
|
// src/router/helpers.ts
|
|
12611
12916
|
import { resolve as resolvePath } from "path";
|
|
12612
12917
|
function parseMcpListOutput(output2) {
|
|
@@ -13307,9 +13612,9 @@ var init_stt = __esm({
|
|
|
13307
13612
|
});
|
|
13308
13613
|
|
|
13309
13614
|
// src/media/image-gen.ts
|
|
13310
|
-
import { mkdirSync as
|
|
13615
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync16, unlink as unlink2, readdir, stat } from "fs";
|
|
13311
13616
|
import { writeFile } from "fs/promises";
|
|
13312
|
-
import { join as
|
|
13617
|
+
import { join as join15 } from "path";
|
|
13313
13618
|
async function generateImage(prompt) {
|
|
13314
13619
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
13315
13620
|
if (!apiKey) {
|
|
@@ -13356,12 +13661,12 @@ async function generateImage(prompt) {
|
|
|
13356
13661
|
if (!imageData) {
|
|
13357
13662
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
13358
13663
|
}
|
|
13359
|
-
if (!
|
|
13360
|
-
|
|
13664
|
+
if (!existsSync16(IMAGE_OUTPUT_DIR)) {
|
|
13665
|
+
mkdirSync8(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
13361
13666
|
}
|
|
13362
13667
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
13363
13668
|
const filename = `img_${Date.now()}.${ext}`;
|
|
13364
|
-
const filePath =
|
|
13669
|
+
const filePath = join15(IMAGE_OUTPUT_DIR, filename);
|
|
13365
13670
|
const buffer = Buffer.from(imageData, "base64");
|
|
13366
13671
|
await writeFile(filePath, buffer);
|
|
13367
13672
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
@@ -13379,7 +13684,7 @@ function cleanupGeneratedImage(filePath) {
|
|
|
13379
13684
|
function pruneImageCache() {
|
|
13380
13685
|
readdir(IMAGE_OUTPUT_DIR, (err, files) => {
|
|
13381
13686
|
if (err || !files) return;
|
|
13382
|
-
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));
|
|
13383
13688
|
if (imageFiles.length === 0) return;
|
|
13384
13689
|
const now = Date.now();
|
|
13385
13690
|
let statsPending = imageFiles.length;
|
|
@@ -13411,8 +13716,8 @@ var init_image_gen = __esm({
|
|
|
13411
13716
|
MAX_GENERATED_IMAGES = 20;
|
|
13412
13717
|
IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
13413
13718
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
13414
|
-
IMAGE_OUTPUT_DIR =
|
|
13415
|
-
process.env.CC_CLAW_HOME ??
|
|
13719
|
+
IMAGE_OUTPUT_DIR = join15(
|
|
13720
|
+
process.env.CC_CLAW_HOME ?? join15(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
13416
13721
|
"data",
|
|
13417
13722
|
"images"
|
|
13418
13723
|
);
|
|
@@ -13885,7 +14190,7 @@ var init_video = __esm({
|
|
|
13885
14190
|
});
|
|
13886
14191
|
|
|
13887
14192
|
// src/router/media.ts
|
|
13888
|
-
import { join as
|
|
14193
|
+
import { join as join16 } from "path";
|
|
13889
14194
|
import { mkdir, writeFile as writeFile2, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
|
|
13890
14195
|
function getMediaRetentionMs() {
|
|
13891
14196
|
const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
|
|
@@ -13894,7 +14199,7 @@ function getMediaRetentionMs() {
|
|
|
13894
14199
|
async function saveMedia(buffer, prefix, ext) {
|
|
13895
14200
|
await mkdir(MEDIA_INCOMING_PATH, { recursive: true });
|
|
13896
14201
|
const filename = `${prefix}-${Date.now()}.${ext}`;
|
|
13897
|
-
const fullPath =
|
|
14202
|
+
const fullPath = join16(MEDIA_INCOMING_PATH, filename);
|
|
13898
14203
|
await writeFile2(fullPath, buffer);
|
|
13899
14204
|
return fullPath;
|
|
13900
14205
|
}
|
|
@@ -13908,7 +14213,7 @@ async function cleanupOldMedia() {
|
|
|
13908
14213
|
let removed = 0;
|
|
13909
14214
|
for (const file of files) {
|
|
13910
14215
|
try {
|
|
13911
|
-
const filePath =
|
|
14216
|
+
const filePath = join16(MEDIA_INCOMING_PATH, file);
|
|
13912
14217
|
const s = await stat2(filePath);
|
|
13913
14218
|
if (now - s.mtimeMs > retentionMs) {
|
|
13914
14219
|
await unlink3(filePath);
|
|
@@ -14091,7 +14396,7 @@ var init_media = __esm({
|
|
|
14091
14396
|
init_store5();
|
|
14092
14397
|
init_helpers();
|
|
14093
14398
|
init_response();
|
|
14094
|
-
MEDIA_INCOMING_PATH =
|
|
14399
|
+
MEDIA_INCOMING_PATH = join16(MEDIA_PATH, "incoming");
|
|
14095
14400
|
}
|
|
14096
14401
|
});
|
|
14097
14402
|
|
|
@@ -14227,7 +14532,7 @@ __export(discover_exports, {
|
|
|
14227
14532
|
import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
|
|
14228
14533
|
import { createHash } from "crypto";
|
|
14229
14534
|
import { homedir as homedir5 } from "os";
|
|
14230
|
-
import { join as
|
|
14535
|
+
import { join as join17 } from "path";
|
|
14231
14536
|
function invalidateSkillCache() {
|
|
14232
14537
|
cachedSkills = null;
|
|
14233
14538
|
cacheTimestamp = 0;
|
|
@@ -14245,7 +14550,7 @@ async function discoverAllSkills() {
|
|
|
14245
14550
|
const rawSkills = [];
|
|
14246
14551
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
14247
14552
|
for (const backendId of getAllBackendIds()) {
|
|
14248
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [
|
|
14553
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join17(homedir5(), `.${backendId}`, "skills")];
|
|
14249
14554
|
for (const dir of dirs) {
|
|
14250
14555
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
14251
14556
|
}
|
|
@@ -14273,7 +14578,7 @@ async function scanSkillDir(skillsDir, source) {
|
|
|
14273
14578
|
let content;
|
|
14274
14579
|
let resolvedPath;
|
|
14275
14580
|
for (const candidate of SKILL_FILE_CANDIDATES) {
|
|
14276
|
-
const p =
|
|
14581
|
+
const p = join17(skillsDir, entry.name, candidate);
|
|
14277
14582
|
try {
|
|
14278
14583
|
content = await readFile4(p, "utf-8");
|
|
14279
14584
|
resolvedPath = p;
|
|
@@ -14377,15 +14682,15 @@ var init_discover = __esm({
|
|
|
14377
14682
|
init_backends();
|
|
14378
14683
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
14379
14684
|
BACKEND_SKILL_DIRS = {
|
|
14380
|
-
claude: [
|
|
14381
|
-
gemini: [
|
|
14685
|
+
claude: [join17(homedir5(), ".claude", "skills")],
|
|
14686
|
+
gemini: [join17(homedir5(), ".gemini", "skills")],
|
|
14382
14687
|
codex: [
|
|
14383
|
-
|
|
14384
|
-
|
|
14688
|
+
join17(homedir5(), ".agents", "skills"),
|
|
14689
|
+
join17(homedir5(), ".codex", "skills")
|
|
14385
14690
|
],
|
|
14386
14691
|
cursor: [
|
|
14387
|
-
|
|
14388
|
-
|
|
14692
|
+
join17(homedir5(), ".cursor", "skills"),
|
|
14693
|
+
join17(homedir5(), ".cursor", "skills-cursor")
|
|
14389
14694
|
]
|
|
14390
14695
|
};
|
|
14391
14696
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -14401,8 +14706,8 @@ __export(install_exports, {
|
|
|
14401
14706
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
14402
14707
|
});
|
|
14403
14708
|
import { mkdir as mkdir2, readdir as readdir4, readFile as readFile5, cp } from "fs/promises";
|
|
14404
|
-
import { existsSync as
|
|
14405
|
-
import { join as
|
|
14709
|
+
import { existsSync as existsSync17 } from "fs";
|
|
14710
|
+
import { join as join18, basename } from "path";
|
|
14406
14711
|
import { execSync as execSync5 } from "child_process";
|
|
14407
14712
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
14408
14713
|
let repoUrl;
|
|
@@ -14413,36 +14718,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
14413
14718
|
}
|
|
14414
14719
|
repoUrl = parsed.cloneUrl;
|
|
14415
14720
|
subPath = parsed.subPath;
|
|
14416
|
-
const tmpDir =
|
|
14721
|
+
const tmpDir = join18("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
14417
14722
|
try {
|
|
14418
14723
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
14419
14724
|
execSync5(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
14420
14725
|
stdio: "pipe",
|
|
14421
14726
|
timeout: 3e4
|
|
14422
14727
|
});
|
|
14423
|
-
if (!
|
|
14728
|
+
if (!existsSync17(join18(tmpDir, ".git"))) {
|
|
14424
14729
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
14425
14730
|
}
|
|
14426
|
-
const searchRoot = subPath ?
|
|
14731
|
+
const searchRoot = subPath ? join18(tmpDir, subPath) : tmpDir;
|
|
14427
14732
|
const skillDir = await findSkillDir(searchRoot);
|
|
14428
14733
|
if (!skillDir) {
|
|
14429
14734
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
14430
14735
|
}
|
|
14431
14736
|
const skillFolderName = basename(skillDir);
|
|
14432
|
-
const destDir =
|
|
14433
|
-
if (
|
|
14737
|
+
const destDir = join18(SKILLS_PATH, skillFolderName);
|
|
14738
|
+
if (existsSync17(destDir)) {
|
|
14434
14739
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
14435
14740
|
}
|
|
14436
14741
|
await mkdir2(destDir, { recursive: true });
|
|
14437
14742
|
await cp(skillDir, destDir, { recursive: true });
|
|
14438
14743
|
let skillName = skillFolderName;
|
|
14439
14744
|
try {
|
|
14440
|
-
const content = await readFile5(
|
|
14745
|
+
const content = await readFile5(join18(destDir, "SKILL.md"), "utf-8");
|
|
14441
14746
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14442
14747
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14443
14748
|
} catch {
|
|
14444
14749
|
try {
|
|
14445
|
-
const content = await readFile5(
|
|
14750
|
+
const content = await readFile5(join18(destDir, "skill.md"), "utf-8");
|
|
14446
14751
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14447
14752
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14448
14753
|
} catch {
|
|
@@ -14477,15 +14782,15 @@ function parseGitHubUrl(input) {
|
|
|
14477
14782
|
async function findSkillDir(root) {
|
|
14478
14783
|
const candidates = ["SKILL.md", "skill.md"];
|
|
14479
14784
|
for (const c of candidates) {
|
|
14480
|
-
if (
|
|
14785
|
+
if (existsSync17(join18(root, c))) return root;
|
|
14481
14786
|
}
|
|
14482
14787
|
try {
|
|
14483
14788
|
const entries = await readdir4(root, { withFileTypes: true });
|
|
14484
14789
|
for (const entry of entries) {
|
|
14485
14790
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14486
14791
|
for (const c of candidates) {
|
|
14487
|
-
if (
|
|
14488
|
-
return
|
|
14792
|
+
if (existsSync17(join18(root, entry.name, c))) {
|
|
14793
|
+
return join18(root, entry.name);
|
|
14489
14794
|
}
|
|
14490
14795
|
}
|
|
14491
14796
|
}
|
|
@@ -14497,15 +14802,15 @@ async function findSkillDir(root) {
|
|
|
14497
14802
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14498
14803
|
let subEntries;
|
|
14499
14804
|
try {
|
|
14500
|
-
subEntries = await readdir4(
|
|
14805
|
+
subEntries = await readdir4(join18(root, entry.name), { withFileTypes: true });
|
|
14501
14806
|
} catch {
|
|
14502
14807
|
continue;
|
|
14503
14808
|
}
|
|
14504
14809
|
for (const sub of subEntries) {
|
|
14505
14810
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
14506
14811
|
for (const c of candidates) {
|
|
14507
|
-
if (
|
|
14508
|
-
return
|
|
14812
|
+
if (existsSync17(join18(root, entry.name, sub.name, c))) {
|
|
14813
|
+
return join18(root, entry.name, sub.name);
|
|
14509
14814
|
}
|
|
14510
14815
|
}
|
|
14511
14816
|
}
|
|
@@ -14523,8 +14828,8 @@ var init_install = __esm({
|
|
|
14523
14828
|
});
|
|
14524
14829
|
|
|
14525
14830
|
// src/bootstrap/heartbeat.ts
|
|
14526
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
14527
|
-
import { join as
|
|
14831
|
+
import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
|
|
14832
|
+
import { join as join19 } from "path";
|
|
14528
14833
|
function initHeartbeat(channelReg) {
|
|
14529
14834
|
registry2 = channelReg;
|
|
14530
14835
|
}
|
|
@@ -14662,7 +14967,7 @@ ${healthLines.join("\n")}`);
|
|
|
14662
14967
|
sections.push(`[Active watches]
|
|
14663
14968
|
${watchLines.join("\n")}`);
|
|
14664
14969
|
}
|
|
14665
|
-
if (
|
|
14970
|
+
if (existsSync18(HEARTBEAT_MD_PATH)) {
|
|
14666
14971
|
try {
|
|
14667
14972
|
const custom = readFileSync9(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
14668
14973
|
if (custom) {
|
|
@@ -14710,7 +15015,7 @@ var init_heartbeat2 = __esm({
|
|
|
14710
15015
|
init_backends();
|
|
14711
15016
|
init_health2();
|
|
14712
15017
|
init_log();
|
|
14713
|
-
HEARTBEAT_MD_PATH =
|
|
15018
|
+
HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
14714
15019
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
14715
15020
|
registry2 = null;
|
|
14716
15021
|
activeTimers = /* @__PURE__ */ new Map();
|
|
@@ -15767,9 +16072,9 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15767
16072
|
await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
|
|
15768
16073
|
} else {
|
|
15769
16074
|
const insightIds = pending.slice(0, 5).map((p) => p.id);
|
|
15770
|
-
createReviewSession2(getDb(),
|
|
16075
|
+
createReviewSession2(getDb(), chatId, insightIds);
|
|
15771
16076
|
await channel.sendText(chatId, `${pending.length} proposal(s) ready. Let's review them one by one.`, { parseMode: "plain" });
|
|
15772
|
-
await sendCurrentProposal(
|
|
16077
|
+
await sendCurrentProposal(chatId, channel);
|
|
15773
16078
|
}
|
|
15774
16079
|
break;
|
|
15775
16080
|
}
|
|
@@ -15927,13 +16232,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15927
16232
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15928
16233
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
15929
16234
|
if (current === "frozen") {
|
|
15930
|
-
const { readFileSync: readFileSync22, existsSync:
|
|
15931
|
-
const { join:
|
|
16235
|
+
const { readFileSync: readFileSync22, existsSync: existsSync50 } = await import("fs");
|
|
16236
|
+
const { join: join30 } = await import("path");
|
|
15932
16237
|
const { CC_CLAW_HOME: CC_CLAW_HOME3 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
15933
|
-
const soulPath =
|
|
15934
|
-
const userPath =
|
|
15935
|
-
const soul =
|
|
15936
|
-
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") : "";
|
|
15937
16242
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
15938
16243
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
15939
16244
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -16086,6 +16391,29 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
16086
16391
|
}
|
|
16087
16392
|
break;
|
|
16088
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
|
+
}
|
|
16089
16417
|
case "verbose": {
|
|
16090
16418
|
const currentVerbose = getVerboseLevel(chatId);
|
|
16091
16419
|
const buttons = Object.entries(VERBOSE_LEVELS).map(([id, label2]) => [{
|
|
@@ -17794,6 +18122,54 @@ ${PERM_MODES[chosen]}`,
|
|
|
17794
18122
|
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
|
|
17795
18123
|
}
|
|
17796
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;
|
|
17797
18173
|
} else if (data.startsWith("model_sig:")) {
|
|
17798
18174
|
const value = data.slice(10);
|
|
17799
18175
|
setModelSignature(chatId, value);
|
|
@@ -18553,6 +18929,7 @@ var init_callbacks = __esm({
|
|
|
18553
18929
|
init_guard();
|
|
18554
18930
|
init_pagination();
|
|
18555
18931
|
init_stt();
|
|
18932
|
+
init_gate();
|
|
18556
18933
|
init_helpers();
|
|
18557
18934
|
init_response();
|
|
18558
18935
|
init_shell();
|
|
@@ -18712,6 +19089,33 @@ async function handleText(msg, channel) {
|
|
|
18712
19089
|
if (hasSqPrefix) {
|
|
18713
19090
|
text = sqCleanText;
|
|
18714
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
|
+
}
|
|
18715
19119
|
{
|
|
18716
19120
|
const { getDiscussionMode: getDiscussionMode2, clearDiscussionMode: clearDiscussionMode2, setDiscussionMode: reenterDiscussion, getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
18717
19121
|
const discussInsightId = getDiscussionMode2(chatId);
|
|
@@ -18788,6 +19192,64 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
18788
19192
|
return;
|
|
18789
19193
|
}
|
|
18790
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
|
+
}
|
|
18791
19253
|
let typingActive = true;
|
|
18792
19254
|
const typingLoop = async () => {
|
|
18793
19255
|
while (typingActive) {
|
|
@@ -18968,6 +19430,7 @@ var init_router = __esm({
|
|
|
18968
19430
|
init_wizard();
|
|
18969
19431
|
init_classify2();
|
|
18970
19432
|
init_store3();
|
|
19433
|
+
init_gate();
|
|
18971
19434
|
init_helpers();
|
|
18972
19435
|
init_response();
|
|
18973
19436
|
init_shell();
|
|
@@ -19228,6 +19691,8 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19228
19691
|
if (job.jobType === "reflection") {
|
|
19229
19692
|
const { runNightlyReflection: runNightlyReflection2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
19230
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));
|
|
19231
19696
|
const timeoutMs2 = job.timeout ? job.timeout * 1e3 : void 0;
|
|
19232
19697
|
const { results } = await runNightlyReflection2({
|
|
19233
19698
|
timeoutMs: timeoutMs2,
|
|
@@ -19240,7 +19705,13 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19240
19705
|
const allInsights = results.flatMap(
|
|
19241
19706
|
(r) => r.insights.map((ins) => ({ id: ++seq, ...ins }))
|
|
19242
19707
|
);
|
|
19243
|
-
|
|
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) };
|
|
19244
19715
|
}
|
|
19245
19716
|
if (job.thinking && job.thinking !== "auto") {
|
|
19246
19717
|
setThinkingLevel(chatId, job.thinking);
|
|
@@ -19346,7 +19817,7 @@ var init_cron = __esm({
|
|
|
19346
19817
|
});
|
|
19347
19818
|
|
|
19348
19819
|
// src/agents/runners/wrap-backend.ts
|
|
19349
|
-
import { join as
|
|
19820
|
+
import { join as join20 } from "path";
|
|
19350
19821
|
function buildMcpCommands(backendId) {
|
|
19351
19822
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
19352
19823
|
return {
|
|
@@ -19440,7 +19911,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
19440
19911
|
const configPath = writeMcpConfigFile(server);
|
|
19441
19912
|
return ["--mcp-config", configPath];
|
|
19442
19913
|
},
|
|
19443
|
-
getSkillPath: () =>
|
|
19914
|
+
getSkillPath: () => join20(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
19444
19915
|
};
|
|
19445
19916
|
}
|
|
19446
19917
|
var BACKEND_CAPABILITIES;
|
|
@@ -19491,18 +19962,18 @@ var init_wrap_backend = __esm({
|
|
|
19491
19962
|
});
|
|
19492
19963
|
|
|
19493
19964
|
// src/agents/runners/config-loader.ts
|
|
19494
|
-
import { readFileSync as readFileSync10, readdirSync as
|
|
19495
|
-
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";
|
|
19496
19967
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
19497
19968
|
function resolveExecutable(config2) {
|
|
19498
|
-
if (
|
|
19969
|
+
if (existsSync19(config2.executable)) return config2.executable;
|
|
19499
19970
|
try {
|
|
19500
19971
|
return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
19501
19972
|
} catch {
|
|
19502
19973
|
}
|
|
19503
19974
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
19504
19975
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
19505
|
-
if (
|
|
19976
|
+
if (existsSync19(resolved)) return resolved;
|
|
19506
19977
|
}
|
|
19507
19978
|
return config2.executable;
|
|
19508
19979
|
}
|
|
@@ -19628,7 +20099,7 @@ function configToRunner(config2) {
|
|
|
19628
20099
|
prepareMcpInjection() {
|
|
19629
20100
|
return [];
|
|
19630
20101
|
},
|
|
19631
|
-
getSkillPath: () =>
|
|
20102
|
+
getSkillPath: () => join21(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
19632
20103
|
};
|
|
19633
20104
|
}
|
|
19634
20105
|
function loadRunnerConfig(filePath) {
|
|
@@ -19641,14 +20112,14 @@ function loadRunnerConfig(filePath) {
|
|
|
19641
20112
|
}
|
|
19642
20113
|
}
|
|
19643
20114
|
function loadAllRunnerConfigs() {
|
|
19644
|
-
if (!
|
|
19645
|
-
|
|
20115
|
+
if (!existsSync19(RUNNERS_PATH)) {
|
|
20116
|
+
mkdirSync9(RUNNERS_PATH, { recursive: true });
|
|
19646
20117
|
return [];
|
|
19647
20118
|
}
|
|
19648
|
-
const files =
|
|
20119
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19649
20120
|
const configs = [];
|
|
19650
20121
|
for (const file of files) {
|
|
19651
|
-
const config2 = loadRunnerConfig(
|
|
20122
|
+
const config2 = loadRunnerConfig(join21(RUNNERS_PATH, file));
|
|
19652
20123
|
if (config2) configs.push(config2);
|
|
19653
20124
|
}
|
|
19654
20125
|
return configs;
|
|
@@ -19669,16 +20140,16 @@ function registerConfigRunners() {
|
|
|
19669
20140
|
return count;
|
|
19670
20141
|
}
|
|
19671
20142
|
function watchRunnerConfigs(onChange) {
|
|
19672
|
-
if (!
|
|
20143
|
+
if (!existsSync19(RUNNERS_PATH)) return;
|
|
19673
20144
|
for (const prev of watchedFiles) {
|
|
19674
|
-
if (!
|
|
20145
|
+
if (!existsSync19(prev)) {
|
|
19675
20146
|
unwatchFile(prev);
|
|
19676
20147
|
watchedFiles.delete(prev);
|
|
19677
20148
|
}
|
|
19678
20149
|
}
|
|
19679
|
-
const files =
|
|
20150
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19680
20151
|
for (const file of files) {
|
|
19681
|
-
const fullPath =
|
|
20152
|
+
const fullPath = join21(RUNNERS_PATH, file);
|
|
19682
20153
|
if (watchedFiles.has(fullPath)) continue;
|
|
19683
20154
|
watchedFiles.add(fullPath);
|
|
19684
20155
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -20076,6 +20547,7 @@ var init_telegram2 = __esm({
|
|
|
20076
20547
|
{ command: "summarizer", description: "Configure session summarization model" },
|
|
20077
20548
|
// Permissions & tools
|
|
20078
20549
|
{ command: "permissions", description: "Permission mode (yolo/safe/readonly/plan)" },
|
|
20550
|
+
{ command: "mode", description: "Execution gate (approved/yolo)" },
|
|
20079
20551
|
{ command: "tools", description: "Configure which tools the agent can use" },
|
|
20080
20552
|
{ command: "verbose", description: "Tool visibility (off/normal/verbose)" },
|
|
20081
20553
|
{ command: "cwd", description: "Set or show working directory" },
|
|
@@ -20512,19 +20984,19 @@ var init_telegram2 = __esm({
|
|
|
20512
20984
|
});
|
|
20513
20985
|
|
|
20514
20986
|
// src/skills/bootstrap.ts
|
|
20515
|
-
import { existsSync as
|
|
20987
|
+
import { existsSync as existsSync20 } from "fs";
|
|
20516
20988
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
20517
|
-
import { join as
|
|
20989
|
+
import { join as join22, dirname as dirname4 } from "path";
|
|
20518
20990
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20519
20991
|
async function copyAgentManifestSkills() {
|
|
20520
|
-
if (!
|
|
20992
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
20521
20993
|
try {
|
|
20522
20994
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
20523
20995
|
for (const entry of entries) {
|
|
20524
20996
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
20525
|
-
const src =
|
|
20526
|
-
const dest =
|
|
20527
|
-
if (
|
|
20997
|
+
const src = join22(PKG_SKILLS, entry.name);
|
|
20998
|
+
const dest = join22(SKILLS_PATH, entry.name);
|
|
20999
|
+
if (existsSync20(dest)) continue;
|
|
20528
21000
|
await copyFile(src, dest);
|
|
20529
21001
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
20530
21002
|
}
|
|
@@ -20534,8 +21006,8 @@ async function copyAgentManifestSkills() {
|
|
|
20534
21006
|
}
|
|
20535
21007
|
async function bootstrapSkills() {
|
|
20536
21008
|
await copyAgentManifestSkills();
|
|
20537
|
-
const usmDir =
|
|
20538
|
-
if (
|
|
21009
|
+
const usmDir = join22(SKILLS_PATH, USM_DIR_NAME);
|
|
21010
|
+
if (existsSync20(usmDir)) return;
|
|
20539
21011
|
try {
|
|
20540
21012
|
const entries = await readdir6(SKILLS_PATH);
|
|
20541
21013
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -20557,8 +21029,8 @@ async function bootstrapSkills() {
|
|
|
20557
21029
|
}
|
|
20558
21030
|
}
|
|
20559
21031
|
async function patchUsmForCcClaw(usmDir) {
|
|
20560
|
-
const skillPath =
|
|
20561
|
-
if (!
|
|
21032
|
+
const skillPath = join22(usmDir, "SKILL.md");
|
|
21033
|
+
if (!existsSync20(skillPath)) return;
|
|
20562
21034
|
try {
|
|
20563
21035
|
let content = await readFile8(skillPath, "utf-8");
|
|
20564
21036
|
let patched = false;
|
|
@@ -20603,8 +21075,8 @@ var init_bootstrap = __esm({
|
|
|
20603
21075
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
20604
21076
|
USM_DIR_NAME = "universal-skills-manager";
|
|
20605
21077
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
20606
|
-
PKG_ROOT =
|
|
20607
|
-
PKG_SKILLS =
|
|
21078
|
+
PKG_ROOT = join22(dirname4(fileURLToPath2(import.meta.url)), "..", "..");
|
|
21079
|
+
PKG_SKILLS = join22(PKG_ROOT, "skills");
|
|
20608
21080
|
}
|
|
20609
21081
|
});
|
|
20610
21082
|
|
|
@@ -20826,13 +21298,13 @@ __export(ai_skill_exports, {
|
|
|
20826
21298
|
generateAiSkill: () => generateAiSkill,
|
|
20827
21299
|
installAiSkill: () => installAiSkill
|
|
20828
21300
|
});
|
|
20829
|
-
import { existsSync as
|
|
20830
|
-
import { join as
|
|
21301
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
|
|
21302
|
+
import { join as join23 } from "path";
|
|
20831
21303
|
import { homedir as homedir7 } from "os";
|
|
20832
21304
|
function generateAiSkill() {
|
|
20833
21305
|
const version = VERSION;
|
|
20834
21306
|
let systemState = "";
|
|
20835
|
-
if (
|
|
21307
|
+
if (existsSync21(DB_PATH)) {
|
|
20836
21308
|
try {
|
|
20837
21309
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
20838
21310
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -21236,10 +21708,10 @@ function installAiSkill() {
|
|
|
21236
21708
|
const failed = [];
|
|
21237
21709
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
21238
21710
|
for (const dir of dirs) {
|
|
21239
|
-
const skillDir =
|
|
21240
|
-
const skillPath =
|
|
21711
|
+
const skillDir = join23(dir, "cc-claw-cli");
|
|
21712
|
+
const skillPath = join23(skillDir, "SKILL.md");
|
|
21241
21713
|
try {
|
|
21242
|
-
|
|
21714
|
+
mkdirSync10(skillDir, { recursive: true });
|
|
21243
21715
|
writeFileSync7(skillPath, skill, "utf-8");
|
|
21244
21716
|
installed.push(skillPath);
|
|
21245
21717
|
} catch {
|
|
@@ -21256,11 +21728,11 @@ var init_ai_skill = __esm({
|
|
|
21256
21728
|
init_paths();
|
|
21257
21729
|
init_version();
|
|
21258
21730
|
BACKEND_SKILL_DIRS2 = {
|
|
21259
|
-
"cc-claw": [
|
|
21260
|
-
claude: [
|
|
21261
|
-
gemini: [
|
|
21262
|
-
codex: [
|
|
21263
|
-
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")]
|
|
21264
21736
|
};
|
|
21265
21737
|
}
|
|
21266
21738
|
});
|
|
@@ -21270,23 +21742,23 @@ var index_exports = {};
|
|
|
21270
21742
|
__export(index_exports, {
|
|
21271
21743
|
main: () => main
|
|
21272
21744
|
});
|
|
21273
|
-
import { mkdirSync as
|
|
21274
|
-
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";
|
|
21275
21747
|
import dotenv from "dotenv";
|
|
21276
21748
|
function migrateLayout() {
|
|
21277
21749
|
const moves = [
|
|
21278
|
-
[
|
|
21279
|
-
[
|
|
21280
|
-
[
|
|
21281
|
-
[
|
|
21282
|
-
[
|
|
21283
|
-
[
|
|
21284
|
-
[
|
|
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")]
|
|
21285
21757
|
];
|
|
21286
21758
|
for (const [from, to] of moves) {
|
|
21287
|
-
if (
|
|
21759
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
21288
21760
|
try {
|
|
21289
|
-
|
|
21761
|
+
renameSync2(from, to);
|
|
21290
21762
|
} catch {
|
|
21291
21763
|
}
|
|
21292
21764
|
}
|
|
@@ -21295,11 +21767,11 @@ function migrateLayout() {
|
|
|
21295
21767
|
function rotateLogs() {
|
|
21296
21768
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
21297
21769
|
try {
|
|
21298
|
-
const { size } =
|
|
21770
|
+
const { size } = statSync6(file);
|
|
21299
21771
|
if (size > LOG_MAX_BYTES) {
|
|
21300
21772
|
const archivePath = `${file}.1`;
|
|
21301
21773
|
try {
|
|
21302
|
-
|
|
21774
|
+
renameSync2(file, archivePath);
|
|
21303
21775
|
} catch {
|
|
21304
21776
|
}
|
|
21305
21777
|
log(`[cc-claw] Rotated ${file} (was ${(size / 1024 / 1024).toFixed(1)}MB)`);
|
|
@@ -21347,6 +21819,12 @@ async function main() {
|
|
|
21347
21819
|
}
|
|
21348
21820
|
setBootTime();
|
|
21349
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
|
+
}
|
|
21350
21828
|
if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
21351
21829
|
channelRegistry.register(new TelegramChannel());
|
|
21352
21830
|
}
|
|
@@ -21423,11 +21901,11 @@ async function main() {
|
|
|
21423
21901
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
21424
21902
|
try {
|
|
21425
21903
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
21426
|
-
const { writeFileSync: writeFileSync12, mkdirSync:
|
|
21427
|
-
const { join:
|
|
21428
|
-
const skillDir =
|
|
21429
|
-
|
|
21430
|
-
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");
|
|
21431
21909
|
log("[cc-claw] AI skill updated");
|
|
21432
21910
|
} catch {
|
|
21433
21911
|
}
|
|
@@ -21500,10 +21978,10 @@ var init_index = __esm({
|
|
|
21500
21978
|
init_health3();
|
|
21501
21979
|
init_image_gen();
|
|
21502
21980
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
21503
|
-
if (!
|
|
21981
|
+
if (!existsSync22(dir)) mkdirSync11(dir, { recursive: true });
|
|
21504
21982
|
}
|
|
21505
21983
|
migrateLayout();
|
|
21506
|
-
if (
|
|
21984
|
+
if (existsSync22(ENV_PATH)) {
|
|
21507
21985
|
dotenv.config({ path: ENV_PATH });
|
|
21508
21986
|
} else {
|
|
21509
21987
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -21524,12 +22002,12 @@ __export(api_client_exports, {
|
|
|
21524
22002
|
apiPost: () => apiPost,
|
|
21525
22003
|
isDaemonRunning: () => isDaemonRunning
|
|
21526
22004
|
});
|
|
21527
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
22005
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
21528
22006
|
import { request as httpRequest, Agent } from "http";
|
|
21529
22007
|
function getToken() {
|
|
21530
22008
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21531
22009
|
try {
|
|
21532
|
-
if (
|
|
22010
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
21533
22011
|
} catch {
|
|
21534
22012
|
}
|
|
21535
22013
|
return null;
|
|
@@ -21628,10 +22106,10 @@ __export(service_exports, {
|
|
|
21628
22106
|
serviceStatus: () => serviceStatus,
|
|
21629
22107
|
uninstallService: () => uninstallService
|
|
21630
22108
|
});
|
|
21631
|
-
import { existsSync as
|
|
22109
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
|
|
21632
22110
|
import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
|
|
21633
22111
|
import { homedir as homedir8, platform } from "os";
|
|
21634
|
-
import { join as
|
|
22112
|
+
import { join as join25, dirname as dirname5 } from "path";
|
|
21635
22113
|
function xmlEscape(s) {
|
|
21636
22114
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
21637
22115
|
}
|
|
@@ -21640,23 +22118,23 @@ function resolveExecutable2(name) {
|
|
|
21640
22118
|
return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
|
|
21641
22119
|
} catch {
|
|
21642
22120
|
const fallback = process.argv[1];
|
|
21643
|
-
if (fallback &&
|
|
22121
|
+
if (fallback && existsSync24(fallback)) return fallback;
|
|
21644
22122
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
21645
22123
|
}
|
|
21646
22124
|
}
|
|
21647
22125
|
function getPathDirs() {
|
|
21648
|
-
const nodeBin =
|
|
22126
|
+
const nodeBin = dirname5(process.execPath);
|
|
21649
22127
|
const home = homedir8();
|
|
21650
22128
|
const dirs = /* @__PURE__ */ new Set([
|
|
21651
22129
|
nodeBin,
|
|
21652
|
-
|
|
22130
|
+
join25(home, ".local", "bin"),
|
|
21653
22131
|
"/usr/local/bin",
|
|
21654
22132
|
"/usr/bin",
|
|
21655
22133
|
"/bin"
|
|
21656
22134
|
]);
|
|
21657
22135
|
try {
|
|
21658
22136
|
const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
21659
|
-
if (prefix) dirs.add(
|
|
22137
|
+
if (prefix) dirs.add(join25(prefix, "bin"));
|
|
21660
22138
|
} catch {
|
|
21661
22139
|
}
|
|
21662
22140
|
return [...dirs].join(":");
|
|
@@ -21714,10 +22192,10 @@ function generatePlist() {
|
|
|
21714
22192
|
</plist>`;
|
|
21715
22193
|
}
|
|
21716
22194
|
function installMacOS() {
|
|
21717
|
-
const agentsDir =
|
|
21718
|
-
if (!
|
|
21719
|
-
if (!
|
|
21720
|
-
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)) {
|
|
21721
22199
|
try {
|
|
21722
22200
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
21723
22201
|
} catch {
|
|
@@ -21729,7 +22207,7 @@ function installMacOS() {
|
|
|
21729
22207
|
console.log(" Service loaded and starting.");
|
|
21730
22208
|
}
|
|
21731
22209
|
function uninstallMacOS() {
|
|
21732
|
-
if (!
|
|
22210
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
21733
22211
|
console.log(" No service found to uninstall.");
|
|
21734
22212
|
return;
|
|
21735
22213
|
}
|
|
@@ -21804,8 +22282,8 @@ WantedBy=default.target
|
|
|
21804
22282
|
`;
|
|
21805
22283
|
}
|
|
21806
22284
|
function installLinux() {
|
|
21807
|
-
if (!
|
|
21808
|
-
if (!
|
|
22285
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync12(SYSTEMD_DIR, { recursive: true });
|
|
22286
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
|
|
21809
22287
|
writeFileSync8(UNIT_PATH, generateUnit());
|
|
21810
22288
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
21811
22289
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -21814,7 +22292,7 @@ function installLinux() {
|
|
|
21814
22292
|
console.log(" Service enabled and started.");
|
|
21815
22293
|
}
|
|
21816
22294
|
function uninstallLinux() {
|
|
21817
|
-
if (!
|
|
22295
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
21818
22296
|
console.log(" No service found to uninstall.");
|
|
21819
22297
|
return;
|
|
21820
22298
|
}
|
|
@@ -21839,7 +22317,7 @@ function statusLinux() {
|
|
|
21839
22317
|
}
|
|
21840
22318
|
}
|
|
21841
22319
|
function installService() {
|
|
21842
|
-
if (!
|
|
22320
|
+
if (!existsSync24(join25(CC_CLAW_HOME, ".env"))) {
|
|
21843
22321
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
21844
22322
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
21845
22323
|
process.exitCode = 1;
|
|
@@ -21868,9 +22346,9 @@ var init_service = __esm({
|
|
|
21868
22346
|
"use strict";
|
|
21869
22347
|
init_paths();
|
|
21870
22348
|
PLIST_LABEL = "com.cc-claw";
|
|
21871
|
-
PLIST_PATH =
|
|
21872
|
-
SYSTEMD_DIR =
|
|
21873
|
-
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");
|
|
21874
22352
|
}
|
|
21875
22353
|
});
|
|
21876
22354
|
|
|
@@ -22067,7 +22545,7 @@ var status_exports = {};
|
|
|
22067
22545
|
__export(status_exports, {
|
|
22068
22546
|
statusCommand: () => statusCommand
|
|
22069
22547
|
});
|
|
22070
|
-
import { existsSync as
|
|
22548
|
+
import { existsSync as existsSync25, statSync as statSync7 } from "fs";
|
|
22071
22549
|
async function statusCommand(globalOpts, localOpts) {
|
|
22072
22550
|
try {
|
|
22073
22551
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22107,7 +22585,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
22107
22585
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
22108
22586
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
22109
22587
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
22110
|
-
const dbStat =
|
|
22588
|
+
const dbStat = existsSync25(DB_PATH) ? statSync7(DB_PATH) : null;
|
|
22111
22589
|
let daemonRunning = false;
|
|
22112
22590
|
let daemonInfo = {};
|
|
22113
22591
|
try {
|
|
@@ -22196,12 +22674,12 @@ var doctor_exports = {};
|
|
|
22196
22674
|
__export(doctor_exports, {
|
|
22197
22675
|
doctorCommand: () => doctorCommand
|
|
22198
22676
|
});
|
|
22199
|
-
import { existsSync as
|
|
22677
|
+
import { existsSync as existsSync26, statSync as statSync8, accessSync, constants } from "fs";
|
|
22200
22678
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22201
22679
|
async function doctorCommand(globalOpts, localOpts) {
|
|
22202
22680
|
const checks = [];
|
|
22203
|
-
if (
|
|
22204
|
-
const size =
|
|
22681
|
+
if (existsSync26(DB_PATH)) {
|
|
22682
|
+
const size = statSync8(DB_PATH).size;
|
|
22205
22683
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
22206
22684
|
try {
|
|
22207
22685
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22230,7 +22708,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22230
22708
|
} else {
|
|
22231
22709
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
22232
22710
|
}
|
|
22233
|
-
if (
|
|
22711
|
+
if (existsSync26(ENV_PATH)) {
|
|
22234
22712
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
22235
22713
|
} else {
|
|
22236
22714
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -22285,7 +22763,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22285
22763
|
} catch {
|
|
22286
22764
|
}
|
|
22287
22765
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
22288
|
-
if (
|
|
22766
|
+
if (existsSync26(tokenPath)) {
|
|
22289
22767
|
try {
|
|
22290
22768
|
accessSync(tokenPath, constants.R_OK);
|
|
22291
22769
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -22310,7 +22788,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22310
22788
|
}
|
|
22311
22789
|
} catch {
|
|
22312
22790
|
}
|
|
22313
|
-
if (
|
|
22791
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
22314
22792
|
try {
|
|
22315
22793
|
const { readFileSync: readFileSync22 } = await import("fs");
|
|
22316
22794
|
const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
|
|
@@ -22436,10 +22914,10 @@ var logs_exports = {};
|
|
|
22436
22914
|
__export(logs_exports, {
|
|
22437
22915
|
logsCommand: () => logsCommand
|
|
22438
22916
|
});
|
|
22439
|
-
import { existsSync as
|
|
22917
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
22440
22918
|
async function logsCommand(opts) {
|
|
22441
22919
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
22442
|
-
if (!
|
|
22920
|
+
if (!existsSync27(logFile)) {
|
|
22443
22921
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
22444
22922
|
process.exit(1);
|
|
22445
22923
|
}
|
|
@@ -22491,11 +22969,11 @@ __export(gemini_exports, {
|
|
|
22491
22969
|
geminiReorder: () => geminiReorder,
|
|
22492
22970
|
geminiRotation: () => geminiRotation
|
|
22493
22971
|
});
|
|
22494
|
-
import { existsSync as
|
|
22495
|
-
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";
|
|
22496
22974
|
import { createInterface as createInterface5 } from "readline";
|
|
22497
22975
|
function requireDb() {
|
|
22498
|
-
if (!
|
|
22976
|
+
if (!existsSync28(DB_PATH)) {
|
|
22499
22977
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22500
22978
|
process.exit(1);
|
|
22501
22979
|
}
|
|
@@ -22520,8 +22998,8 @@ async function resolveSlotId(idOrLabel) {
|
|
|
22520
22998
|
function resolveOAuthEmail(configHome) {
|
|
22521
22999
|
if (!configHome) return null;
|
|
22522
23000
|
try {
|
|
22523
|
-
const accountsPath =
|
|
22524
|
-
if (!
|
|
23001
|
+
const accountsPath = join26(configHome, ".gemini", "google_accounts.json");
|
|
23002
|
+
if (!existsSync28(accountsPath)) return null;
|
|
22525
23003
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
22526
23004
|
return accounts.active || null;
|
|
22527
23005
|
} catch {
|
|
@@ -22604,14 +23082,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
22604
23082
|
}
|
|
22605
23083
|
async function geminiAddAccount(globalOpts, opts) {
|
|
22606
23084
|
await requireWriteDb();
|
|
22607
|
-
const slotsDir =
|
|
22608
|
-
if (!
|
|
23085
|
+
const slotsDir = join26(CC_CLAW_HOME, "gemini-slots");
|
|
23086
|
+
if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
|
|
22609
23087
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22610
23088
|
const tempId = Date.now();
|
|
22611
|
-
const slotDir =
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
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({
|
|
22615
23093
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
22616
23094
|
}, null, 2));
|
|
22617
23095
|
console.log("");
|
|
@@ -22628,8 +23106,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22628
23106
|
});
|
|
22629
23107
|
} catch {
|
|
22630
23108
|
}
|
|
22631
|
-
const oauthPath =
|
|
22632
|
-
if (!
|
|
23109
|
+
const oauthPath = join26(slotDir, ".gemini", "oauth_creds.json");
|
|
23110
|
+
if (!existsSync28(oauthPath)) {
|
|
22633
23111
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
22634
23112
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
22635
23113
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -22637,7 +23115,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22637
23115
|
}
|
|
22638
23116
|
let accountEmail = "unknown";
|
|
22639
23117
|
try {
|
|
22640
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
23118
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join26(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
22641
23119
|
accountEmail = accounts.active || accountEmail;
|
|
22642
23120
|
} catch {
|
|
22643
23121
|
}
|
|
@@ -22648,6 +23126,13 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22648
23126
|
configHome: slotDir,
|
|
22649
23127
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22650
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
|
+
}
|
|
22651
23136
|
output(
|
|
22652
23137
|
{ id, type: "oauth", label: opts.label || accountEmail, configHome: slotDir },
|
|
22653
23138
|
() => success(`
|
|
@@ -22749,11 +23234,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
22749
23234
|
makeReorder: () => makeReorder,
|
|
22750
23235
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
22751
23236
|
});
|
|
22752
|
-
import { existsSync as
|
|
22753
|
-
import { join as
|
|
23237
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync14, readFileSync as readFileSync18 } from "fs";
|
|
23238
|
+
import { join as join27 } from "path";
|
|
22754
23239
|
import { createInterface as createInterface6 } from "readline";
|
|
22755
23240
|
function requireDb2() {
|
|
22756
|
-
if (!
|
|
23241
|
+
if (!existsSync29(DB_PATH)) {
|
|
22757
23242
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22758
23243
|
process.exit(1);
|
|
22759
23244
|
}
|
|
@@ -22842,11 +23327,11 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22842
23327
|
process.exit(1);
|
|
22843
23328
|
}
|
|
22844
23329
|
await requireWriteDb2();
|
|
22845
|
-
const slotsDir =
|
|
22846
|
-
if (!
|
|
23330
|
+
const slotsDir = join27(CC_CLAW_HOME, config2.slotsSubdir);
|
|
23331
|
+
if (!existsSync29(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
22847
23332
|
const tempId = Date.now();
|
|
22848
|
-
const slotDir =
|
|
22849
|
-
|
|
23333
|
+
const slotDir = join27(slotsDir, `slot-${tempId}`);
|
|
23334
|
+
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
22850
23335
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
22851
23336
|
console.log("");
|
|
22852
23337
|
console.log(` Opening ${displayName} CLI for sign-in...`);
|
|
@@ -22884,6 +23369,13 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22884
23369
|
configHome: slotDir,
|
|
22885
23370
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22886
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
|
+
}
|
|
22887
23379
|
output(
|
|
22888
23380
|
{ id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
|
|
22889
23381
|
() => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
|
|
@@ -23007,12 +23499,12 @@ var init_backend_cmd_factory = __esm({
|
|
|
23007
23499
|
envValue: (slotDir) => slotDir,
|
|
23008
23500
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
23009
23501
|
preSetup: (slotDir) => {
|
|
23010
|
-
|
|
23502
|
+
mkdirSync14(join27(slotDir, ".claude"), { recursive: true });
|
|
23011
23503
|
},
|
|
23012
23504
|
verifyCredentials: (slotDir) => {
|
|
23013
|
-
const claudeJson =
|
|
23014
|
-
const claudeJsonNested =
|
|
23015
|
-
if (
|
|
23505
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23506
|
+
const claudeJsonNested = join27(slotDir, ".claude", ".claude.json");
|
|
23507
|
+
if (existsSync29(claudeJson)) {
|
|
23016
23508
|
try {
|
|
23017
23509
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
23018
23510
|
return Boolean(data.oauthAccount);
|
|
@@ -23020,7 +23512,7 @@ var init_backend_cmd_factory = __esm({
|
|
|
23020
23512
|
return false;
|
|
23021
23513
|
}
|
|
23022
23514
|
}
|
|
23023
|
-
if (
|
|
23515
|
+
if (existsSync29(claudeJsonNested)) {
|
|
23024
23516
|
try {
|
|
23025
23517
|
const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
|
|
23026
23518
|
return Boolean(data.oauthAccount);
|
|
@@ -23043,8 +23535,8 @@ var init_backend_cmd_factory = __esm({
|
|
|
23043
23535
|
} catch {
|
|
23044
23536
|
}
|
|
23045
23537
|
try {
|
|
23046
|
-
const claudeJson =
|
|
23047
|
-
if (
|
|
23538
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23539
|
+
if (existsSync29(claudeJson)) {
|
|
23048
23540
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
23049
23541
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
23050
23542
|
}
|
|
@@ -23060,11 +23552,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
23060
23552
|
envValue: (slotDir) => slotDir,
|
|
23061
23553
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
23062
23554
|
verifyCredentials: (slotDir) => {
|
|
23063
|
-
return
|
|
23555
|
+
return existsSync29(join27(slotDir, "auth.json"));
|
|
23064
23556
|
},
|
|
23065
23557
|
extractLabel: (slotDir) => {
|
|
23066
23558
|
try {
|
|
23067
|
-
const authData = JSON.parse(readFileSync18(
|
|
23559
|
+
const authData = JSON.parse(readFileSync18(join27(slotDir, "auth.json"), "utf-8"));
|
|
23068
23560
|
if (authData.email) return authData.email;
|
|
23069
23561
|
if (authData.account_name) return authData.account_name;
|
|
23070
23562
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -23084,12 +23576,12 @@ __export(backend_exports, {
|
|
|
23084
23576
|
backendList: () => backendList,
|
|
23085
23577
|
backendSet: () => backendSet
|
|
23086
23578
|
});
|
|
23087
|
-
import { existsSync as
|
|
23579
|
+
import { existsSync as existsSync30 } from "fs";
|
|
23088
23580
|
async function backendList(globalOpts) {
|
|
23089
23581
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23090
23582
|
const chatId = resolveChatId(globalOpts);
|
|
23091
23583
|
let activeBackend = null;
|
|
23092
|
-
if (
|
|
23584
|
+
if (existsSync30(DB_PATH)) {
|
|
23093
23585
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23094
23586
|
const readDb = openDatabaseReadOnly2();
|
|
23095
23587
|
try {
|
|
@@ -23120,7 +23612,7 @@ async function backendList(globalOpts) {
|
|
|
23120
23612
|
}
|
|
23121
23613
|
async function backendGet(globalOpts) {
|
|
23122
23614
|
const chatId = resolveChatId(globalOpts);
|
|
23123
|
-
if (!
|
|
23615
|
+
if (!existsSync30(DB_PATH)) {
|
|
23124
23616
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23125
23617
|
process.exit(1);
|
|
23126
23618
|
}
|
|
@@ -23164,13 +23656,13 @@ __export(model_exports, {
|
|
|
23164
23656
|
modelList: () => modelList,
|
|
23165
23657
|
modelSet: () => modelSet
|
|
23166
23658
|
});
|
|
23167
|
-
import { existsSync as
|
|
23659
|
+
import { existsSync as existsSync31 } from "fs";
|
|
23168
23660
|
async function modelList(globalOpts) {
|
|
23169
23661
|
const chatId = resolveChatId(globalOpts);
|
|
23170
23662
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23171
23663
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23172
23664
|
let backendId = "claude";
|
|
23173
|
-
if (
|
|
23665
|
+
if (existsSync31(DB_PATH)) {
|
|
23174
23666
|
const readDb = openDatabaseReadOnly2();
|
|
23175
23667
|
try {
|
|
23176
23668
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -23203,7 +23695,7 @@ async function modelList(globalOpts) {
|
|
|
23203
23695
|
}
|
|
23204
23696
|
async function modelGet(globalOpts) {
|
|
23205
23697
|
const chatId = resolveChatId(globalOpts);
|
|
23206
|
-
if (!
|
|
23698
|
+
if (!existsSync31(DB_PATH)) {
|
|
23207
23699
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23208
23700
|
process.exit(1);
|
|
23209
23701
|
}
|
|
@@ -23247,9 +23739,9 @@ __export(memory_exports2, {
|
|
|
23247
23739
|
memoryList: () => memoryList,
|
|
23248
23740
|
memorySearch: () => memorySearch
|
|
23249
23741
|
});
|
|
23250
|
-
import { existsSync as
|
|
23742
|
+
import { existsSync as existsSync32 } from "fs";
|
|
23251
23743
|
async function memoryList(globalOpts) {
|
|
23252
|
-
if (!
|
|
23744
|
+
if (!existsSync32(DB_PATH)) {
|
|
23253
23745
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23254
23746
|
process.exit(1);
|
|
23255
23747
|
}
|
|
@@ -23273,7 +23765,7 @@ async function memoryList(globalOpts) {
|
|
|
23273
23765
|
});
|
|
23274
23766
|
}
|
|
23275
23767
|
async function memorySearch(globalOpts, query) {
|
|
23276
|
-
if (!
|
|
23768
|
+
if (!existsSync32(DB_PATH)) {
|
|
23277
23769
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23278
23770
|
process.exit(1);
|
|
23279
23771
|
}
|
|
@@ -23295,7 +23787,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
23295
23787
|
});
|
|
23296
23788
|
}
|
|
23297
23789
|
async function memoryHistory(globalOpts, opts) {
|
|
23298
|
-
if (!
|
|
23790
|
+
if (!existsSync32(DB_PATH)) {
|
|
23299
23791
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23300
23792
|
process.exit(1);
|
|
23301
23793
|
}
|
|
@@ -23343,7 +23835,7 @@ __export(cron_exports2, {
|
|
|
23343
23835
|
cronList: () => cronList,
|
|
23344
23836
|
cronRuns: () => cronRuns
|
|
23345
23837
|
});
|
|
23346
|
-
import { existsSync as
|
|
23838
|
+
import { existsSync as existsSync33 } from "fs";
|
|
23347
23839
|
function parseFallbacks(raw) {
|
|
23348
23840
|
return raw.slice(0, 3).map((f) => {
|
|
23349
23841
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -23364,7 +23856,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
23364
23856
|
return val;
|
|
23365
23857
|
}
|
|
23366
23858
|
async function cronList(globalOpts) {
|
|
23367
|
-
if (!
|
|
23859
|
+
if (!existsSync33(DB_PATH)) {
|
|
23368
23860
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23369
23861
|
process.exit(1);
|
|
23370
23862
|
}
|
|
@@ -23402,7 +23894,7 @@ async function cronList(globalOpts) {
|
|
|
23402
23894
|
});
|
|
23403
23895
|
}
|
|
23404
23896
|
async function cronHealth(globalOpts) {
|
|
23405
|
-
if (!
|
|
23897
|
+
if (!existsSync33(DB_PATH)) {
|
|
23406
23898
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23407
23899
|
process.exit(1);
|
|
23408
23900
|
}
|
|
@@ -23561,7 +24053,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
23561
24053
|
}
|
|
23562
24054
|
}
|
|
23563
24055
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
23564
|
-
if (!
|
|
24056
|
+
if (!existsSync33(DB_PATH)) {
|
|
23565
24057
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23566
24058
|
process.exit(1);
|
|
23567
24059
|
}
|
|
@@ -23608,9 +24100,9 @@ __export(agents_exports, {
|
|
|
23608
24100
|
runnersList: () => runnersList,
|
|
23609
24101
|
tasksList: () => tasksList
|
|
23610
24102
|
});
|
|
23611
|
-
import { existsSync as
|
|
24103
|
+
import { existsSync as existsSync34 } from "fs";
|
|
23612
24104
|
async function agentsList(globalOpts) {
|
|
23613
|
-
if (!
|
|
24105
|
+
if (!existsSync34(DB_PATH)) {
|
|
23614
24106
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23615
24107
|
process.exit(1);
|
|
23616
24108
|
}
|
|
@@ -23641,7 +24133,7 @@ async function agentsList(globalOpts) {
|
|
|
23641
24133
|
});
|
|
23642
24134
|
}
|
|
23643
24135
|
async function tasksList(globalOpts) {
|
|
23644
|
-
if (!
|
|
24136
|
+
if (!existsSync34(DB_PATH)) {
|
|
23645
24137
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23646
24138
|
process.exit(1);
|
|
23647
24139
|
}
|
|
@@ -23769,18 +24261,18 @@ __export(db_exports, {
|
|
|
23769
24261
|
dbPath: () => dbPath,
|
|
23770
24262
|
dbStats: () => dbStats
|
|
23771
24263
|
});
|
|
23772
|
-
import { existsSync as
|
|
23773
|
-
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";
|
|
23774
24266
|
async function dbStats(globalOpts) {
|
|
23775
|
-
if (!
|
|
24267
|
+
if (!existsSync35(DB_PATH)) {
|
|
23776
24268
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23777
24269
|
process.exit(1);
|
|
23778
24270
|
}
|
|
23779
24271
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23780
24272
|
const readDb = openDatabaseReadOnly2();
|
|
23781
|
-
const mainSize =
|
|
24273
|
+
const mainSize = statSync9(DB_PATH).size;
|
|
23782
24274
|
const walPath = DB_PATH + "-wal";
|
|
23783
|
-
const walSize =
|
|
24275
|
+
const walSize = existsSync35(walPath) ? statSync9(walPath).size : 0;
|
|
23784
24276
|
const tableNames = readDb.prepare(
|
|
23785
24277
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
23786
24278
|
).all();
|
|
@@ -23814,17 +24306,17 @@ async function dbPath(globalOpts) {
|
|
|
23814
24306
|
output({ path: DB_PATH }, (d) => d.path);
|
|
23815
24307
|
}
|
|
23816
24308
|
async function dbBackup(globalOpts, destPath) {
|
|
23817
|
-
if (!
|
|
24309
|
+
if (!existsSync35(DB_PATH)) {
|
|
23818
24310
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23819
24311
|
process.exit(1);
|
|
23820
24312
|
}
|
|
23821
24313
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
23822
24314
|
try {
|
|
23823
|
-
|
|
23824
|
-
|
|
24315
|
+
mkdirSync15(dirname6(dest), { recursive: true });
|
|
24316
|
+
copyFileSync3(DB_PATH, dest);
|
|
23825
24317
|
const walPath = DB_PATH + "-wal";
|
|
23826
|
-
if (
|
|
23827
|
-
output({ path: dest, sizeBytes:
|
|
24318
|
+
if (existsSync35(walPath)) copyFileSync3(walPath, dest + "-wal");
|
|
24319
|
+
output({ path: dest, sizeBytes: statSync9(dest).size }, (d) => {
|
|
23828
24320
|
const b = d;
|
|
23829
24321
|
return `
|
|
23830
24322
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -23852,9 +24344,9 @@ __export(usage_exports, {
|
|
|
23852
24344
|
usageCost: () => usageCost,
|
|
23853
24345
|
usageTokens: () => usageTokens
|
|
23854
24346
|
});
|
|
23855
|
-
import { existsSync as
|
|
24347
|
+
import { existsSync as existsSync36 } from "fs";
|
|
23856
24348
|
function ensureDb() {
|
|
23857
|
-
if (!
|
|
24349
|
+
if (!existsSync36(DB_PATH)) {
|
|
23858
24350
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23859
24351
|
process.exit(1);
|
|
23860
24352
|
}
|
|
@@ -24044,9 +24536,9 @@ __export(config_exports2, {
|
|
|
24044
24536
|
configList: () => configList,
|
|
24045
24537
|
configSet: () => configSet
|
|
24046
24538
|
});
|
|
24047
|
-
import { existsSync as
|
|
24539
|
+
import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
|
|
24048
24540
|
async function configList(globalOpts) {
|
|
24049
|
-
if (!
|
|
24541
|
+
if (!existsSync37(DB_PATH)) {
|
|
24050
24542
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24051
24543
|
process.exit(1);
|
|
24052
24544
|
}
|
|
@@ -24080,7 +24572,7 @@ async function configGet(globalOpts, key) {
|
|
|
24080
24572
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
24081
24573
|
process.exit(1);
|
|
24082
24574
|
}
|
|
24083
|
-
if (!
|
|
24575
|
+
if (!existsSync37(DB_PATH)) {
|
|
24084
24576
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24085
24577
|
process.exit(1);
|
|
24086
24578
|
}
|
|
@@ -24126,7 +24618,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
24126
24618
|
}
|
|
24127
24619
|
}
|
|
24128
24620
|
async function configEnv(_globalOpts) {
|
|
24129
|
-
if (!
|
|
24621
|
+
if (!existsSync37(ENV_PATH)) {
|
|
24130
24622
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
24131
24623
|
process.exit(1);
|
|
24132
24624
|
}
|
|
@@ -24180,9 +24672,9 @@ __export(session_exports, {
|
|
|
24180
24672
|
sessionGet: () => sessionGet,
|
|
24181
24673
|
sessionNew: () => sessionNew
|
|
24182
24674
|
});
|
|
24183
|
-
import { existsSync as
|
|
24675
|
+
import { existsSync as existsSync38 } from "fs";
|
|
24184
24676
|
async function sessionGet(globalOpts) {
|
|
24185
|
-
if (!
|
|
24677
|
+
if (!existsSync38(DB_PATH)) {
|
|
24186
24678
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24187
24679
|
process.exit(1);
|
|
24188
24680
|
}
|
|
@@ -24243,9 +24735,9 @@ __export(permissions_exports, {
|
|
|
24243
24735
|
verboseGet: () => verboseGet,
|
|
24244
24736
|
verboseSet: () => verboseSet
|
|
24245
24737
|
});
|
|
24246
|
-
import { existsSync as
|
|
24738
|
+
import { existsSync as existsSync39 } from "fs";
|
|
24247
24739
|
function ensureDb2() {
|
|
24248
|
-
if (!
|
|
24740
|
+
if (!existsSync39(DB_PATH)) {
|
|
24249
24741
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24250
24742
|
process.exit(1);
|
|
24251
24743
|
}
|
|
@@ -24392,9 +24884,9 @@ __export(cwd_exports, {
|
|
|
24392
24884
|
cwdGet: () => cwdGet,
|
|
24393
24885
|
cwdSet: () => cwdSet
|
|
24394
24886
|
});
|
|
24395
|
-
import { existsSync as
|
|
24887
|
+
import { existsSync as existsSync40 } from "fs";
|
|
24396
24888
|
async function cwdGet(globalOpts) {
|
|
24397
|
-
if (!
|
|
24889
|
+
if (!existsSync40(DB_PATH)) {
|
|
24398
24890
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24399
24891
|
process.exit(1);
|
|
24400
24892
|
}
|
|
@@ -24456,9 +24948,9 @@ __export(voice_exports, {
|
|
|
24456
24948
|
voiceGet: () => voiceGet,
|
|
24457
24949
|
voiceSet: () => voiceSet
|
|
24458
24950
|
});
|
|
24459
|
-
import { existsSync as
|
|
24951
|
+
import { existsSync as existsSync41 } from "fs";
|
|
24460
24952
|
async function voiceGet(globalOpts) {
|
|
24461
|
-
if (!
|
|
24953
|
+
if (!existsSync41(DB_PATH)) {
|
|
24462
24954
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24463
24955
|
process.exit(1);
|
|
24464
24956
|
}
|
|
@@ -24507,9 +24999,9 @@ __export(heartbeat_exports, {
|
|
|
24507
24999
|
heartbeatGet: () => heartbeatGet,
|
|
24508
25000
|
heartbeatSet: () => heartbeatSet
|
|
24509
25001
|
});
|
|
24510
|
-
import { existsSync as
|
|
25002
|
+
import { existsSync as existsSync42 } from "fs";
|
|
24511
25003
|
async function heartbeatGet(globalOpts) {
|
|
24512
|
-
if (!
|
|
25004
|
+
if (!existsSync42(DB_PATH)) {
|
|
24513
25005
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24514
25006
|
process.exit(1);
|
|
24515
25007
|
}
|
|
@@ -24618,9 +25110,9 @@ __export(summarizer_exports, {
|
|
|
24618
25110
|
summarizerGet: () => summarizerGet,
|
|
24619
25111
|
summarizerSet: () => summarizerSet
|
|
24620
25112
|
});
|
|
24621
|
-
import { existsSync as
|
|
25113
|
+
import { existsSync as existsSync43 } from "fs";
|
|
24622
25114
|
async function summarizerGet(globalOpts) {
|
|
24623
|
-
if (!
|
|
25115
|
+
if (!existsSync43(DB_PATH)) {
|
|
24624
25116
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24625
25117
|
process.exit(1);
|
|
24626
25118
|
}
|
|
@@ -24664,9 +25156,9 @@ __export(thinking_exports, {
|
|
|
24664
25156
|
thinkingGet: () => thinkingGet,
|
|
24665
25157
|
thinkingSet: () => thinkingSet
|
|
24666
25158
|
});
|
|
24667
|
-
import { existsSync as
|
|
25159
|
+
import { existsSync as existsSync44 } from "fs";
|
|
24668
25160
|
async function thinkingGet(globalOpts) {
|
|
24669
|
-
if (!
|
|
25161
|
+
if (!existsSync44(DB_PATH)) {
|
|
24670
25162
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24671
25163
|
process.exit(1);
|
|
24672
25164
|
}
|
|
@@ -24710,9 +25202,9 @@ __export(chats_exports, {
|
|
|
24710
25202
|
chatsList: () => chatsList,
|
|
24711
25203
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
24712
25204
|
});
|
|
24713
|
-
import { existsSync as
|
|
25205
|
+
import { existsSync as existsSync45 } from "fs";
|
|
24714
25206
|
async function chatsList(_globalOpts) {
|
|
24715
|
-
if (!
|
|
25207
|
+
if (!existsSync45(DB_PATH)) {
|
|
24716
25208
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24717
25209
|
process.exit(1);
|
|
24718
25210
|
}
|
|
@@ -24840,9 +25332,9 @@ var mcps_exports2 = {};
|
|
|
24840
25332
|
__export(mcps_exports2, {
|
|
24841
25333
|
mcpsList: () => mcpsList
|
|
24842
25334
|
});
|
|
24843
|
-
import { existsSync as
|
|
25335
|
+
import { existsSync as existsSync46 } from "fs";
|
|
24844
25336
|
async function mcpsList(_globalOpts) {
|
|
24845
|
-
if (!
|
|
25337
|
+
if (!existsSync46(DB_PATH)) {
|
|
24846
25338
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24847
25339
|
process.exit(1);
|
|
24848
25340
|
}
|
|
@@ -24879,11 +25371,11 @@ __export(chat_exports2, {
|
|
|
24879
25371
|
chatSend: () => chatSend
|
|
24880
25372
|
});
|
|
24881
25373
|
import { request as httpRequest2 } from "http";
|
|
24882
|
-
import { readFileSync as readFileSync20, existsSync as
|
|
25374
|
+
import { readFileSync as readFileSync20, existsSync as existsSync47 } from "fs";
|
|
24883
25375
|
function getToken2() {
|
|
24884
25376
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
24885
25377
|
try {
|
|
24886
|
-
if (
|
|
25378
|
+
if (existsSync47(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
|
|
24887
25379
|
} catch {
|
|
24888
25380
|
}
|
|
24889
25381
|
return null;
|
|
@@ -25162,8 +25654,8 @@ var completion_exports = {};
|
|
|
25162
25654
|
__export(completion_exports, {
|
|
25163
25655
|
completionCommand: () => completionCommand
|
|
25164
25656
|
});
|
|
25165
|
-
import { writeFileSync as writeFileSync10, mkdirSync as
|
|
25166
|
-
import { join as
|
|
25657
|
+
import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync16 } from "fs";
|
|
25658
|
+
import { join as join28 } from "path";
|
|
25167
25659
|
import { homedir as homedir9 } from "os";
|
|
25168
25660
|
async function completionCommand(opts) {
|
|
25169
25661
|
const shell = opts.shell ?? detectShell();
|
|
@@ -25179,10 +25671,10 @@ async function completionCommand(opts) {
|
|
|
25179
25671
|
process.exit(1);
|
|
25180
25672
|
}
|
|
25181
25673
|
if (opts.install) {
|
|
25182
|
-
const dir =
|
|
25183
|
-
|
|
25674
|
+
const dir = join28(homedir9(), ".config", "cc-claw", "completions");
|
|
25675
|
+
mkdirSync16(dir, { recursive: true });
|
|
25184
25676
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
25185
|
-
const filepath =
|
|
25677
|
+
const filepath = join28(dir, filename);
|
|
25186
25678
|
writeFileSync10(filepath, script, "utf-8");
|
|
25187
25679
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
25188
25680
|
`);
|
|
@@ -25353,9 +25845,9 @@ __export(evolve_exports2, {
|
|
|
25353
25845
|
evolveStatus: () => evolveStatus,
|
|
25354
25846
|
evolveUndo: () => evolveUndo
|
|
25355
25847
|
});
|
|
25356
|
-
import { existsSync as
|
|
25848
|
+
import { existsSync as existsSync48 } from "fs";
|
|
25357
25849
|
function ensureDb3() {
|
|
25358
|
-
if (!
|
|
25850
|
+
if (!existsSync48(DB_PATH)) {
|
|
25359
25851
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25360
25852
|
process.exit(1);
|
|
25361
25853
|
}
|
|
@@ -25771,10 +26263,10 @@ var init_evolve3 = __esm({
|
|
|
25771
26263
|
|
|
25772
26264
|
// src/setup.ts
|
|
25773
26265
|
var setup_exports = {};
|
|
25774
|
-
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";
|
|
25775
26267
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
25776
26268
|
import { createInterface as createInterface8 } from "readline";
|
|
25777
|
-
import { join as
|
|
26269
|
+
import { join as join29 } from "path";
|
|
25778
26270
|
function divider2() {
|
|
25779
26271
|
console.log(dim("\u2500".repeat(55)));
|
|
25780
26272
|
}
|
|
@@ -25849,10 +26341,10 @@ async function setup() {
|
|
|
25849
26341
|
}
|
|
25850
26342
|
console.log("");
|
|
25851
26343
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
25852
|
-
if (!
|
|
26344
|
+
if (!existsSync49(dir)) mkdirSync17(dir, { recursive: true });
|
|
25853
26345
|
}
|
|
25854
26346
|
const env = {};
|
|
25855
|
-
const envSource =
|
|
26347
|
+
const envSource = existsSync49(ENV_PATH) ? ENV_PATH : existsSync49(".env") ? ".env" : null;
|
|
25856
26348
|
if (envSource) {
|
|
25857
26349
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
25858
26350
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -25862,13 +26354,13 @@ async function setup() {
|
|
|
25862
26354
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
25863
26355
|
}
|
|
25864
26356
|
}
|
|
25865
|
-
const cwdDb =
|
|
25866
|
-
if (
|
|
25867
|
-
const { size } =
|
|
26357
|
+
const cwdDb = join29(process.cwd(), "cc-claw.db");
|
|
26358
|
+
if (existsSync49(cwdDb) && !existsSync49(DB_PATH)) {
|
|
26359
|
+
const { size } = statSync10(cwdDb);
|
|
25868
26360
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
25869
26361
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
25870
26362
|
if (migrate) {
|
|
25871
|
-
|
|
26363
|
+
copyFileSync4(cwdDb, DB_PATH);
|
|
25872
26364
|
console.log(green(` Database copied to ${DB_PATH}`));
|
|
25873
26365
|
}
|
|
25874
26366
|
console.log("");
|