cc-claw 0.16.4 → 0.17.1
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 +875 -372
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -33,7 +33,7 @@ var VERSION;
|
|
|
33
33
|
var init_version = __esm({
|
|
34
34
|
"src/version.ts"() {
|
|
35
35
|
"use strict";
|
|
36
|
-
VERSION = true ? "0.
|
|
36
|
+
VERSION = true ? "0.17.1" : (() => {
|
|
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,87 @@ 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.messageText.startsWith(">>")) return false;
|
|
12838
|
+
if (EXEMPT_TIERS.has(input.bootstrapTier)) return false;
|
|
12839
|
+
if (input.isSideQuest) return false;
|
|
12840
|
+
return true;
|
|
12841
|
+
}
|
|
12842
|
+
function buildPlanningDirective() {
|
|
12843
|
+
return [
|
|
12844
|
+
"## PLANNING MODE \u2014 Read-Only",
|
|
12845
|
+
"",
|
|
12846
|
+
"You are in PLANNING mode. Your goal is to research and present a plan.",
|
|
12847
|
+
"",
|
|
12848
|
+
"**ALLOWED:**",
|
|
12849
|
+
"- Read files, directories, and code",
|
|
12850
|
+
"- Load and read skills",
|
|
12851
|
+
"- Search the codebase (grep, glob, find)",
|
|
12852
|
+
"- Search the web for documentation or solutions",
|
|
12853
|
+
"- Analyze and reason about architecture",
|
|
12854
|
+
"",
|
|
12855
|
+
"**NOT ALLOWED:**",
|
|
12856
|
+
"- Do NOT create, modify, or delete any files",
|
|
12857
|
+
"- Do NOT run shell commands that mutate state",
|
|
12858
|
+
"- Do NOT write code or make edits",
|
|
12859
|
+
"- Do NOT install packages or dependencies",
|
|
12860
|
+
"",
|
|
12861
|
+
"**YOUR TASK:**",
|
|
12862
|
+
"Research the request thoroughly, then present a clear, concise plan",
|
|
12863
|
+
"of what you will do. The user will review and approve before you execute.",
|
|
12864
|
+
"Structure your plan with numbered steps and be specific about which",
|
|
12865
|
+
"files you will modify and what changes you will make."
|
|
12866
|
+
].join("\n");
|
|
12867
|
+
}
|
|
12868
|
+
function storePendingPlan(chatId, plan, originalMessage) {
|
|
12869
|
+
pendingPlans.set(chatId, {
|
|
12870
|
+
plan,
|
|
12871
|
+
originalMessage,
|
|
12872
|
+
createdAt: Date.now()
|
|
12873
|
+
});
|
|
12874
|
+
}
|
|
12875
|
+
function getPendingPlan(chatId) {
|
|
12876
|
+
const entry = pendingPlans.get(chatId);
|
|
12877
|
+
if (!entry) return void 0;
|
|
12878
|
+
if (Date.now() - entry.createdAt > PLAN_TTL_MS) {
|
|
12879
|
+
pendingPlans.delete(chatId);
|
|
12880
|
+
return void 0;
|
|
12881
|
+
}
|
|
12882
|
+
return entry;
|
|
12883
|
+
}
|
|
12884
|
+
function removePendingPlan(chatId) {
|
|
12885
|
+
pendingPlans.delete(chatId);
|
|
12886
|
+
}
|
|
12887
|
+
function setRejectionMode(chatId) {
|
|
12888
|
+
rejectionModes.set(chatId, Date.now());
|
|
12889
|
+
}
|
|
12890
|
+
function getRejectionMode(chatId) {
|
|
12891
|
+
const createdAt = rejectionModes.get(chatId);
|
|
12892
|
+
if (createdAt === void 0) return false;
|
|
12893
|
+
if (Date.now() - createdAt > REJECTION_TTL_MS) {
|
|
12894
|
+
rejectionModes.delete(chatId);
|
|
12895
|
+
return false;
|
|
12896
|
+
}
|
|
12897
|
+
return true;
|
|
12898
|
+
}
|
|
12899
|
+
function clearRejectionMode(chatId) {
|
|
12900
|
+
rejectionModes.delete(chatId);
|
|
12901
|
+
}
|
|
12902
|
+
var EXEMPT_TIERS, PLAN_TTL_MS, pendingPlans, REJECTION_TTL_MS, rejectionModes;
|
|
12903
|
+
var init_gate = __esm({
|
|
12904
|
+
"src/execution/gate.ts"() {
|
|
12905
|
+
"use strict";
|
|
12906
|
+
EXEMPT_TIERS = /* @__PURE__ */ new Set(["slim", "heartbeat", "chat"]);
|
|
12907
|
+
PLAN_TTL_MS = 5 * 60 * 1e3;
|
|
12908
|
+
pendingPlans = /* @__PURE__ */ new Map();
|
|
12909
|
+
REJECTION_TTL_MS = 5 * 60 * 1e3;
|
|
12910
|
+
rejectionModes = /* @__PURE__ */ new Map();
|
|
12911
|
+
}
|
|
12912
|
+
});
|
|
12913
|
+
|
|
12610
12914
|
// src/router/helpers.ts
|
|
12611
12915
|
import { resolve as resolvePath } from "path";
|
|
12612
12916
|
function parseMcpListOutput(output2) {
|
|
@@ -13307,9 +13611,9 @@ var init_stt = __esm({
|
|
|
13307
13611
|
});
|
|
13308
13612
|
|
|
13309
13613
|
// src/media/image-gen.ts
|
|
13310
|
-
import { mkdirSync as
|
|
13614
|
+
import { mkdirSync as mkdirSync8, existsSync as existsSync16, unlink as unlink2, readdir, stat } from "fs";
|
|
13311
13615
|
import { writeFile } from "fs/promises";
|
|
13312
|
-
import { join as
|
|
13616
|
+
import { join as join15 } from "path";
|
|
13313
13617
|
async function generateImage(prompt) {
|
|
13314
13618
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
13315
13619
|
if (!apiKey) {
|
|
@@ -13356,12 +13660,12 @@ async function generateImage(prompt) {
|
|
|
13356
13660
|
if (!imageData) {
|
|
13357
13661
|
throw new Error(textResponse ?? "Gemini did not generate an image. The prompt may have been filtered.");
|
|
13358
13662
|
}
|
|
13359
|
-
if (!
|
|
13360
|
-
|
|
13663
|
+
if (!existsSync16(IMAGE_OUTPUT_DIR)) {
|
|
13664
|
+
mkdirSync8(IMAGE_OUTPUT_DIR, { recursive: true });
|
|
13361
13665
|
}
|
|
13362
13666
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
13363
13667
|
const filename = `img_${Date.now()}.${ext}`;
|
|
13364
|
-
const filePath =
|
|
13668
|
+
const filePath = join15(IMAGE_OUTPUT_DIR, filename);
|
|
13365
13669
|
const buffer = Buffer.from(imageData, "base64");
|
|
13366
13670
|
await writeFile(filePath, buffer);
|
|
13367
13671
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
@@ -13379,7 +13683,7 @@ function cleanupGeneratedImage(filePath) {
|
|
|
13379
13683
|
function pruneImageCache() {
|
|
13380
13684
|
readdir(IMAGE_OUTPUT_DIR, (err, files) => {
|
|
13381
13685
|
if (err || !files) return;
|
|
13382
|
-
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) =>
|
|
13686
|
+
const imageFiles = files.filter((f) => /\.(png|jpg)$/.test(f)).map((f) => join15(IMAGE_OUTPUT_DIR, f));
|
|
13383
13687
|
if (imageFiles.length === 0) return;
|
|
13384
13688
|
const now = Date.now();
|
|
13385
13689
|
let statsPending = imageFiles.length;
|
|
@@ -13411,8 +13715,8 @@ var init_image_gen = __esm({
|
|
|
13411
13715
|
MAX_GENERATED_IMAGES = 20;
|
|
13412
13716
|
IMAGE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
13413
13717
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
13414
|
-
IMAGE_OUTPUT_DIR =
|
|
13415
|
-
process.env.CC_CLAW_HOME ??
|
|
13718
|
+
IMAGE_OUTPUT_DIR = join15(
|
|
13719
|
+
process.env.CC_CLAW_HOME ?? join15(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
13416
13720
|
"data",
|
|
13417
13721
|
"images"
|
|
13418
13722
|
);
|
|
@@ -13885,7 +14189,7 @@ var init_video = __esm({
|
|
|
13885
14189
|
});
|
|
13886
14190
|
|
|
13887
14191
|
// src/router/media.ts
|
|
13888
|
-
import { join as
|
|
14192
|
+
import { join as join16 } from "path";
|
|
13889
14193
|
import { mkdir, writeFile as writeFile2, readdir as readdir2, stat as stat2, unlink as unlink3 } from "fs/promises";
|
|
13890
14194
|
function getMediaRetentionMs() {
|
|
13891
14195
|
const hours = parseInt(process.env.MEDIA_RETENTION_HOURS ?? "24", 10);
|
|
@@ -13894,7 +14198,7 @@ function getMediaRetentionMs() {
|
|
|
13894
14198
|
async function saveMedia(buffer, prefix, ext) {
|
|
13895
14199
|
await mkdir(MEDIA_INCOMING_PATH, { recursive: true });
|
|
13896
14200
|
const filename = `${prefix}-${Date.now()}.${ext}`;
|
|
13897
|
-
const fullPath =
|
|
14201
|
+
const fullPath = join16(MEDIA_INCOMING_PATH, filename);
|
|
13898
14202
|
await writeFile2(fullPath, buffer);
|
|
13899
14203
|
return fullPath;
|
|
13900
14204
|
}
|
|
@@ -13908,7 +14212,7 @@ async function cleanupOldMedia() {
|
|
|
13908
14212
|
let removed = 0;
|
|
13909
14213
|
for (const file of files) {
|
|
13910
14214
|
try {
|
|
13911
|
-
const filePath =
|
|
14215
|
+
const filePath = join16(MEDIA_INCOMING_PATH, file);
|
|
13912
14216
|
const s = await stat2(filePath);
|
|
13913
14217
|
if (now - s.mtimeMs > retentionMs) {
|
|
13914
14218
|
await unlink3(filePath);
|
|
@@ -14091,7 +14395,7 @@ var init_media = __esm({
|
|
|
14091
14395
|
init_store5();
|
|
14092
14396
|
init_helpers();
|
|
14093
14397
|
init_response();
|
|
14094
|
-
MEDIA_INCOMING_PATH =
|
|
14398
|
+
MEDIA_INCOMING_PATH = join16(MEDIA_PATH, "incoming");
|
|
14095
14399
|
}
|
|
14096
14400
|
});
|
|
14097
14401
|
|
|
@@ -14227,7 +14531,7 @@ __export(discover_exports, {
|
|
|
14227
14531
|
import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
|
|
14228
14532
|
import { createHash } from "crypto";
|
|
14229
14533
|
import { homedir as homedir5 } from "os";
|
|
14230
|
-
import { join as
|
|
14534
|
+
import { join as join17 } from "path";
|
|
14231
14535
|
function invalidateSkillCache() {
|
|
14232
14536
|
cachedSkills = null;
|
|
14233
14537
|
cacheTimestamp = 0;
|
|
@@ -14245,7 +14549,7 @@ async function discoverAllSkills() {
|
|
|
14245
14549
|
const rawSkills = [];
|
|
14246
14550
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
14247
14551
|
for (const backendId of getAllBackendIds()) {
|
|
14248
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [
|
|
14552
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join17(homedir5(), `.${backendId}`, "skills")];
|
|
14249
14553
|
for (const dir of dirs) {
|
|
14250
14554
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
14251
14555
|
}
|
|
@@ -14273,7 +14577,7 @@ async function scanSkillDir(skillsDir, source) {
|
|
|
14273
14577
|
let content;
|
|
14274
14578
|
let resolvedPath;
|
|
14275
14579
|
for (const candidate of SKILL_FILE_CANDIDATES) {
|
|
14276
|
-
const p =
|
|
14580
|
+
const p = join17(skillsDir, entry.name, candidate);
|
|
14277
14581
|
try {
|
|
14278
14582
|
content = await readFile4(p, "utf-8");
|
|
14279
14583
|
resolvedPath = p;
|
|
@@ -14377,15 +14681,15 @@ var init_discover = __esm({
|
|
|
14377
14681
|
init_backends();
|
|
14378
14682
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
14379
14683
|
BACKEND_SKILL_DIRS = {
|
|
14380
|
-
claude: [
|
|
14381
|
-
gemini: [
|
|
14684
|
+
claude: [join17(homedir5(), ".claude", "skills")],
|
|
14685
|
+
gemini: [join17(homedir5(), ".gemini", "skills")],
|
|
14382
14686
|
codex: [
|
|
14383
|
-
|
|
14384
|
-
|
|
14687
|
+
join17(homedir5(), ".agents", "skills"),
|
|
14688
|
+
join17(homedir5(), ".codex", "skills")
|
|
14385
14689
|
],
|
|
14386
14690
|
cursor: [
|
|
14387
|
-
|
|
14388
|
-
|
|
14691
|
+
join17(homedir5(), ".cursor", "skills"),
|
|
14692
|
+
join17(homedir5(), ".cursor", "skills-cursor")
|
|
14389
14693
|
]
|
|
14390
14694
|
};
|
|
14391
14695
|
CACHE_TTL_MS2 = 3e5;
|
|
@@ -14401,8 +14705,8 @@ __export(install_exports, {
|
|
|
14401
14705
|
installSkillFromGitHub: () => installSkillFromGitHub
|
|
14402
14706
|
});
|
|
14403
14707
|
import { mkdir as mkdir2, readdir as readdir4, readFile as readFile5, cp } from "fs/promises";
|
|
14404
|
-
import { existsSync as
|
|
14405
|
-
import { join as
|
|
14708
|
+
import { existsSync as existsSync17 } from "fs";
|
|
14709
|
+
import { join as join18, basename } from "path";
|
|
14406
14710
|
import { execSync as execSync5 } from "child_process";
|
|
14407
14711
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
14408
14712
|
let repoUrl;
|
|
@@ -14413,36 +14717,36 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
14413
14717
|
}
|
|
14414
14718
|
repoUrl = parsed.cloneUrl;
|
|
14415
14719
|
subPath = parsed.subPath;
|
|
14416
|
-
const tmpDir =
|
|
14720
|
+
const tmpDir = join18("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
14417
14721
|
try {
|
|
14418
14722
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
14419
14723
|
execSync5(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
14420
14724
|
stdio: "pipe",
|
|
14421
14725
|
timeout: 3e4
|
|
14422
14726
|
});
|
|
14423
|
-
if (!
|
|
14727
|
+
if (!existsSync17(join18(tmpDir, ".git"))) {
|
|
14424
14728
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
14425
14729
|
}
|
|
14426
|
-
const searchRoot = subPath ?
|
|
14730
|
+
const searchRoot = subPath ? join18(tmpDir, subPath) : tmpDir;
|
|
14427
14731
|
const skillDir = await findSkillDir(searchRoot);
|
|
14428
14732
|
if (!skillDir) {
|
|
14429
14733
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
14430
14734
|
}
|
|
14431
14735
|
const skillFolderName = basename(skillDir);
|
|
14432
|
-
const destDir =
|
|
14433
|
-
if (
|
|
14736
|
+
const destDir = join18(SKILLS_PATH, skillFolderName);
|
|
14737
|
+
if (existsSync17(destDir)) {
|
|
14434
14738
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
14435
14739
|
}
|
|
14436
14740
|
await mkdir2(destDir, { recursive: true });
|
|
14437
14741
|
await cp(skillDir, destDir, { recursive: true });
|
|
14438
14742
|
let skillName = skillFolderName;
|
|
14439
14743
|
try {
|
|
14440
|
-
const content = await readFile5(
|
|
14744
|
+
const content = await readFile5(join18(destDir, "SKILL.md"), "utf-8");
|
|
14441
14745
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14442
14746
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14443
14747
|
} catch {
|
|
14444
14748
|
try {
|
|
14445
|
-
const content = await readFile5(
|
|
14749
|
+
const content = await readFile5(join18(destDir, "skill.md"), "utf-8");
|
|
14446
14750
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
14447
14751
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
14448
14752
|
} catch {
|
|
@@ -14477,15 +14781,15 @@ function parseGitHubUrl(input) {
|
|
|
14477
14781
|
async function findSkillDir(root) {
|
|
14478
14782
|
const candidates = ["SKILL.md", "skill.md"];
|
|
14479
14783
|
for (const c of candidates) {
|
|
14480
|
-
if (
|
|
14784
|
+
if (existsSync17(join18(root, c))) return root;
|
|
14481
14785
|
}
|
|
14482
14786
|
try {
|
|
14483
14787
|
const entries = await readdir4(root, { withFileTypes: true });
|
|
14484
14788
|
for (const entry of entries) {
|
|
14485
14789
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14486
14790
|
for (const c of candidates) {
|
|
14487
|
-
if (
|
|
14488
|
-
return
|
|
14791
|
+
if (existsSync17(join18(root, entry.name, c))) {
|
|
14792
|
+
return join18(root, entry.name);
|
|
14489
14793
|
}
|
|
14490
14794
|
}
|
|
14491
14795
|
}
|
|
@@ -14497,15 +14801,15 @@ async function findSkillDir(root) {
|
|
|
14497
14801
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
14498
14802
|
let subEntries;
|
|
14499
14803
|
try {
|
|
14500
|
-
subEntries = await readdir4(
|
|
14804
|
+
subEntries = await readdir4(join18(root, entry.name), { withFileTypes: true });
|
|
14501
14805
|
} catch {
|
|
14502
14806
|
continue;
|
|
14503
14807
|
}
|
|
14504
14808
|
for (const sub of subEntries) {
|
|
14505
14809
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
14506
14810
|
for (const c of candidates) {
|
|
14507
|
-
if (
|
|
14508
|
-
return
|
|
14811
|
+
if (existsSync17(join18(root, entry.name, sub.name, c))) {
|
|
14812
|
+
return join18(root, entry.name, sub.name);
|
|
14509
14813
|
}
|
|
14510
14814
|
}
|
|
14511
14815
|
}
|
|
@@ -14523,8 +14827,8 @@ var init_install = __esm({
|
|
|
14523
14827
|
});
|
|
14524
14828
|
|
|
14525
14829
|
// src/bootstrap/heartbeat.ts
|
|
14526
|
-
import { readFileSync as readFileSync9, existsSync as
|
|
14527
|
-
import { join as
|
|
14830
|
+
import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
|
|
14831
|
+
import { join as join19 } from "path";
|
|
14528
14832
|
function initHeartbeat(channelReg) {
|
|
14529
14833
|
registry2 = channelReg;
|
|
14530
14834
|
}
|
|
@@ -14662,7 +14966,7 @@ ${healthLines.join("\n")}`);
|
|
|
14662
14966
|
sections.push(`[Active watches]
|
|
14663
14967
|
${watchLines.join("\n")}`);
|
|
14664
14968
|
}
|
|
14665
|
-
if (
|
|
14969
|
+
if (existsSync18(HEARTBEAT_MD_PATH)) {
|
|
14666
14970
|
try {
|
|
14667
14971
|
const custom = readFileSync9(HEARTBEAT_MD_PATH, "utf-8").trim();
|
|
14668
14972
|
if (custom) {
|
|
@@ -14710,7 +15014,7 @@ var init_heartbeat2 = __esm({
|
|
|
14710
15014
|
init_backends();
|
|
14711
15015
|
init_health2();
|
|
14712
15016
|
init_log();
|
|
14713
|
-
HEARTBEAT_MD_PATH =
|
|
15017
|
+
HEARTBEAT_MD_PATH = join19(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
14714
15018
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
14715
15019
|
registry2 = null;
|
|
14716
15020
|
activeTimers = /* @__PURE__ */ new Map();
|
|
@@ -15767,9 +16071,9 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15767
16071
|
await channel.sendText(chatId, "No pending proposals.", { parseMode: "plain" });
|
|
15768
16072
|
} else {
|
|
15769
16073
|
const insightIds = pending.slice(0, 5).map((p) => p.id);
|
|
15770
|
-
createReviewSession2(getDb(),
|
|
16074
|
+
createReviewSession2(getDb(), chatId, insightIds);
|
|
15771
16075
|
await channel.sendText(chatId, `${pending.length} proposal(s) ready. Let's review them one by one.`, { parseMode: "plain" });
|
|
15772
|
-
await sendCurrentProposal(
|
|
16076
|
+
await sendCurrentProposal(chatId, channel);
|
|
15773
16077
|
}
|
|
15774
16078
|
break;
|
|
15775
16079
|
}
|
|
@@ -15927,13 +16231,13 @@ async function handleEvolveCallback(chatId, data, channel) {
|
|
|
15927
16231
|
const { getReflectionStatus: getReflectionStatus2, setReflectionStatus: setReflectionStatus2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
15928
16232
|
const current = getReflectionStatus2(getDb(), chatId);
|
|
15929
16233
|
if (current === "frozen") {
|
|
15930
|
-
const { readFileSync: readFileSync22, existsSync:
|
|
15931
|
-
const { join:
|
|
16234
|
+
const { readFileSync: readFileSync22, existsSync: existsSync50 } = await import("fs");
|
|
16235
|
+
const { join: join30 } = await import("path");
|
|
15932
16236
|
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 =
|
|
16237
|
+
const soulPath = join30(CC_CLAW_HOME3, "identity/SOUL.md");
|
|
16238
|
+
const userPath = join30(CC_CLAW_HOME3, "identity/USER.md");
|
|
16239
|
+
const soul = existsSync50(soulPath) ? readFileSync22(soulPath, "utf-8") : "";
|
|
16240
|
+
const user = existsSync50(userPath) ? readFileSync22(userPath, "utf-8") : "";
|
|
15937
16241
|
setReflectionStatus2(getDb(), chatId, "active", soul, user);
|
|
15938
16242
|
const { logActivity: logActivity2 } = await Promise.resolve().then(() => (init_store3(), store_exports3));
|
|
15939
16243
|
logActivity2(getDb(), { chatId, source: "telegram", eventType: "reflection_unfrozen", summary: "Reflection enabled" });
|
|
@@ -16086,6 +16390,29 @@ ${cmds.map((c) => ` ${c.cmd} \u2014 ${c.desc}`).join("\n")}`
|
|
|
16086
16390
|
}
|
|
16087
16391
|
break;
|
|
16088
16392
|
}
|
|
16393
|
+
case "mode":
|
|
16394
|
+
case "execmode": {
|
|
16395
|
+
const currentExecMode = getExecMode(chatId);
|
|
16396
|
+
const EXEC_MODES = {
|
|
16397
|
+
approved: "\u2705 Approved \u2014 AI shows a plan before acting",
|
|
16398
|
+
yolo: "\u26A1 YOLO \u2014 AI executes immediately"
|
|
16399
|
+
};
|
|
16400
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
16401
|
+
const buttons = Object.entries(EXEC_MODES).map(([id, label2]) => [{
|
|
16402
|
+
label: `${id === currentExecMode ? "\u2713 " : ""}${label2}`,
|
|
16403
|
+
data: `execmode:${id}`,
|
|
16404
|
+
...id === currentExecMode ? { style: "primary" } : {}
|
|
16405
|
+
}]);
|
|
16406
|
+
await channel.sendKeyboard(chatId, `Execution mode (current: <b>${currentExecMode}</b>):`, buttons);
|
|
16407
|
+
} else {
|
|
16408
|
+
const lines = ["Execution modes:", ""];
|
|
16409
|
+
for (const [id, label2] of Object.entries(EXEC_MODES)) {
|
|
16410
|
+
lines.push(`${id === currentExecMode ? "\u2713 " : " "}/mode ${id} \u2014 ${label2}`);
|
|
16411
|
+
}
|
|
16412
|
+
await channel.sendText(chatId, lines.join("\n"), { parseMode: "plain" });
|
|
16413
|
+
}
|
|
16414
|
+
break;
|
|
16415
|
+
}
|
|
16089
16416
|
case "verbose": {
|
|
16090
16417
|
const currentVerbose = getVerboseLevel(chatId);
|
|
16091
16418
|
const buttons = Object.entries(VERBOSE_LEVELS).map(([id, label2]) => [{
|
|
@@ -16140,8 +16467,23 @@ Tap to toggle:`,
|
|
|
16140
16467
|
setSessionStartedAt(chatId);
|
|
16141
16468
|
logActivity(getDb(), { chatId, source: "telegram", eventType: "config_changed", summary: "New session started", detail: { field: "session", action: "reset", summarized } });
|
|
16142
16469
|
if (typeof channel.sendKeyboard === "function" && oldSessionId) {
|
|
16143
|
-
|
|
16470
|
+
let adapter;
|
|
16471
|
+
try {
|
|
16472
|
+
adapter = getAdapterForChat(chatId);
|
|
16473
|
+
} catch {
|
|
16474
|
+
adapter = null;
|
|
16475
|
+
}
|
|
16476
|
+
const currentModel = getModel(chatId) ?? adapter?.defaultModel ?? "default";
|
|
16477
|
+
const modelLabel = adapter ? formatModelShort(currentModel) : currentModel;
|
|
16478
|
+
const backendLabel = adapter?.displayName ?? getBackend(chatId) ?? "not set";
|
|
16479
|
+
const msg2 = `\u2705 New session started. Previous session archived${exchangeCount > 0 ? ` (${exchangeCount} exchanges)` : ""}.
|
|
16480
|
+
|
|
16481
|
+
\u{1F9E0} ${backendLabel} \xB7 ${modelLabel}`;
|
|
16144
16482
|
const kbMsgId = await channel.sendKeyboard(chatId, msg2, [
|
|
16483
|
+
[
|
|
16484
|
+
{ label: "Switch Backend", data: "menu:backend", style: "primary" },
|
|
16485
|
+
{ label: "Switch Model", data: "menu:model", style: "primary" }
|
|
16486
|
+
],
|
|
16145
16487
|
[{ label: "Undo", data: "newchat:undo" }]
|
|
16146
16488
|
]);
|
|
16147
16489
|
if (kbMsgId) {
|
|
@@ -17794,6 +18136,54 @@ ${PERM_MODES[chosen]}`,
|
|
|
17794
18136
|
await channel.sendText(chatId, `Agent mode set to <b>${mode}</b>. Session cleared.`, { parseMode: "html" });
|
|
17795
18137
|
}
|
|
17796
18138
|
return;
|
|
18139
|
+
} else if (data === "exec:approve") {
|
|
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
|
+
await channel.sendText(chatId, "\u2705 Approved. Executing...", { parseMode: "plain" });
|
|
18147
|
+
const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
|
|
18148
|
+
await handleMessage2(
|
|
18149
|
+
{ text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
|
|
18150
|
+
channel
|
|
18151
|
+
);
|
|
18152
|
+
return;
|
|
18153
|
+
} else if (data === "exec:reject") {
|
|
18154
|
+
const plan = getPendingPlan(chatId);
|
|
18155
|
+
if (!plan) {
|
|
18156
|
+
await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
|
|
18157
|
+
return;
|
|
18158
|
+
}
|
|
18159
|
+
removePendingPlan(chatId);
|
|
18160
|
+
setRejectionMode(chatId);
|
|
18161
|
+
await channel.sendText(chatId, "\u270F\uFE0F Plan rejected. Send your feedback and I'll revise the plan.", { parseMode: "plain" });
|
|
18162
|
+
return;
|
|
18163
|
+
} else if (data === "exec:yolo") {
|
|
18164
|
+
const plan = getPendingPlan(chatId);
|
|
18165
|
+
if (!plan) {
|
|
18166
|
+
await channel.sendText(chatId, "\u26A0\uFE0F Plan expired or already processed.", { parseMode: "plain" });
|
|
18167
|
+
return;
|
|
18168
|
+
}
|
|
18169
|
+
removePendingPlan(chatId);
|
|
18170
|
+
setExecMode(chatId, "yolo");
|
|
18171
|
+
await channel.sendText(chatId, "\u26A1 Switched to YOLO mode. Executing without approval gate...", { parseMode: "plain" });
|
|
18172
|
+
const { handleMessage: handleMessage2 } = await Promise.resolve().then(() => (init_router(), router_exports));
|
|
18173
|
+
await handleMessage2(
|
|
18174
|
+
{ text: `>>${plan.originalMessage}`, chatId, source: "telegram", type: "text", senderName: "", messageId: "" },
|
|
18175
|
+
channel
|
|
18176
|
+
);
|
|
18177
|
+
return;
|
|
18178
|
+
} else if (data.startsWith("execmode:")) {
|
|
18179
|
+
const mode = data.split(":")[1];
|
|
18180
|
+
if (mode === "approved" || mode === "yolo") {
|
|
18181
|
+
setExecMode(chatId, mode);
|
|
18182
|
+
const desc = mode === "approved" ? "AI will show a plan for approval before acting." : "AI will execute immediately without showing a plan.";
|
|
18183
|
+
await channel.sendText(chatId, `Execution mode set to <b>${mode}</b>.
|
|
18184
|
+
${desc}`, { parseMode: "html" });
|
|
18185
|
+
}
|
|
18186
|
+
return;
|
|
17797
18187
|
} else if (data.startsWith("model_sig:")) {
|
|
17798
18188
|
const value = data.slice(10);
|
|
17799
18189
|
setModelSignature(chatId, value);
|
|
@@ -18553,6 +18943,7 @@ var init_callbacks = __esm({
|
|
|
18553
18943
|
init_guard();
|
|
18554
18944
|
init_pagination();
|
|
18555
18945
|
init_stt();
|
|
18946
|
+
init_gate();
|
|
18556
18947
|
init_helpers();
|
|
18557
18948
|
init_response();
|
|
18558
18949
|
init_shell();
|
|
@@ -18712,6 +19103,33 @@ async function handleText(msg, channel) {
|
|
|
18712
19103
|
if (hasSqPrefix) {
|
|
18713
19104
|
text = sqCleanText;
|
|
18714
19105
|
}
|
|
19106
|
+
if (getRejectionMode(chatId)) {
|
|
19107
|
+
clearRejectionMode(chatId);
|
|
19108
|
+
await channel.sendTyping?.(chatId);
|
|
19109
|
+
const response = await askAgent(chatId, `Plan rejected. Feedback: "${text}". Revise your plan.`, {
|
|
19110
|
+
cwd: getCwd(chatId),
|
|
19111
|
+
model: model2,
|
|
19112
|
+
permMode: "yolo",
|
|
19113
|
+
agentMode: effectiveAgentMode
|
|
19114
|
+
});
|
|
19115
|
+
if (response.text) {
|
|
19116
|
+
storePendingPlan(chatId, response.text, text);
|
|
19117
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
19118
|
+
await channel.sendKeyboard(chatId, `\u{1F50D} ${response.text}`, [
|
|
19119
|
+
[
|
|
19120
|
+
{ label: "\u2705 Approve", data: "exec:approve", style: "success" },
|
|
19121
|
+
{ label: "\u274C Reject", data: "exec:reject", style: "danger" }
|
|
19122
|
+
],
|
|
19123
|
+
[
|
|
19124
|
+
{ label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
|
|
19125
|
+
]
|
|
19126
|
+
]);
|
|
19127
|
+
} else {
|
|
19128
|
+
await sendResponse(chatId, channel, response.text, void 0);
|
|
19129
|
+
}
|
|
19130
|
+
}
|
|
19131
|
+
return;
|
|
19132
|
+
}
|
|
18715
19133
|
{
|
|
18716
19134
|
const { getDiscussionMode: getDiscussionMode2, clearDiscussionMode: clearDiscussionMode2, setDiscussionMode: reenterDiscussion, getInsightById: getInsightById2, updateInsightProposal: updateInsightProposal2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
18717
19135
|
const discussInsightId = getDiscussionMode2(chatId);
|
|
@@ -18788,6 +19206,61 @@ You're still in discussion mode \u2014 try again or click a button to exit.`, {
|
|
|
18788
19206
|
return;
|
|
18789
19207
|
}
|
|
18790
19208
|
}
|
|
19209
|
+
const execMode = getExecMode(chatId);
|
|
19210
|
+
if (shouldRequireApproval({
|
|
19211
|
+
execMode,
|
|
19212
|
+
intent,
|
|
19213
|
+
bootstrapTier: bootstrapTier ?? "full",
|
|
19214
|
+
messageText: text,
|
|
19215
|
+
isSideQuest: hasSqPrefix
|
|
19216
|
+
})) {
|
|
19217
|
+
const planDirective = buildPlanningDirective();
|
|
19218
|
+
let typingActive2 = true;
|
|
19219
|
+
const typingLoop2 = async () => {
|
|
19220
|
+
while (typingActive2) {
|
|
19221
|
+
try {
|
|
19222
|
+
await channel.sendTyping?.(chatId);
|
|
19223
|
+
} catch {
|
|
19224
|
+
}
|
|
19225
|
+
await new Promise((r) => setTimeout(r, 4e3));
|
|
19226
|
+
}
|
|
19227
|
+
};
|
|
19228
|
+
typingLoop2().catch(() => {
|
|
19229
|
+
});
|
|
19230
|
+
try {
|
|
19231
|
+
const planResponse = await askAgent(chatId, cleanText || text, {
|
|
19232
|
+
cwd: getCwd(chatId),
|
|
19233
|
+
model: model2,
|
|
19234
|
+
permMode: "yolo",
|
|
19235
|
+
bootstrapTier: bootstrapTier ?? "full",
|
|
19236
|
+
agentMode: effectiveAgentMode,
|
|
19237
|
+
planningDirective: planDirective
|
|
19238
|
+
});
|
|
19239
|
+
typingActive2 = false;
|
|
19240
|
+
if (planResponse.text) {
|
|
19241
|
+
storePendingPlan(chatId, planResponse.text, cleanText || text);
|
|
19242
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
19243
|
+
await channel.sendKeyboard(chatId, `\u{1F50D} ${planResponse.text}`, [
|
|
19244
|
+
[
|
|
19245
|
+
{ label: "\u2705 Approve", data: "exec:approve", style: "success" },
|
|
19246
|
+
{ label: "\u274C Reject", data: "exec:reject", style: "danger" }
|
|
19247
|
+
],
|
|
19248
|
+
[
|
|
19249
|
+
{ label: "\u26A1 Skip & YOLO", data: "exec:yolo" }
|
|
19250
|
+
]
|
|
19251
|
+
]);
|
|
19252
|
+
} else {
|
|
19253
|
+
await sendResponse(chatId, channel, planResponse.text, void 0);
|
|
19254
|
+
}
|
|
19255
|
+
} else {
|
|
19256
|
+
await channel.sendText(chatId, "(No plan generated \u2014 proceeding normally)", { parseMode: "plain" });
|
|
19257
|
+
}
|
|
19258
|
+
} catch (err) {
|
|
19259
|
+
typingActive2 = false;
|
|
19260
|
+
await channel.sendText(chatId, `\u26A0\uFE0F Planning error: ${err.message}`, { parseMode: "plain" });
|
|
19261
|
+
}
|
|
19262
|
+
return;
|
|
19263
|
+
}
|
|
18791
19264
|
let typingActive = true;
|
|
18792
19265
|
const typingLoop = async () => {
|
|
18793
19266
|
while (typingActive) {
|
|
@@ -18968,6 +19441,7 @@ var init_router = __esm({
|
|
|
18968
19441
|
init_wizard();
|
|
18969
19442
|
init_classify2();
|
|
18970
19443
|
init_store3();
|
|
19444
|
+
init_gate();
|
|
18971
19445
|
init_helpers();
|
|
18972
19446
|
init_response();
|
|
18973
19447
|
init_shell();
|
|
@@ -19228,6 +19702,8 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19228
19702
|
if (job.jobType === "reflection") {
|
|
19229
19703
|
const { runNightlyReflection: runNightlyReflection2 } = await Promise.resolve().then(() => (init_analyze(), analyze_exports));
|
|
19230
19704
|
const { formatNightlySummary: formatNightlySummary2 } = await Promise.resolve().then(() => (init_propose(), propose_exports));
|
|
19705
|
+
const { getPendingInsightCount: getPendingInsightCount2, getActiveReflectionChatIds: getActiveReflectionChatIds2 } = await Promise.resolve().then(() => (init_store4(), store_exports4));
|
|
19706
|
+
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
19231
19707
|
const timeoutMs2 = job.timeout ? job.timeout * 1e3 : void 0;
|
|
19232
19708
|
const { results } = await runNightlyReflection2({
|
|
19233
19709
|
timeoutMs: timeoutMs2,
|
|
@@ -19240,7 +19716,13 @@ async function runWithRetry(job, model2, runId, t0) {
|
|
|
19240
19716
|
const allInsights = results.flatMap(
|
|
19241
19717
|
(r) => r.insights.map((ins) => ({ id: ++seq, ...ins }))
|
|
19242
19718
|
);
|
|
19243
|
-
|
|
19719
|
+
const db3 = getDb2();
|
|
19720
|
+
const activeChats2 = getActiveReflectionChatIds2(db3);
|
|
19721
|
+
let totalPending = 0;
|
|
19722
|
+
for (const cid of activeChats2) {
|
|
19723
|
+
totalPending += getPendingInsightCount2(db3, cid);
|
|
19724
|
+
}
|
|
19725
|
+
return { text: formatNightlySummary2(allInsights, totalPending) };
|
|
19244
19726
|
}
|
|
19245
19727
|
if (job.thinking && job.thinking !== "auto") {
|
|
19246
19728
|
setThinkingLevel(chatId, job.thinking);
|
|
@@ -19346,7 +19828,7 @@ var init_cron = __esm({
|
|
|
19346
19828
|
});
|
|
19347
19829
|
|
|
19348
19830
|
// src/agents/runners/wrap-backend.ts
|
|
19349
|
-
import { join as
|
|
19831
|
+
import { join as join20 } from "path";
|
|
19350
19832
|
function buildMcpCommands(backendId) {
|
|
19351
19833
|
const exe = backendId === "cursor" ? "agent" : backendId;
|
|
19352
19834
|
return {
|
|
@@ -19440,7 +19922,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
19440
19922
|
const configPath = writeMcpConfigFile(server);
|
|
19441
19923
|
return ["--mcp-config", configPath];
|
|
19442
19924
|
},
|
|
19443
|
-
getSkillPath: () =>
|
|
19925
|
+
getSkillPath: () => join20(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
19444
19926
|
};
|
|
19445
19927
|
}
|
|
19446
19928
|
var BACKEND_CAPABILITIES;
|
|
@@ -19491,18 +19973,18 @@ var init_wrap_backend = __esm({
|
|
|
19491
19973
|
});
|
|
19492
19974
|
|
|
19493
19975
|
// src/agents/runners/config-loader.ts
|
|
19494
|
-
import { readFileSync as readFileSync10, readdirSync as
|
|
19495
|
-
import { join as
|
|
19976
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync9, existsSync as existsSync19, mkdirSync as mkdirSync9, watchFile, unwatchFile } from "fs";
|
|
19977
|
+
import { join as join21 } from "path";
|
|
19496
19978
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
19497
19979
|
function resolveExecutable(config2) {
|
|
19498
|
-
if (
|
|
19980
|
+
if (existsSync19(config2.executable)) return config2.executable;
|
|
19499
19981
|
try {
|
|
19500
19982
|
return execFileSync2("which", [config2.executable], { encoding: "utf-8" }).trim();
|
|
19501
19983
|
} catch {
|
|
19502
19984
|
}
|
|
19503
19985
|
for (const fallback of config2.executableFallbacks ?? []) {
|
|
19504
19986
|
const resolved = fallback.replace(/^~/, process.env.HOME ?? "");
|
|
19505
|
-
if (
|
|
19987
|
+
if (existsSync19(resolved)) return resolved;
|
|
19506
19988
|
}
|
|
19507
19989
|
return config2.executable;
|
|
19508
19990
|
}
|
|
@@ -19628,7 +20110,7 @@ function configToRunner(config2) {
|
|
|
19628
20110
|
prepareMcpInjection() {
|
|
19629
20111
|
return [];
|
|
19630
20112
|
},
|
|
19631
|
-
getSkillPath: () =>
|
|
20113
|
+
getSkillPath: () => join21(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
19632
20114
|
};
|
|
19633
20115
|
}
|
|
19634
20116
|
function loadRunnerConfig(filePath) {
|
|
@@ -19641,14 +20123,14 @@ function loadRunnerConfig(filePath) {
|
|
|
19641
20123
|
}
|
|
19642
20124
|
}
|
|
19643
20125
|
function loadAllRunnerConfigs() {
|
|
19644
|
-
if (!
|
|
19645
|
-
|
|
20126
|
+
if (!existsSync19(RUNNERS_PATH)) {
|
|
20127
|
+
mkdirSync9(RUNNERS_PATH, { recursive: true });
|
|
19646
20128
|
return [];
|
|
19647
20129
|
}
|
|
19648
|
-
const files =
|
|
20130
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19649
20131
|
const configs = [];
|
|
19650
20132
|
for (const file of files) {
|
|
19651
|
-
const config2 = loadRunnerConfig(
|
|
20133
|
+
const config2 = loadRunnerConfig(join21(RUNNERS_PATH, file));
|
|
19652
20134
|
if (config2) configs.push(config2);
|
|
19653
20135
|
}
|
|
19654
20136
|
return configs;
|
|
@@ -19669,16 +20151,16 @@ function registerConfigRunners() {
|
|
|
19669
20151
|
return count;
|
|
19670
20152
|
}
|
|
19671
20153
|
function watchRunnerConfigs(onChange) {
|
|
19672
|
-
if (!
|
|
20154
|
+
if (!existsSync19(RUNNERS_PATH)) return;
|
|
19673
20155
|
for (const prev of watchedFiles) {
|
|
19674
|
-
if (!
|
|
20156
|
+
if (!existsSync19(prev)) {
|
|
19675
20157
|
unwatchFile(prev);
|
|
19676
20158
|
watchedFiles.delete(prev);
|
|
19677
20159
|
}
|
|
19678
20160
|
}
|
|
19679
|
-
const files =
|
|
20161
|
+
const files = readdirSync9(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
19680
20162
|
for (const file of files) {
|
|
19681
|
-
const fullPath =
|
|
20163
|
+
const fullPath = join21(RUNNERS_PATH, file);
|
|
19682
20164
|
if (watchedFiles.has(fullPath)) continue;
|
|
19683
20165
|
watchedFiles.add(fullPath);
|
|
19684
20166
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -20076,6 +20558,7 @@ var init_telegram2 = __esm({
|
|
|
20076
20558
|
{ command: "summarizer", description: "Configure session summarization model" },
|
|
20077
20559
|
// Permissions & tools
|
|
20078
20560
|
{ command: "permissions", description: "Permission mode (yolo/safe/readonly/plan)" },
|
|
20561
|
+
{ command: "mode", description: "Execution gate (approved/yolo)" },
|
|
20079
20562
|
{ command: "tools", description: "Configure which tools the agent can use" },
|
|
20080
20563
|
{ command: "verbose", description: "Tool visibility (off/normal/verbose)" },
|
|
20081
20564
|
{ command: "cwd", description: "Set or show working directory" },
|
|
@@ -20512,19 +20995,19 @@ var init_telegram2 = __esm({
|
|
|
20512
20995
|
});
|
|
20513
20996
|
|
|
20514
20997
|
// src/skills/bootstrap.ts
|
|
20515
|
-
import { existsSync as
|
|
20998
|
+
import { existsSync as existsSync20 } from "fs";
|
|
20516
20999
|
import { readdir as readdir6, readFile as readFile8, writeFile as writeFile5, copyFile } from "fs/promises";
|
|
20517
|
-
import { join as
|
|
21000
|
+
import { join as join22, dirname as dirname4 } from "path";
|
|
20518
21001
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20519
21002
|
async function copyAgentManifestSkills() {
|
|
20520
|
-
if (!
|
|
21003
|
+
if (!existsSync20(PKG_SKILLS)) return;
|
|
20521
21004
|
try {
|
|
20522
21005
|
const entries = await readdir6(PKG_SKILLS, { withFileTypes: true });
|
|
20523
21006
|
for (const entry of entries) {
|
|
20524
21007
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
20525
|
-
const src =
|
|
20526
|
-
const dest =
|
|
20527
|
-
if (
|
|
21008
|
+
const src = join22(PKG_SKILLS, entry.name);
|
|
21009
|
+
const dest = join22(SKILLS_PATH, entry.name);
|
|
21010
|
+
if (existsSync20(dest)) continue;
|
|
20528
21011
|
await copyFile(src, dest);
|
|
20529
21012
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
20530
21013
|
}
|
|
@@ -20534,8 +21017,8 @@ async function copyAgentManifestSkills() {
|
|
|
20534
21017
|
}
|
|
20535
21018
|
async function bootstrapSkills() {
|
|
20536
21019
|
await copyAgentManifestSkills();
|
|
20537
|
-
const usmDir =
|
|
20538
|
-
if (
|
|
21020
|
+
const usmDir = join22(SKILLS_PATH, USM_DIR_NAME);
|
|
21021
|
+
if (existsSync20(usmDir)) return;
|
|
20539
21022
|
try {
|
|
20540
21023
|
const entries = await readdir6(SKILLS_PATH);
|
|
20541
21024
|
const dirs = entries.filter((e) => !e.startsWith("."));
|
|
@@ -20557,8 +21040,8 @@ async function bootstrapSkills() {
|
|
|
20557
21040
|
}
|
|
20558
21041
|
}
|
|
20559
21042
|
async function patchUsmForCcClaw(usmDir) {
|
|
20560
|
-
const skillPath =
|
|
20561
|
-
if (!
|
|
21043
|
+
const skillPath = join22(usmDir, "SKILL.md");
|
|
21044
|
+
if (!existsSync20(skillPath)) return;
|
|
20562
21045
|
try {
|
|
20563
21046
|
let content = await readFile8(skillPath, "utf-8");
|
|
20564
21047
|
let patched = false;
|
|
@@ -20603,8 +21086,8 @@ var init_bootstrap = __esm({
|
|
|
20603
21086
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
20604
21087
|
USM_DIR_NAME = "universal-skills-manager";
|
|
20605
21088
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
20606
|
-
PKG_ROOT =
|
|
20607
|
-
PKG_SKILLS =
|
|
21089
|
+
PKG_ROOT = join22(dirname4(fileURLToPath2(import.meta.url)), "..", "..");
|
|
21090
|
+
PKG_SKILLS = join22(PKG_ROOT, "skills");
|
|
20608
21091
|
}
|
|
20609
21092
|
});
|
|
20610
21093
|
|
|
@@ -20826,13 +21309,13 @@ __export(ai_skill_exports, {
|
|
|
20826
21309
|
generateAiSkill: () => generateAiSkill,
|
|
20827
21310
|
installAiSkill: () => installAiSkill
|
|
20828
21311
|
});
|
|
20829
|
-
import { existsSync as
|
|
20830
|
-
import { join as
|
|
21312
|
+
import { existsSync as existsSync21, writeFileSync as writeFileSync7, mkdirSync as mkdirSync10 } from "fs";
|
|
21313
|
+
import { join as join23 } from "path";
|
|
20831
21314
|
import { homedir as homedir7 } from "os";
|
|
20832
21315
|
function generateAiSkill() {
|
|
20833
21316
|
const version = VERSION;
|
|
20834
21317
|
let systemState = "";
|
|
20835
|
-
if (
|
|
21318
|
+
if (existsSync21(DB_PATH)) {
|
|
20836
21319
|
try {
|
|
20837
21320
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = (init_store5(), __toCommonJS(store_exports5));
|
|
20838
21321
|
const readDb = openDatabaseReadOnly2();
|
|
@@ -21236,10 +21719,10 @@ function installAiSkill() {
|
|
|
21236
21719
|
const failed = [];
|
|
21237
21720
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
21238
21721
|
for (const dir of dirs) {
|
|
21239
|
-
const skillDir =
|
|
21240
|
-
const skillPath =
|
|
21722
|
+
const skillDir = join23(dir, "cc-claw-cli");
|
|
21723
|
+
const skillPath = join23(skillDir, "SKILL.md");
|
|
21241
21724
|
try {
|
|
21242
|
-
|
|
21725
|
+
mkdirSync10(skillDir, { recursive: true });
|
|
21243
21726
|
writeFileSync7(skillPath, skill, "utf-8");
|
|
21244
21727
|
installed.push(skillPath);
|
|
21245
21728
|
} catch {
|
|
@@ -21256,11 +21739,11 @@ var init_ai_skill = __esm({
|
|
|
21256
21739
|
init_paths();
|
|
21257
21740
|
init_version();
|
|
21258
21741
|
BACKEND_SKILL_DIRS2 = {
|
|
21259
|
-
"cc-claw": [
|
|
21260
|
-
claude: [
|
|
21261
|
-
gemini: [
|
|
21262
|
-
codex: [
|
|
21263
|
-
cursor: [
|
|
21742
|
+
"cc-claw": [join23(homedir7(), ".cc-claw", "workspace", "skills")],
|
|
21743
|
+
claude: [join23(homedir7(), ".claude", "skills")],
|
|
21744
|
+
gemini: [join23(homedir7(), ".gemini", "skills")],
|
|
21745
|
+
codex: [join23(homedir7(), ".agents", "skills")],
|
|
21746
|
+
cursor: [join23(homedir7(), ".cursor", "skills"), join23(homedir7(), ".cursor", "skills-cursor")]
|
|
21264
21747
|
};
|
|
21265
21748
|
}
|
|
21266
21749
|
});
|
|
@@ -21270,23 +21753,23 @@ var index_exports = {};
|
|
|
21270
21753
|
__export(index_exports, {
|
|
21271
21754
|
main: () => main
|
|
21272
21755
|
});
|
|
21273
|
-
import { mkdirSync as
|
|
21274
|
-
import { join as
|
|
21756
|
+
import { mkdirSync as mkdirSync11, existsSync as existsSync22, renameSync as renameSync2, statSync as statSync6, readFileSync as readFileSync12 } from "fs";
|
|
21757
|
+
import { join as join24 } from "path";
|
|
21275
21758
|
import dotenv from "dotenv";
|
|
21276
21759
|
function migrateLayout() {
|
|
21277
21760
|
const moves = [
|
|
21278
|
-
[
|
|
21279
|
-
[
|
|
21280
|
-
[
|
|
21281
|
-
[
|
|
21282
|
-
[
|
|
21283
|
-
[
|
|
21284
|
-
[
|
|
21761
|
+
[join24(CC_CLAW_HOME, "cc-claw.db"), join24(DATA_PATH, "cc-claw.db")],
|
|
21762
|
+
[join24(CC_CLAW_HOME, "cc-claw.db-shm"), join24(DATA_PATH, "cc-claw.db-shm")],
|
|
21763
|
+
[join24(CC_CLAW_HOME, "cc-claw.db-wal"), join24(DATA_PATH, "cc-claw.db-wal")],
|
|
21764
|
+
[join24(CC_CLAW_HOME, "cc-claw.log"), join24(LOGS_PATH, "cc-claw.log")],
|
|
21765
|
+
[join24(CC_CLAW_HOME, "cc-claw.log.1"), join24(LOGS_PATH, "cc-claw.log.1")],
|
|
21766
|
+
[join24(CC_CLAW_HOME, "cc-claw.error.log"), join24(LOGS_PATH, "cc-claw.error.log")],
|
|
21767
|
+
[join24(CC_CLAW_HOME, "cc-claw.error.log.1"), join24(LOGS_PATH, "cc-claw.error.log.1")]
|
|
21285
21768
|
];
|
|
21286
21769
|
for (const [from, to] of moves) {
|
|
21287
|
-
if (
|
|
21770
|
+
if (existsSync22(from) && !existsSync22(to)) {
|
|
21288
21771
|
try {
|
|
21289
|
-
|
|
21772
|
+
renameSync2(from, to);
|
|
21290
21773
|
} catch {
|
|
21291
21774
|
}
|
|
21292
21775
|
}
|
|
@@ -21295,11 +21778,11 @@ function migrateLayout() {
|
|
|
21295
21778
|
function rotateLogs() {
|
|
21296
21779
|
for (const file of [LOG_PATH, ERROR_LOG_PATH]) {
|
|
21297
21780
|
try {
|
|
21298
|
-
const { size } =
|
|
21781
|
+
const { size } = statSync6(file);
|
|
21299
21782
|
if (size > LOG_MAX_BYTES) {
|
|
21300
21783
|
const archivePath = `${file}.1`;
|
|
21301
21784
|
try {
|
|
21302
|
-
|
|
21785
|
+
renameSync2(file, archivePath);
|
|
21303
21786
|
} catch {
|
|
21304
21787
|
}
|
|
21305
21788
|
log(`[cc-claw] Rotated ${file} (was ${(size / 1024 / 1024).toFixed(1)}MB)`);
|
|
@@ -21347,6 +21830,12 @@ async function main() {
|
|
|
21347
21830
|
}
|
|
21348
21831
|
setBootTime();
|
|
21349
21832
|
log("[cc-claw] Database initialized (sessions preserved for resume)");
|
|
21833
|
+
try {
|
|
21834
|
+
const { migrateAllSlots: migrateAllSlots2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
21835
|
+
migrateAllSlots2(CC_CLAW_HOME);
|
|
21836
|
+
} catch (err) {
|
|
21837
|
+
warn(`[cc-claw] Slot symlink migration failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
21838
|
+
}
|
|
21350
21839
|
if (process.env.TELEGRAM_BOT_TOKEN) {
|
|
21351
21840
|
channelRegistry.register(new TelegramChannel());
|
|
21352
21841
|
}
|
|
@@ -21423,11 +21912,11 @@ async function main() {
|
|
|
21423
21912
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
21424
21913
|
try {
|
|
21425
21914
|
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(
|
|
21915
|
+
const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync18 } = await import("fs");
|
|
21916
|
+
const { join: join30 } = await import("path");
|
|
21917
|
+
const skillDir = join30(SKILLS_PATH, "cc-claw-cli");
|
|
21918
|
+
mkdirSync18(skillDir, { recursive: true });
|
|
21919
|
+
writeFileSync12(join30(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
21431
21920
|
log("[cc-claw] AI skill updated");
|
|
21432
21921
|
} catch {
|
|
21433
21922
|
}
|
|
@@ -21500,10 +21989,10 @@ var init_index = __esm({
|
|
|
21500
21989
|
init_health3();
|
|
21501
21990
|
init_image_gen();
|
|
21502
21991
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
21503
|
-
if (!
|
|
21992
|
+
if (!existsSync22(dir)) mkdirSync11(dir, { recursive: true });
|
|
21504
21993
|
}
|
|
21505
21994
|
migrateLayout();
|
|
21506
|
-
if (
|
|
21995
|
+
if (existsSync22(ENV_PATH)) {
|
|
21507
21996
|
dotenv.config({ path: ENV_PATH });
|
|
21508
21997
|
} else {
|
|
21509
21998
|
console.error(`[cc-claw] Config not found at ${ENV_PATH} \u2014 run 'cc-claw setup' first`);
|
|
@@ -21524,12 +22013,12 @@ __export(api_client_exports, {
|
|
|
21524
22013
|
apiPost: () => apiPost,
|
|
21525
22014
|
isDaemonRunning: () => isDaemonRunning
|
|
21526
22015
|
});
|
|
21527
|
-
import { readFileSync as readFileSync13, existsSync as
|
|
22016
|
+
import { readFileSync as readFileSync13, existsSync as existsSync23 } from "fs";
|
|
21528
22017
|
import { request as httpRequest, Agent } from "http";
|
|
21529
22018
|
function getToken() {
|
|
21530
22019
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
21531
22020
|
try {
|
|
21532
|
-
if (
|
|
22021
|
+
if (existsSync23(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
21533
22022
|
} catch {
|
|
21534
22023
|
}
|
|
21535
22024
|
return null;
|
|
@@ -21628,10 +22117,10 @@ __export(service_exports, {
|
|
|
21628
22117
|
serviceStatus: () => serviceStatus,
|
|
21629
22118
|
uninstallService: () => uninstallService
|
|
21630
22119
|
});
|
|
21631
|
-
import { existsSync as
|
|
22120
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync12, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
|
|
21632
22121
|
import { execFileSync as execFileSync3, execSync as execSync6 } from "child_process";
|
|
21633
22122
|
import { homedir as homedir8, platform } from "os";
|
|
21634
|
-
import { join as
|
|
22123
|
+
import { join as join25, dirname as dirname5 } from "path";
|
|
21635
22124
|
function xmlEscape(s) {
|
|
21636
22125
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
21637
22126
|
}
|
|
@@ -21640,23 +22129,23 @@ function resolveExecutable2(name) {
|
|
|
21640
22129
|
return execFileSync3("which", [name], { encoding: "utf-8" }).trim();
|
|
21641
22130
|
} catch {
|
|
21642
22131
|
const fallback = process.argv[1];
|
|
21643
|
-
if (fallback &&
|
|
22132
|
+
if (fallback && existsSync24(fallback)) return fallback;
|
|
21644
22133
|
throw new Error(`Cannot find '${name}' executable. Install globally: npm install -g cc-claw`);
|
|
21645
22134
|
}
|
|
21646
22135
|
}
|
|
21647
22136
|
function getPathDirs() {
|
|
21648
|
-
const nodeBin =
|
|
22137
|
+
const nodeBin = dirname5(process.execPath);
|
|
21649
22138
|
const home = homedir8();
|
|
21650
22139
|
const dirs = /* @__PURE__ */ new Set([
|
|
21651
22140
|
nodeBin,
|
|
21652
|
-
|
|
22141
|
+
join25(home, ".local", "bin"),
|
|
21653
22142
|
"/usr/local/bin",
|
|
21654
22143
|
"/usr/bin",
|
|
21655
22144
|
"/bin"
|
|
21656
22145
|
]);
|
|
21657
22146
|
try {
|
|
21658
22147
|
const prefix = execSync6("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
21659
|
-
if (prefix) dirs.add(
|
|
22148
|
+
if (prefix) dirs.add(join25(prefix, "bin"));
|
|
21660
22149
|
} catch {
|
|
21661
22150
|
}
|
|
21662
22151
|
return [...dirs].join(":");
|
|
@@ -21714,10 +22203,10 @@ function generatePlist() {
|
|
|
21714
22203
|
</plist>`;
|
|
21715
22204
|
}
|
|
21716
22205
|
function installMacOS() {
|
|
21717
|
-
const agentsDir =
|
|
21718
|
-
if (!
|
|
21719
|
-
if (!
|
|
21720
|
-
if (
|
|
22206
|
+
const agentsDir = dirname5(PLIST_PATH);
|
|
22207
|
+
if (!existsSync24(agentsDir)) mkdirSync12(agentsDir, { recursive: true });
|
|
22208
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
|
|
22209
|
+
if (existsSync24(PLIST_PATH)) {
|
|
21721
22210
|
try {
|
|
21722
22211
|
execFileSync3("launchctl", ["unload", PLIST_PATH]);
|
|
21723
22212
|
} catch {
|
|
@@ -21729,7 +22218,7 @@ function installMacOS() {
|
|
|
21729
22218
|
console.log(" Service loaded and starting.");
|
|
21730
22219
|
}
|
|
21731
22220
|
function uninstallMacOS() {
|
|
21732
|
-
if (!
|
|
22221
|
+
if (!existsSync24(PLIST_PATH)) {
|
|
21733
22222
|
console.log(" No service found to uninstall.");
|
|
21734
22223
|
return;
|
|
21735
22224
|
}
|
|
@@ -21804,8 +22293,8 @@ WantedBy=default.target
|
|
|
21804
22293
|
`;
|
|
21805
22294
|
}
|
|
21806
22295
|
function installLinux() {
|
|
21807
|
-
if (!
|
|
21808
|
-
if (!
|
|
22296
|
+
if (!existsSync24(SYSTEMD_DIR)) mkdirSync12(SYSTEMD_DIR, { recursive: true });
|
|
22297
|
+
if (!existsSync24(LOGS_PATH)) mkdirSync12(LOGS_PATH, { recursive: true });
|
|
21809
22298
|
writeFileSync8(UNIT_PATH, generateUnit());
|
|
21810
22299
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
21811
22300
|
execFileSync3("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -21814,7 +22303,7 @@ function installLinux() {
|
|
|
21814
22303
|
console.log(" Service enabled and started.");
|
|
21815
22304
|
}
|
|
21816
22305
|
function uninstallLinux() {
|
|
21817
|
-
if (!
|
|
22306
|
+
if (!existsSync24(UNIT_PATH)) {
|
|
21818
22307
|
console.log(" No service found to uninstall.");
|
|
21819
22308
|
return;
|
|
21820
22309
|
}
|
|
@@ -21839,7 +22328,7 @@ function statusLinux() {
|
|
|
21839
22328
|
}
|
|
21840
22329
|
}
|
|
21841
22330
|
function installService() {
|
|
21842
|
-
if (!
|
|
22331
|
+
if (!existsSync24(join25(CC_CLAW_HOME, ".env"))) {
|
|
21843
22332
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
21844
22333
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
21845
22334
|
process.exitCode = 1;
|
|
@@ -21868,9 +22357,9 @@ var init_service = __esm({
|
|
|
21868
22357
|
"use strict";
|
|
21869
22358
|
init_paths();
|
|
21870
22359
|
PLIST_LABEL = "com.cc-claw";
|
|
21871
|
-
PLIST_PATH =
|
|
21872
|
-
SYSTEMD_DIR =
|
|
21873
|
-
UNIT_PATH =
|
|
22360
|
+
PLIST_PATH = join25(homedir8(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
22361
|
+
SYSTEMD_DIR = join25(homedir8(), ".config", "systemd", "user");
|
|
22362
|
+
UNIT_PATH = join25(SYSTEMD_DIR, "cc-claw.service");
|
|
21874
22363
|
}
|
|
21875
22364
|
});
|
|
21876
22365
|
|
|
@@ -22067,7 +22556,7 @@ var status_exports = {};
|
|
|
22067
22556
|
__export(status_exports, {
|
|
22068
22557
|
statusCommand: () => statusCommand
|
|
22069
22558
|
});
|
|
22070
|
-
import { existsSync as
|
|
22559
|
+
import { existsSync as existsSync25, statSync as statSync7 } from "fs";
|
|
22071
22560
|
async function statusCommand(globalOpts, localOpts) {
|
|
22072
22561
|
try {
|
|
22073
22562
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22107,7 +22596,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
22107
22596
|
const cwdRow = readDb.prepare("SELECT cwd FROM chat_cwd WHERE chat_id = ?").get(chatId);
|
|
22108
22597
|
const voiceRow = readDb.prepare("SELECT enabled FROM chat_voice WHERE chat_id = ?").get(chatId);
|
|
22109
22598
|
const usageRow = readDb.prepare("SELECT * FROM chat_usage WHERE chat_id = ?").get(chatId);
|
|
22110
|
-
const dbStat =
|
|
22599
|
+
const dbStat = existsSync25(DB_PATH) ? statSync7(DB_PATH) : null;
|
|
22111
22600
|
let daemonRunning = false;
|
|
22112
22601
|
let daemonInfo = {};
|
|
22113
22602
|
try {
|
|
@@ -22196,12 +22685,12 @@ var doctor_exports = {};
|
|
|
22196
22685
|
__export(doctor_exports, {
|
|
22197
22686
|
doctorCommand: () => doctorCommand
|
|
22198
22687
|
});
|
|
22199
|
-
import { existsSync as
|
|
22688
|
+
import { existsSync as existsSync26, statSync as statSync8, accessSync, constants } from "fs";
|
|
22200
22689
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22201
22690
|
async function doctorCommand(globalOpts, localOpts) {
|
|
22202
22691
|
const checks = [];
|
|
22203
|
-
if (
|
|
22204
|
-
const size =
|
|
22692
|
+
if (existsSync26(DB_PATH)) {
|
|
22693
|
+
const size = statSync8(DB_PATH).size;
|
|
22205
22694
|
checks.push({ name: "Database", status: "ok", message: `${DB_PATH} (${(size / 1024).toFixed(0)}KB)` });
|
|
22206
22695
|
try {
|
|
22207
22696
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
@@ -22230,7 +22719,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22230
22719
|
} else {
|
|
22231
22720
|
checks.push({ name: "Database", status: "error", message: `Not found at ${DB_PATH}`, fix: "cc-claw setup" });
|
|
22232
22721
|
}
|
|
22233
|
-
if (
|
|
22722
|
+
if (existsSync26(ENV_PATH)) {
|
|
22234
22723
|
checks.push({ name: "Environment", status: "ok", message: `.env loaded` });
|
|
22235
22724
|
} else {
|
|
22236
22725
|
checks.push({ name: "Environment", status: "error", message: "No .env found", fix: "cc-claw setup" });
|
|
@@ -22285,7 +22774,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22285
22774
|
} catch {
|
|
22286
22775
|
}
|
|
22287
22776
|
const tokenPath = `${DATA_PATH}/api-token`;
|
|
22288
|
-
if (
|
|
22777
|
+
if (existsSync26(tokenPath)) {
|
|
22289
22778
|
try {
|
|
22290
22779
|
accessSync(tokenPath, constants.R_OK);
|
|
22291
22780
|
checks.push({ name: "API token", status: "ok", message: "token file readable" });
|
|
@@ -22310,7 +22799,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
22310
22799
|
}
|
|
22311
22800
|
} catch {
|
|
22312
22801
|
}
|
|
22313
|
-
if (
|
|
22802
|
+
if (existsSync26(ERROR_LOG_PATH)) {
|
|
22314
22803
|
try {
|
|
22315
22804
|
const { readFileSync: readFileSync22 } = await import("fs");
|
|
22316
22805
|
const logContent = readFileSync22(ERROR_LOG_PATH, "utf-8");
|
|
@@ -22436,10 +22925,10 @@ var logs_exports = {};
|
|
|
22436
22925
|
__export(logs_exports, {
|
|
22437
22926
|
logsCommand: () => logsCommand
|
|
22438
22927
|
});
|
|
22439
|
-
import { existsSync as
|
|
22928
|
+
import { existsSync as existsSync27, readFileSync as readFileSync16, watchFile as watchFile2, unwatchFile as unwatchFile2 } from "fs";
|
|
22440
22929
|
async function logsCommand(opts) {
|
|
22441
22930
|
const logFile = opts.error ? ERROR_LOG_PATH : LOG_PATH;
|
|
22442
|
-
if (!
|
|
22931
|
+
if (!existsSync27(logFile)) {
|
|
22443
22932
|
outputError("LOG_NOT_FOUND", `Log file not found: ${logFile}`);
|
|
22444
22933
|
process.exit(1);
|
|
22445
22934
|
}
|
|
@@ -22491,11 +22980,11 @@ __export(gemini_exports, {
|
|
|
22491
22980
|
geminiReorder: () => geminiReorder,
|
|
22492
22981
|
geminiRotation: () => geminiRotation
|
|
22493
22982
|
});
|
|
22494
|
-
import { existsSync as
|
|
22495
|
-
import { join as
|
|
22983
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync13, writeFileSync as writeFileSync9, readFileSync as readFileSync17, chmodSync } from "fs";
|
|
22984
|
+
import { join as join26 } from "path";
|
|
22496
22985
|
import { createInterface as createInterface5 } from "readline";
|
|
22497
22986
|
function requireDb() {
|
|
22498
|
-
if (!
|
|
22987
|
+
if (!existsSync28(DB_PATH)) {
|
|
22499
22988
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22500
22989
|
process.exit(1);
|
|
22501
22990
|
}
|
|
@@ -22520,8 +23009,8 @@ async function resolveSlotId(idOrLabel) {
|
|
|
22520
23009
|
function resolveOAuthEmail(configHome) {
|
|
22521
23010
|
if (!configHome) return null;
|
|
22522
23011
|
try {
|
|
22523
|
-
const accountsPath =
|
|
22524
|
-
if (!
|
|
23012
|
+
const accountsPath = join26(configHome, ".gemini", "google_accounts.json");
|
|
23013
|
+
if (!existsSync28(accountsPath)) return null;
|
|
22525
23014
|
const accounts = JSON.parse(readFileSync17(accountsPath, "utf-8"));
|
|
22526
23015
|
return accounts.active || null;
|
|
22527
23016
|
} catch {
|
|
@@ -22604,14 +23093,14 @@ async function geminiAddKey(globalOpts, opts) {
|
|
|
22604
23093
|
}
|
|
22605
23094
|
async function geminiAddAccount(globalOpts, opts) {
|
|
22606
23095
|
await requireWriteDb();
|
|
22607
|
-
const slotsDir =
|
|
22608
|
-
if (!
|
|
23096
|
+
const slotsDir = join26(CC_CLAW_HOME, "gemini-slots");
|
|
23097
|
+
if (!existsSync28(slotsDir)) mkdirSync13(slotsDir, { recursive: true });
|
|
22609
23098
|
const { addGeminiSlot: addGeminiSlot2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
22610
23099
|
const tempId = Date.now();
|
|
22611
|
-
const slotDir =
|
|
22612
|
-
|
|
22613
|
-
|
|
22614
|
-
writeFileSync9(
|
|
23100
|
+
const slotDir = join26(slotsDir, `slot-${tempId}`);
|
|
23101
|
+
mkdirSync13(slotDir, { recursive: true, mode: 448 });
|
|
23102
|
+
mkdirSync13(join26(slotDir, ".gemini"), { recursive: true });
|
|
23103
|
+
writeFileSync9(join26(slotDir, ".gemini", "settings.json"), JSON.stringify({
|
|
22615
23104
|
security: { auth: { selectedType: "oauth-personal" } }
|
|
22616
23105
|
}, null, 2));
|
|
22617
23106
|
console.log("");
|
|
@@ -22628,8 +23117,8 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22628
23117
|
});
|
|
22629
23118
|
} catch {
|
|
22630
23119
|
}
|
|
22631
|
-
const oauthPath =
|
|
22632
|
-
if (!
|
|
23120
|
+
const oauthPath = join26(slotDir, ".gemini", "oauth_creds.json");
|
|
23121
|
+
if (!existsSync28(oauthPath)) {
|
|
22633
23122
|
console.log(error2("\n No OAuth credentials found. Sign-in may have failed."));
|
|
22634
23123
|
console.log(" The slot directory is preserved at: " + slotDir);
|
|
22635
23124
|
console.log(" Re-run: cc-claw gemini add-account\n");
|
|
@@ -22637,7 +23126,7 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22637
23126
|
}
|
|
22638
23127
|
let accountEmail = "unknown";
|
|
22639
23128
|
try {
|
|
22640
|
-
const accounts = JSON.parse(__require("fs").readFileSync(
|
|
23129
|
+
const accounts = JSON.parse(__require("fs").readFileSync(join26(slotDir, ".gemini", "google_accounts.json"), "utf-8"));
|
|
22641
23130
|
accountEmail = accounts.active || accountEmail;
|
|
22642
23131
|
} catch {
|
|
22643
23132
|
}
|
|
@@ -22648,6 +23137,13 @@ async function geminiAddAccount(globalOpts, opts) {
|
|
|
22648
23137
|
configHome: slotDir,
|
|
22649
23138
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22650
23139
|
});
|
|
23140
|
+
try {
|
|
23141
|
+
const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
23142
|
+
const primaryDir = getPrimaryDir2("gemini");
|
|
23143
|
+
if (primaryDir) setupSlotSymlinks2("gemini", slotDir, primaryDir);
|
|
23144
|
+
} catch (err) {
|
|
23145
|
+
console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
|
|
23146
|
+
}
|
|
22651
23147
|
output(
|
|
22652
23148
|
{ id, type: "oauth", label: opts.label || accountEmail, configHome: slotDir },
|
|
22653
23149
|
() => success(`
|
|
@@ -22749,11 +23245,11 @@ __export(backend_cmd_factory_exports, {
|
|
|
22749
23245
|
makeReorder: () => makeReorder,
|
|
22750
23246
|
registerBackendSlotCommands: () => registerBackendSlotCommands
|
|
22751
23247
|
});
|
|
22752
|
-
import { existsSync as
|
|
22753
|
-
import { join as
|
|
23248
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync14, readFileSync as readFileSync18 } from "fs";
|
|
23249
|
+
import { join as join27 } from "path";
|
|
22754
23250
|
import { createInterface as createInterface6 } from "readline";
|
|
22755
23251
|
function requireDb2() {
|
|
22756
|
-
if (!
|
|
23252
|
+
if (!existsSync29(DB_PATH)) {
|
|
22757
23253
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
22758
23254
|
process.exit(1);
|
|
22759
23255
|
}
|
|
@@ -22842,11 +23338,11 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22842
23338
|
process.exit(1);
|
|
22843
23339
|
}
|
|
22844
23340
|
await requireWriteDb2();
|
|
22845
|
-
const slotsDir =
|
|
22846
|
-
if (!
|
|
23341
|
+
const slotsDir = join27(CC_CLAW_HOME, config2.slotsSubdir);
|
|
23342
|
+
if (!existsSync29(slotsDir)) mkdirSync14(slotsDir, { recursive: true });
|
|
22847
23343
|
const tempId = Date.now();
|
|
22848
|
-
const slotDir =
|
|
22849
|
-
|
|
23344
|
+
const slotDir = join27(slotsDir, `slot-${tempId}`);
|
|
23345
|
+
mkdirSync14(slotDir, { recursive: true, mode: 448 });
|
|
22850
23346
|
if (config2.preSetup) config2.preSetup(slotDir);
|
|
22851
23347
|
console.log("");
|
|
22852
23348
|
console.log(` Opening ${displayName} CLI for sign-in...`);
|
|
@@ -22884,6 +23380,13 @@ function makeAddAccount(backend2, displayName) {
|
|
|
22884
23380
|
configHome: slotDir,
|
|
22885
23381
|
priority: opts.priority ? parseInt(opts.priority, 10) : 0
|
|
22886
23382
|
});
|
|
23383
|
+
try {
|
|
23384
|
+
const { setupSlotSymlinks: setupSlotSymlinks2, getPrimaryDir: getPrimaryDir2 } = await Promise.resolve().then(() => (init_symlink_manager(), symlink_manager_exports));
|
|
23385
|
+
const primaryDir = getPrimaryDir2(backend2);
|
|
23386
|
+
if (primaryDir) setupSlotSymlinks2(backend2, slotDir, primaryDir);
|
|
23387
|
+
} catch (err) {
|
|
23388
|
+
console.log(warning(` Warning: could not set up state symlinks \u2014 ${err instanceof Error ? err.message : String(err)}`));
|
|
23389
|
+
}
|
|
22887
23390
|
output(
|
|
22888
23391
|
{ id, type: "oauth", backend: backend2, label: accountLabel, configHome: slotDir },
|
|
22889
23392
|
() => success(`Added ${displayName} subscription slot #${id} (${accountLabel})`)
|
|
@@ -23007,12 +23510,12 @@ var init_backend_cmd_factory = __esm({
|
|
|
23007
23510
|
envValue: (slotDir) => slotDir,
|
|
23008
23511
|
envOverrides: { ANTHROPIC_API_KEY: void 0 },
|
|
23009
23512
|
preSetup: (slotDir) => {
|
|
23010
|
-
|
|
23513
|
+
mkdirSync14(join27(slotDir, ".claude"), { recursive: true });
|
|
23011
23514
|
},
|
|
23012
23515
|
verifyCredentials: (slotDir) => {
|
|
23013
|
-
const claudeJson =
|
|
23014
|
-
const claudeJsonNested =
|
|
23015
|
-
if (
|
|
23516
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23517
|
+
const claudeJsonNested = join27(slotDir, ".claude", ".claude.json");
|
|
23518
|
+
if (existsSync29(claudeJson)) {
|
|
23016
23519
|
try {
|
|
23017
23520
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
23018
23521
|
return Boolean(data.oauthAccount);
|
|
@@ -23020,7 +23523,7 @@ var init_backend_cmd_factory = __esm({
|
|
|
23020
23523
|
return false;
|
|
23021
23524
|
}
|
|
23022
23525
|
}
|
|
23023
|
-
if (
|
|
23526
|
+
if (existsSync29(claudeJsonNested)) {
|
|
23024
23527
|
try {
|
|
23025
23528
|
const data = JSON.parse(readFileSync18(claudeJsonNested, "utf-8"));
|
|
23026
23529
|
return Boolean(data.oauthAccount);
|
|
@@ -23043,8 +23546,8 @@ var init_backend_cmd_factory = __esm({
|
|
|
23043
23546
|
} catch {
|
|
23044
23547
|
}
|
|
23045
23548
|
try {
|
|
23046
|
-
const claudeJson =
|
|
23047
|
-
if (
|
|
23549
|
+
const claudeJson = join27(slotDir, ".claude.json");
|
|
23550
|
+
if (existsSync29(claudeJson)) {
|
|
23048
23551
|
const data = JSON.parse(readFileSync18(claudeJson, "utf-8"));
|
|
23049
23552
|
if (data.oauthAccount?.emailAddress) return data.oauthAccount.emailAddress;
|
|
23050
23553
|
}
|
|
@@ -23060,11 +23563,11 @@ var init_backend_cmd_factory = __esm({
|
|
|
23060
23563
|
envValue: (slotDir) => slotDir,
|
|
23061
23564
|
envOverrides: { OPENAI_API_KEY: void 0 },
|
|
23062
23565
|
verifyCredentials: (slotDir) => {
|
|
23063
|
-
return
|
|
23566
|
+
return existsSync29(join27(slotDir, "auth.json"));
|
|
23064
23567
|
},
|
|
23065
23568
|
extractLabel: (slotDir) => {
|
|
23066
23569
|
try {
|
|
23067
|
-
const authData = JSON.parse(readFileSync18(
|
|
23570
|
+
const authData = JSON.parse(readFileSync18(join27(slotDir, "auth.json"), "utf-8"));
|
|
23068
23571
|
if (authData.email) return authData.email;
|
|
23069
23572
|
if (authData.account_name) return authData.account_name;
|
|
23070
23573
|
if (authData.user?.email) return authData.user.email;
|
|
@@ -23084,12 +23587,12 @@ __export(backend_exports, {
|
|
|
23084
23587
|
backendList: () => backendList,
|
|
23085
23588
|
backendSet: () => backendSet
|
|
23086
23589
|
});
|
|
23087
|
-
import { existsSync as
|
|
23590
|
+
import { existsSync as existsSync30 } from "fs";
|
|
23088
23591
|
async function backendList(globalOpts) {
|
|
23089
23592
|
const { getAvailableAdapters: getAvailableAdapters3 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23090
23593
|
const chatId = resolveChatId(globalOpts);
|
|
23091
23594
|
let activeBackend = null;
|
|
23092
|
-
if (
|
|
23595
|
+
if (existsSync30(DB_PATH)) {
|
|
23093
23596
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23094
23597
|
const readDb = openDatabaseReadOnly2();
|
|
23095
23598
|
try {
|
|
@@ -23120,7 +23623,7 @@ async function backendList(globalOpts) {
|
|
|
23120
23623
|
}
|
|
23121
23624
|
async function backendGet(globalOpts) {
|
|
23122
23625
|
const chatId = resolveChatId(globalOpts);
|
|
23123
|
-
if (!
|
|
23626
|
+
if (!existsSync30(DB_PATH)) {
|
|
23124
23627
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23125
23628
|
process.exit(1);
|
|
23126
23629
|
}
|
|
@@ -23164,13 +23667,13 @@ __export(model_exports, {
|
|
|
23164
23667
|
modelList: () => modelList,
|
|
23165
23668
|
modelSet: () => modelSet
|
|
23166
23669
|
});
|
|
23167
|
-
import { existsSync as
|
|
23670
|
+
import { existsSync as existsSync31 } from "fs";
|
|
23168
23671
|
async function modelList(globalOpts) {
|
|
23169
23672
|
const chatId = resolveChatId(globalOpts);
|
|
23170
23673
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23171
23674
|
const { getAdapter: getAdapter4, getAllAdapters: getAllAdapters5 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
23172
23675
|
let backendId = "claude";
|
|
23173
|
-
if (
|
|
23676
|
+
if (existsSync31(DB_PATH)) {
|
|
23174
23677
|
const readDb = openDatabaseReadOnly2();
|
|
23175
23678
|
try {
|
|
23176
23679
|
const row = readDb.prepare("SELECT backend FROM chat_backend WHERE chat_id = ?").get(chatId);
|
|
@@ -23203,7 +23706,7 @@ async function modelList(globalOpts) {
|
|
|
23203
23706
|
}
|
|
23204
23707
|
async function modelGet(globalOpts) {
|
|
23205
23708
|
const chatId = resolveChatId(globalOpts);
|
|
23206
|
-
if (!
|
|
23709
|
+
if (!existsSync31(DB_PATH)) {
|
|
23207
23710
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23208
23711
|
process.exit(1);
|
|
23209
23712
|
}
|
|
@@ -23247,9 +23750,9 @@ __export(memory_exports2, {
|
|
|
23247
23750
|
memoryList: () => memoryList,
|
|
23248
23751
|
memorySearch: () => memorySearch
|
|
23249
23752
|
});
|
|
23250
|
-
import { existsSync as
|
|
23753
|
+
import { existsSync as existsSync32 } from "fs";
|
|
23251
23754
|
async function memoryList(globalOpts) {
|
|
23252
|
-
if (!
|
|
23755
|
+
if (!existsSync32(DB_PATH)) {
|
|
23253
23756
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23254
23757
|
process.exit(1);
|
|
23255
23758
|
}
|
|
@@ -23273,7 +23776,7 @@ async function memoryList(globalOpts) {
|
|
|
23273
23776
|
});
|
|
23274
23777
|
}
|
|
23275
23778
|
async function memorySearch(globalOpts, query) {
|
|
23276
|
-
if (!
|
|
23779
|
+
if (!existsSync32(DB_PATH)) {
|
|
23277
23780
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23278
23781
|
process.exit(1);
|
|
23279
23782
|
}
|
|
@@ -23295,7 +23798,7 @@ async function memorySearch(globalOpts, query) {
|
|
|
23295
23798
|
});
|
|
23296
23799
|
}
|
|
23297
23800
|
async function memoryHistory(globalOpts, opts) {
|
|
23298
|
-
if (!
|
|
23801
|
+
if (!existsSync32(DB_PATH)) {
|
|
23299
23802
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23300
23803
|
process.exit(1);
|
|
23301
23804
|
}
|
|
@@ -23343,7 +23846,7 @@ __export(cron_exports2, {
|
|
|
23343
23846
|
cronList: () => cronList,
|
|
23344
23847
|
cronRuns: () => cronRuns
|
|
23345
23848
|
});
|
|
23346
|
-
import { existsSync as
|
|
23849
|
+
import { existsSync as existsSync33 } from "fs";
|
|
23347
23850
|
function parseFallbacks(raw) {
|
|
23348
23851
|
return raw.slice(0, 3).map((f) => {
|
|
23349
23852
|
const [backend2, ...rest] = f.split(":");
|
|
@@ -23364,7 +23867,7 @@ function parseAndValidateTimeout(raw) {
|
|
|
23364
23867
|
return val;
|
|
23365
23868
|
}
|
|
23366
23869
|
async function cronList(globalOpts) {
|
|
23367
|
-
if (!
|
|
23870
|
+
if (!existsSync33(DB_PATH)) {
|
|
23368
23871
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23369
23872
|
process.exit(1);
|
|
23370
23873
|
}
|
|
@@ -23402,7 +23905,7 @@ async function cronList(globalOpts) {
|
|
|
23402
23905
|
});
|
|
23403
23906
|
}
|
|
23404
23907
|
async function cronHealth(globalOpts) {
|
|
23405
|
-
if (!
|
|
23908
|
+
if (!existsSync33(DB_PATH)) {
|
|
23406
23909
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23407
23910
|
process.exit(1);
|
|
23408
23911
|
}
|
|
@@ -23561,7 +24064,7 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
23561
24064
|
}
|
|
23562
24065
|
}
|
|
23563
24066
|
async function cronRuns(globalOpts, jobId, opts) {
|
|
23564
|
-
if (!
|
|
24067
|
+
if (!existsSync33(DB_PATH)) {
|
|
23565
24068
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23566
24069
|
process.exit(1);
|
|
23567
24070
|
}
|
|
@@ -23608,9 +24111,9 @@ __export(agents_exports, {
|
|
|
23608
24111
|
runnersList: () => runnersList,
|
|
23609
24112
|
tasksList: () => tasksList
|
|
23610
24113
|
});
|
|
23611
|
-
import { existsSync as
|
|
24114
|
+
import { existsSync as existsSync34 } from "fs";
|
|
23612
24115
|
async function agentsList(globalOpts) {
|
|
23613
|
-
if (!
|
|
24116
|
+
if (!existsSync34(DB_PATH)) {
|
|
23614
24117
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23615
24118
|
process.exit(1);
|
|
23616
24119
|
}
|
|
@@ -23641,7 +24144,7 @@ async function agentsList(globalOpts) {
|
|
|
23641
24144
|
});
|
|
23642
24145
|
}
|
|
23643
24146
|
async function tasksList(globalOpts) {
|
|
23644
|
-
if (!
|
|
24147
|
+
if (!existsSync34(DB_PATH)) {
|
|
23645
24148
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
23646
24149
|
process.exit(1);
|
|
23647
24150
|
}
|
|
@@ -23769,18 +24272,18 @@ __export(db_exports, {
|
|
|
23769
24272
|
dbPath: () => dbPath,
|
|
23770
24273
|
dbStats: () => dbStats
|
|
23771
24274
|
});
|
|
23772
|
-
import { existsSync as
|
|
23773
|
-
import { dirname as
|
|
24275
|
+
import { existsSync as existsSync35, statSync as statSync9, copyFileSync as copyFileSync3, mkdirSync as mkdirSync15 } from "fs";
|
|
24276
|
+
import { dirname as dirname6 } from "path";
|
|
23774
24277
|
async function dbStats(globalOpts) {
|
|
23775
|
-
if (!
|
|
24278
|
+
if (!existsSync35(DB_PATH)) {
|
|
23776
24279
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23777
24280
|
process.exit(1);
|
|
23778
24281
|
}
|
|
23779
24282
|
const { openDatabaseReadOnly: openDatabaseReadOnly2 } = await Promise.resolve().then(() => (init_store5(), store_exports5));
|
|
23780
24283
|
const readDb = openDatabaseReadOnly2();
|
|
23781
|
-
const mainSize =
|
|
24284
|
+
const mainSize = statSync9(DB_PATH).size;
|
|
23782
24285
|
const walPath = DB_PATH + "-wal";
|
|
23783
|
-
const walSize =
|
|
24286
|
+
const walSize = existsSync35(walPath) ? statSync9(walPath).size : 0;
|
|
23784
24287
|
const tableNames = readDb.prepare(
|
|
23785
24288
|
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '%_fts%' ORDER BY name"
|
|
23786
24289
|
).all();
|
|
@@ -23814,17 +24317,17 @@ async function dbPath(globalOpts) {
|
|
|
23814
24317
|
output({ path: DB_PATH }, (d) => d.path);
|
|
23815
24318
|
}
|
|
23816
24319
|
async function dbBackup(globalOpts, destPath) {
|
|
23817
|
-
if (!
|
|
24320
|
+
if (!existsSync35(DB_PATH)) {
|
|
23818
24321
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
23819
24322
|
process.exit(1);
|
|
23820
24323
|
}
|
|
23821
24324
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
23822
24325
|
try {
|
|
23823
|
-
|
|
23824
|
-
|
|
24326
|
+
mkdirSync15(dirname6(dest), { recursive: true });
|
|
24327
|
+
copyFileSync3(DB_PATH, dest);
|
|
23825
24328
|
const walPath = DB_PATH + "-wal";
|
|
23826
|
-
if (
|
|
23827
|
-
output({ path: dest, sizeBytes:
|
|
24329
|
+
if (existsSync35(walPath)) copyFileSync3(walPath, dest + "-wal");
|
|
24330
|
+
output({ path: dest, sizeBytes: statSync9(dest).size }, (d) => {
|
|
23828
24331
|
const b = d;
|
|
23829
24332
|
return `
|
|
23830
24333
|
${success("Backup created:")} ${b.path} (${(b.sizeBytes / 1024).toFixed(0)}KB)
|
|
@@ -23852,9 +24355,9 @@ __export(usage_exports, {
|
|
|
23852
24355
|
usageCost: () => usageCost,
|
|
23853
24356
|
usageTokens: () => usageTokens
|
|
23854
24357
|
});
|
|
23855
|
-
import { existsSync as
|
|
24358
|
+
import { existsSync as existsSync36 } from "fs";
|
|
23856
24359
|
function ensureDb() {
|
|
23857
|
-
if (!
|
|
24360
|
+
if (!existsSync36(DB_PATH)) {
|
|
23858
24361
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
23859
24362
|
process.exit(1);
|
|
23860
24363
|
}
|
|
@@ -24044,9 +24547,9 @@ __export(config_exports2, {
|
|
|
24044
24547
|
configList: () => configList,
|
|
24045
24548
|
configSet: () => configSet
|
|
24046
24549
|
});
|
|
24047
|
-
import { existsSync as
|
|
24550
|
+
import { existsSync as existsSync37, readFileSync as readFileSync19 } from "fs";
|
|
24048
24551
|
async function configList(globalOpts) {
|
|
24049
|
-
if (!
|
|
24552
|
+
if (!existsSync37(DB_PATH)) {
|
|
24050
24553
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24051
24554
|
process.exit(1);
|
|
24052
24555
|
}
|
|
@@ -24080,7 +24583,7 @@ async function configGet(globalOpts, key) {
|
|
|
24080
24583
|
outputError("INVALID_KEY", `Unknown config key "${key}". Valid keys: ${RUNTIME_KEYS.join(", ")}`);
|
|
24081
24584
|
process.exit(1);
|
|
24082
24585
|
}
|
|
24083
|
-
if (!
|
|
24586
|
+
if (!existsSync37(DB_PATH)) {
|
|
24084
24587
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24085
24588
|
process.exit(1);
|
|
24086
24589
|
}
|
|
@@ -24126,7 +24629,7 @@ async function configSet(globalOpts, key, value) {
|
|
|
24126
24629
|
}
|
|
24127
24630
|
}
|
|
24128
24631
|
async function configEnv(_globalOpts) {
|
|
24129
|
-
if (!
|
|
24632
|
+
if (!existsSync37(ENV_PATH)) {
|
|
24130
24633
|
outputError("ENV_NOT_FOUND", `No .env file at ${ENV_PATH}. Run cc-claw setup.`);
|
|
24131
24634
|
process.exit(1);
|
|
24132
24635
|
}
|
|
@@ -24180,9 +24683,9 @@ __export(session_exports, {
|
|
|
24180
24683
|
sessionGet: () => sessionGet,
|
|
24181
24684
|
sessionNew: () => sessionNew
|
|
24182
24685
|
});
|
|
24183
|
-
import { existsSync as
|
|
24686
|
+
import { existsSync as existsSync38 } from "fs";
|
|
24184
24687
|
async function sessionGet(globalOpts) {
|
|
24185
|
-
if (!
|
|
24688
|
+
if (!existsSync38(DB_PATH)) {
|
|
24186
24689
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24187
24690
|
process.exit(1);
|
|
24188
24691
|
}
|
|
@@ -24243,9 +24746,9 @@ __export(permissions_exports, {
|
|
|
24243
24746
|
verboseGet: () => verboseGet,
|
|
24244
24747
|
verboseSet: () => verboseSet
|
|
24245
24748
|
});
|
|
24246
|
-
import { existsSync as
|
|
24749
|
+
import { existsSync as existsSync39 } from "fs";
|
|
24247
24750
|
function ensureDb2() {
|
|
24248
|
-
if (!
|
|
24751
|
+
if (!existsSync39(DB_PATH)) {
|
|
24249
24752
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24250
24753
|
process.exit(1);
|
|
24251
24754
|
}
|
|
@@ -24392,9 +24895,9 @@ __export(cwd_exports, {
|
|
|
24392
24895
|
cwdGet: () => cwdGet,
|
|
24393
24896
|
cwdSet: () => cwdSet
|
|
24394
24897
|
});
|
|
24395
|
-
import { existsSync as
|
|
24898
|
+
import { existsSync as existsSync40 } from "fs";
|
|
24396
24899
|
async function cwdGet(globalOpts) {
|
|
24397
|
-
if (!
|
|
24900
|
+
if (!existsSync40(DB_PATH)) {
|
|
24398
24901
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24399
24902
|
process.exit(1);
|
|
24400
24903
|
}
|
|
@@ -24456,9 +24959,9 @@ __export(voice_exports, {
|
|
|
24456
24959
|
voiceGet: () => voiceGet,
|
|
24457
24960
|
voiceSet: () => voiceSet
|
|
24458
24961
|
});
|
|
24459
|
-
import { existsSync as
|
|
24962
|
+
import { existsSync as existsSync41 } from "fs";
|
|
24460
24963
|
async function voiceGet(globalOpts) {
|
|
24461
|
-
if (!
|
|
24964
|
+
if (!existsSync41(DB_PATH)) {
|
|
24462
24965
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24463
24966
|
process.exit(1);
|
|
24464
24967
|
}
|
|
@@ -24507,9 +25010,9 @@ __export(heartbeat_exports, {
|
|
|
24507
25010
|
heartbeatGet: () => heartbeatGet,
|
|
24508
25011
|
heartbeatSet: () => heartbeatSet
|
|
24509
25012
|
});
|
|
24510
|
-
import { existsSync as
|
|
25013
|
+
import { existsSync as existsSync42 } from "fs";
|
|
24511
25014
|
async function heartbeatGet(globalOpts) {
|
|
24512
|
-
if (!
|
|
25015
|
+
if (!existsSync42(DB_PATH)) {
|
|
24513
25016
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24514
25017
|
process.exit(1);
|
|
24515
25018
|
}
|
|
@@ -24618,9 +25121,9 @@ __export(summarizer_exports, {
|
|
|
24618
25121
|
summarizerGet: () => summarizerGet,
|
|
24619
25122
|
summarizerSet: () => summarizerSet
|
|
24620
25123
|
});
|
|
24621
|
-
import { existsSync as
|
|
25124
|
+
import { existsSync as existsSync43 } from "fs";
|
|
24622
25125
|
async function summarizerGet(globalOpts) {
|
|
24623
|
-
if (!
|
|
25126
|
+
if (!existsSync43(DB_PATH)) {
|
|
24624
25127
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24625
25128
|
process.exit(1);
|
|
24626
25129
|
}
|
|
@@ -24664,9 +25167,9 @@ __export(thinking_exports, {
|
|
|
24664
25167
|
thinkingGet: () => thinkingGet,
|
|
24665
25168
|
thinkingSet: () => thinkingSet
|
|
24666
25169
|
});
|
|
24667
|
-
import { existsSync as
|
|
25170
|
+
import { existsSync as existsSync44 } from "fs";
|
|
24668
25171
|
async function thinkingGet(globalOpts) {
|
|
24669
|
-
if (!
|
|
25172
|
+
if (!existsSync44(DB_PATH)) {
|
|
24670
25173
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24671
25174
|
process.exit(1);
|
|
24672
25175
|
}
|
|
@@ -24710,9 +25213,9 @@ __export(chats_exports, {
|
|
|
24710
25213
|
chatsList: () => chatsList,
|
|
24711
25214
|
chatsRemoveAlias: () => chatsRemoveAlias
|
|
24712
25215
|
});
|
|
24713
|
-
import { existsSync as
|
|
25216
|
+
import { existsSync as existsSync45 } from "fs";
|
|
24714
25217
|
async function chatsList(_globalOpts) {
|
|
24715
|
-
if (!
|
|
25218
|
+
if (!existsSync45(DB_PATH)) {
|
|
24716
25219
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24717
25220
|
process.exit(1);
|
|
24718
25221
|
}
|
|
@@ -24840,9 +25343,9 @@ var mcps_exports2 = {};
|
|
|
24840
25343
|
__export(mcps_exports2, {
|
|
24841
25344
|
mcpsList: () => mcpsList
|
|
24842
25345
|
});
|
|
24843
|
-
import { existsSync as
|
|
25346
|
+
import { existsSync as existsSync46 } from "fs";
|
|
24844
25347
|
async function mcpsList(_globalOpts) {
|
|
24845
|
-
if (!
|
|
25348
|
+
if (!existsSync46(DB_PATH)) {
|
|
24846
25349
|
outputError("DB_NOT_FOUND", "Database not found.");
|
|
24847
25350
|
process.exit(1);
|
|
24848
25351
|
}
|
|
@@ -24879,11 +25382,11 @@ __export(chat_exports2, {
|
|
|
24879
25382
|
chatSend: () => chatSend
|
|
24880
25383
|
});
|
|
24881
25384
|
import { request as httpRequest2 } from "http";
|
|
24882
|
-
import { readFileSync as readFileSync20, existsSync as
|
|
25385
|
+
import { readFileSync as readFileSync20, existsSync as existsSync47 } from "fs";
|
|
24883
25386
|
function getToken2() {
|
|
24884
25387
|
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
24885
25388
|
try {
|
|
24886
|
-
if (
|
|
25389
|
+
if (existsSync47(TOKEN_PATH2)) return readFileSync20(TOKEN_PATH2, "utf-8").trim();
|
|
24887
25390
|
} catch {
|
|
24888
25391
|
}
|
|
24889
25392
|
return null;
|
|
@@ -25162,8 +25665,8 @@ var completion_exports = {};
|
|
|
25162
25665
|
__export(completion_exports, {
|
|
25163
25666
|
completionCommand: () => completionCommand
|
|
25164
25667
|
});
|
|
25165
|
-
import { writeFileSync as writeFileSync10, mkdirSync as
|
|
25166
|
-
import { join as
|
|
25668
|
+
import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync16 } from "fs";
|
|
25669
|
+
import { join as join28 } from "path";
|
|
25167
25670
|
import { homedir as homedir9 } from "os";
|
|
25168
25671
|
async function completionCommand(opts) {
|
|
25169
25672
|
const shell = opts.shell ?? detectShell();
|
|
@@ -25179,10 +25682,10 @@ async function completionCommand(opts) {
|
|
|
25179
25682
|
process.exit(1);
|
|
25180
25683
|
}
|
|
25181
25684
|
if (opts.install) {
|
|
25182
|
-
const dir =
|
|
25183
|
-
|
|
25685
|
+
const dir = join28(homedir9(), ".config", "cc-claw", "completions");
|
|
25686
|
+
mkdirSync16(dir, { recursive: true });
|
|
25184
25687
|
const filename = shell === "zsh" ? "_cc-claw" : shell === "fish" ? "cc-claw.fish" : "cc-claw.bash";
|
|
25185
|
-
const filepath =
|
|
25688
|
+
const filepath = join28(dir, filename);
|
|
25186
25689
|
writeFileSync10(filepath, script, "utf-8");
|
|
25187
25690
|
console.log(`\u2713 Completion script written to ${filepath}
|
|
25188
25691
|
`);
|
|
@@ -25353,9 +25856,9 @@ __export(evolve_exports2, {
|
|
|
25353
25856
|
evolveStatus: () => evolveStatus,
|
|
25354
25857
|
evolveUndo: () => evolveUndo
|
|
25355
25858
|
});
|
|
25356
|
-
import { existsSync as
|
|
25859
|
+
import { existsSync as existsSync48 } from "fs";
|
|
25357
25860
|
function ensureDb3() {
|
|
25358
|
-
if (!
|
|
25861
|
+
if (!existsSync48(DB_PATH)) {
|
|
25359
25862
|
outputError("DB_NOT_FOUND", "Database not found. Run cc-claw setup first.");
|
|
25360
25863
|
process.exit(1);
|
|
25361
25864
|
}
|
|
@@ -25771,10 +26274,10 @@ var init_evolve3 = __esm({
|
|
|
25771
26274
|
|
|
25772
26275
|
// src/setup.ts
|
|
25773
26276
|
var setup_exports = {};
|
|
25774
|
-
import { existsSync as
|
|
26277
|
+
import { existsSync as existsSync49, writeFileSync as writeFileSync11, readFileSync as readFileSync21, copyFileSync as copyFileSync4, mkdirSync as mkdirSync17, statSync as statSync10 } from "fs";
|
|
25775
26278
|
import { execFileSync as execFileSync5 } from "child_process";
|
|
25776
26279
|
import { createInterface as createInterface8 } from "readline";
|
|
25777
|
-
import { join as
|
|
26280
|
+
import { join as join29 } from "path";
|
|
25778
26281
|
function divider2() {
|
|
25779
26282
|
console.log(dim("\u2500".repeat(55)));
|
|
25780
26283
|
}
|
|
@@ -25849,10 +26352,10 @@ async function setup() {
|
|
|
25849
26352
|
}
|
|
25850
26353
|
console.log("");
|
|
25851
26354
|
for (const dir of [CC_CLAW_HOME, DATA_PATH, LOGS_PATH, SKILLS_PATH, RUNNERS_PATH, AGENTS_PATH]) {
|
|
25852
|
-
if (!
|
|
26355
|
+
if (!existsSync49(dir)) mkdirSync17(dir, { recursive: true });
|
|
25853
26356
|
}
|
|
25854
26357
|
const env = {};
|
|
25855
|
-
const envSource =
|
|
26358
|
+
const envSource = existsSync49(ENV_PATH) ? ENV_PATH : existsSync49(".env") ? ".env" : null;
|
|
25856
26359
|
if (envSource) {
|
|
25857
26360
|
console.log(yellow(` Found existing config at ${envSource} \u2014 your values will be preserved`));
|
|
25858
26361
|
console.log(yellow(" unless you enter new ones. Just press Enter to keep existing values.\n"));
|
|
@@ -25862,13 +26365,13 @@ async function setup() {
|
|
|
25862
26365
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
25863
26366
|
}
|
|
25864
26367
|
}
|
|
25865
|
-
const cwdDb =
|
|
25866
|
-
if (
|
|
25867
|
-
const { size } =
|
|
26368
|
+
const cwdDb = join29(process.cwd(), "cc-claw.db");
|
|
26369
|
+
if (existsSync49(cwdDb) && !existsSync49(DB_PATH)) {
|
|
26370
|
+
const { size } = statSync10(cwdDb);
|
|
25868
26371
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
25869
26372
|
const migrate = await confirm("Copy database to ~/.cc-claw/? (preserves memories & history)", true);
|
|
25870
26373
|
if (migrate) {
|
|
25871
|
-
|
|
26374
|
+
copyFileSync4(cwdDb, DB_PATH);
|
|
25872
26375
|
console.log(green(` Database copied to ${DB_PATH}`));
|
|
25873
26376
|
}
|
|
25874
26377
|
console.log("");
|