cc-claw 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +253 -160
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -48,7 +48,7 @@ var VERSION;
|
|
|
48
48
|
var init_version = __esm({
|
|
49
49
|
"src/version.ts"() {
|
|
50
50
|
"use strict";
|
|
51
|
-
VERSION = true ? "0.4.
|
|
51
|
+
VERSION = true ? "0.4.7" : (() => {
|
|
52
52
|
try {
|
|
53
53
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
54
54
|
} catch {
|
|
@@ -358,10 +358,10 @@ function claimTask(db3, taskId, agentId) {
|
|
|
358
358
|
).get(...blockedBy);
|
|
359
359
|
if (incomplete.count > 0) return false;
|
|
360
360
|
}
|
|
361
|
-
db3.prepare(
|
|
361
|
+
const result = db3.prepare(
|
|
362
362
|
"UPDATE agent_tasks SET assignee = ?, status = 'in_progress' WHERE id = ? AND status = 'pending'"
|
|
363
363
|
).run(agentId, taskId);
|
|
364
|
-
return
|
|
364
|
+
return result.changes > 0;
|
|
365
365
|
}
|
|
366
366
|
function sendInboxMessage(db3, opts) {
|
|
367
367
|
const result = db3.prepare(`
|
|
@@ -2490,6 +2490,7 @@ var init_store4 = __esm({
|
|
|
2490
2490
|
});
|
|
2491
2491
|
|
|
2492
2492
|
// src/env.ts
|
|
2493
|
+
import { homedir as homedir2 } from "os";
|
|
2493
2494
|
function stripProxyVars(env) {
|
|
2494
2495
|
for (const key of PROXY_KEYS) delete env[key];
|
|
2495
2496
|
}
|
|
@@ -2498,7 +2499,7 @@ function buildBaseEnv(extraOverrides) {
|
|
|
2498
2499
|
for (const [k, v] of Object.entries(process.env)) {
|
|
2499
2500
|
if (v !== void 0) env[k] = v;
|
|
2500
2501
|
}
|
|
2501
|
-
if (!env.HOME) env.HOME =
|
|
2502
|
+
if (!env.HOME) env.HOME = homedir2();
|
|
2502
2503
|
stripProxyVars(env);
|
|
2503
2504
|
if (extraOverrides) Object.assign(env, extraOverrides);
|
|
2504
2505
|
return env;
|
|
@@ -3208,8 +3209,9 @@ async function injectMemoryContext(userMessage) {
|
|
|
3208
3209
|
seen.add(mem.id);
|
|
3209
3210
|
combinedMemories.push(mem);
|
|
3210
3211
|
}
|
|
3212
|
+
if (combinedMemories.length >= FINAL_TOP_K_MEMORIES) break;
|
|
3211
3213
|
}
|
|
3212
|
-
combinedSessions = ftsSessions;
|
|
3214
|
+
combinedSessions = ftsSessions.slice(0, FINAL_TOP_K_SESSIONS);
|
|
3213
3215
|
}
|
|
3214
3216
|
if (combinedMemories.length === 0 && combinedSessions.length === 0) return null;
|
|
3215
3217
|
const lines = [];
|
|
@@ -4000,8 +4002,10 @@ function spawnAgentProcess(runner, opts, callbacks) {
|
|
|
4000
4002
|
const child = spawn2(runner.getExecutablePath(), args, {
|
|
4001
4003
|
env: buildSpawnEnv(runner, opts.isSubAgent),
|
|
4002
4004
|
cwd: opts.cwd,
|
|
4003
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
4005
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4006
|
+
detached: true
|
|
4004
4007
|
});
|
|
4008
|
+
child.unref();
|
|
4005
4009
|
let resultText = "";
|
|
4006
4010
|
let usage2;
|
|
4007
4011
|
if (child.stdout) {
|
|
@@ -4024,7 +4028,14 @@ function spawnAgentProcess(runner, opts, callbacks) {
|
|
|
4024
4028
|
if (event.usage) usage2 = event.usage;
|
|
4025
4029
|
callbacks.onResult?.(resultText, usage2);
|
|
4026
4030
|
if (runner.shouldKillOnResult()) {
|
|
4027
|
-
|
|
4031
|
+
try {
|
|
4032
|
+
if (child.pid) process.kill(-child.pid, "SIGTERM");
|
|
4033
|
+
} catch {
|
|
4034
|
+
try {
|
|
4035
|
+
child.kill("SIGTERM");
|
|
4036
|
+
} catch {
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4028
4039
|
}
|
|
4029
4040
|
}
|
|
4030
4041
|
}
|
|
@@ -4104,7 +4115,7 @@ var init_cost = __esm({
|
|
|
4104
4115
|
// src/mcps/propagate.ts
|
|
4105
4116
|
import { execFile } from "child_process";
|
|
4106
4117
|
import { promisify } from "util";
|
|
4107
|
-
import { homedir as
|
|
4118
|
+
import { homedir as homedir3 } from "os";
|
|
4108
4119
|
async function discoverExistingMcps(runner) {
|
|
4109
4120
|
try {
|
|
4110
4121
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -4113,7 +4124,7 @@ async function discoverExistingMcps(runner) {
|
|
|
4113
4124
|
const result = await execFileAsync(exe, args, {
|
|
4114
4125
|
encoding: "utf-8",
|
|
4115
4126
|
env: runner.getEnv(),
|
|
4116
|
-
cwd:
|
|
4127
|
+
cwd: homedir3(),
|
|
4117
4128
|
timeout: 3e4
|
|
4118
4129
|
});
|
|
4119
4130
|
const stdout = typeof result === "string" ? result : Array.isArray(result) ? result[0] : result?.stdout ?? null;
|
|
@@ -4628,6 +4639,26 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
4628
4639
|
clearTimeout(timeoutTimers.get(agentId));
|
|
4629
4640
|
timeoutTimers.delete(agentId);
|
|
4630
4641
|
activeProcesses.delete(agentId);
|
|
4642
|
+
const crashedAgent = getAgent(db3, agentId);
|
|
4643
|
+
if (crashedAgent) {
|
|
4644
|
+
const mcpsCrashed = crashedAgent.mcpsAdded ? JSON.parse(crashedAgent.mcpsAdded) : [];
|
|
4645
|
+
if (mcpsCrashed.length > 0) {
|
|
4646
|
+
const runner2 = getRunner(crashedAgent.runnerId);
|
|
4647
|
+
if (runner2) {
|
|
4648
|
+
const cleanupFn = () => cleanupMcps(runner2, mcpsCrashed, db3, `agent:${agentId}`);
|
|
4649
|
+
if (runner2.capabilities.mcpInjection === "add-remove") {
|
|
4650
|
+
withRunnerLock(runner2.id, cleanupFn).catch((err) => {
|
|
4651
|
+
warn(`[orchestrator] MCP cleanup failed for crashed agent ${agentId.slice(0, 8)}:`, err);
|
|
4652
|
+
});
|
|
4653
|
+
} else {
|
|
4654
|
+
cleanupFn().catch((err) => {
|
|
4655
|
+
warn(`[orchestrator] MCP cleanup failed for crashed agent ${agentId.slice(0, 8)}:`, err);
|
|
4656
|
+
});
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
deleteMcpConfigFile(`cc-claw-${agentId.slice(0, 8)}`);
|
|
4661
|
+
}
|
|
4631
4662
|
sendInboxMessage(db3, {
|
|
4632
4663
|
orchestrationId: agent.orchestrationId,
|
|
4633
4664
|
toAgentId: "main",
|
|
@@ -4789,9 +4820,23 @@ function cancelAgent(agentId, reason = "user_cancelled") {
|
|
|
4789
4820
|
if (!agent) return false;
|
|
4790
4821
|
const proc = activeProcesses.get(agentId);
|
|
4791
4822
|
if (proc) {
|
|
4792
|
-
|
|
4823
|
+
try {
|
|
4824
|
+
if (proc.pid) process.kill(-proc.pid, "SIGTERM");
|
|
4825
|
+
} catch {
|
|
4826
|
+
try {
|
|
4827
|
+
proc.kill("SIGTERM");
|
|
4828
|
+
} catch {
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4793
4831
|
setTimeout(() => {
|
|
4794
|
-
|
|
4832
|
+
try {
|
|
4833
|
+
if (proc.pid) process.kill(-proc.pid, "SIGKILL");
|
|
4834
|
+
} catch {
|
|
4835
|
+
try {
|
|
4836
|
+
proc.kill("SIGKILL");
|
|
4837
|
+
} catch {
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4795
4840
|
}, 2e3);
|
|
4796
4841
|
}
|
|
4797
4842
|
updateAgentStatus(db3, agentId, "cancelled");
|
|
@@ -4836,7 +4881,14 @@ function cancelAllAgents(chatId, reason = "user_cancelled") {
|
|
|
4836
4881
|
}
|
|
4837
4882
|
function shutdownOrchestrator() {
|
|
4838
4883
|
for (const [agentId, proc] of activeProcesses) {
|
|
4839
|
-
|
|
4884
|
+
try {
|
|
4885
|
+
if (proc.pid) process.kill(-proc.pid, "SIGTERM");
|
|
4886
|
+
} catch {
|
|
4887
|
+
try {
|
|
4888
|
+
proc.kill("SIGTERM");
|
|
4889
|
+
} catch {
|
|
4890
|
+
}
|
|
4891
|
+
}
|
|
4840
4892
|
clearTimeout(timeoutTimers.get(agentId));
|
|
4841
4893
|
}
|
|
4842
4894
|
activeProcesses.clear();
|
|
@@ -5532,7 +5584,7 @@ function startDashboard() {
|
|
|
5532
5584
|
return jsonResponse(res, { error: "message and chatId required" }, 400);
|
|
5533
5585
|
}
|
|
5534
5586
|
const { askAgent: askAgent2 } = await Promise.resolve().then(() => (init_agent(), agent_exports));
|
|
5535
|
-
const { getMode: getMode2, getCwd: getCwd2, getModel:
|
|
5587
|
+
const { getMode: getMode2, getCwd: getCwd2, getModel: getModel2, addUsage: addUsage2, getBackend: getBackend2 } = await Promise.resolve().then(() => (init_store4(), store_exports3));
|
|
5536
5588
|
const { getAdapterForChat: getAdapterForChat2 } = await Promise.resolve().then(() => (init_backends(), backends_exports));
|
|
5537
5589
|
const chatId = body.chatId;
|
|
5538
5590
|
const PERM_LEVEL = { plan: 0, safe: 1, yolo: 2 };
|
|
@@ -5540,7 +5592,7 @@ function startDashboard() {
|
|
|
5540
5592
|
const requestedMode = body.mode ?? storedMode;
|
|
5541
5593
|
const mode = (PERM_LEVEL[requestedMode] ?? 2) <= (PERM_LEVEL[storedMode] ?? 2) ? requestedMode : storedMode;
|
|
5542
5594
|
const cwd = body.cwd ?? getCwd2(chatId);
|
|
5543
|
-
const model2 = body.model ??
|
|
5595
|
+
const model2 = body.model ?? getModel2(chatId) ?? (() => {
|
|
5544
5596
|
try {
|
|
5545
5597
|
return getAdapterForChat2(chatId).defaultModel;
|
|
5546
5598
|
} catch {
|
|
@@ -5696,8 +5748,8 @@ data: ${JSON.stringify(data)}
|
|
|
5696
5748
|
if (url.pathname === "/api/heartbeat/set" && req.method === "POST") {
|
|
5697
5749
|
try {
|
|
5698
5750
|
const body = JSON.parse(await readBody(req));
|
|
5699
|
-
const { setHeartbeatConfig:
|
|
5700
|
-
|
|
5751
|
+
const { setHeartbeatConfig: setHeartbeatConfig2 } = await Promise.resolve().then(() => (init_store4(), store_exports3));
|
|
5752
|
+
setHeartbeatConfig2(body.chatId, body);
|
|
5701
5753
|
return jsonResponse(res, { success: true });
|
|
5702
5754
|
} catch (err) {
|
|
5703
5755
|
return jsonResponse(res, { error: errorMessage(err) }, 400);
|
|
@@ -5998,14 +6050,21 @@ var init_server = __esm({
|
|
|
5998
6050
|
var agent_exports = {};
|
|
5999
6051
|
__export(agent_exports, {
|
|
6000
6052
|
askAgent: () => askAgent,
|
|
6001
|
-
isAgentActive: () => isAgentActive,
|
|
6002
6053
|
isChatBusy: () => isChatBusy,
|
|
6003
6054
|
stopAgent: () => stopAgent
|
|
6004
6055
|
});
|
|
6005
6056
|
import { spawn as spawn4 } from "child_process";
|
|
6006
6057
|
import { createInterface as createInterface3 } from "readline";
|
|
6007
|
-
|
|
6008
|
-
|
|
6058
|
+
function killProcessGroup(proc, signal = "SIGTERM") {
|
|
6059
|
+
try {
|
|
6060
|
+
if (proc.pid) process.kill(-proc.pid, signal);
|
|
6061
|
+
} catch {
|
|
6062
|
+
try {
|
|
6063
|
+
proc.kill(signal);
|
|
6064
|
+
} catch {
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6067
|
+
}
|
|
6009
6068
|
function withChatLock(chatId, fn) {
|
|
6010
6069
|
const prev = chatLocks.get(chatId) ?? Promise.resolve();
|
|
6011
6070
|
const isBlocked = activeChats.has(chatId);
|
|
@@ -6026,14 +6085,13 @@ function stopAgent(chatId) {
|
|
|
6026
6085
|
if (!state) return false;
|
|
6027
6086
|
state.cancelled = true;
|
|
6028
6087
|
if (state.process) {
|
|
6029
|
-
state.process
|
|
6030
|
-
state.killTimer = setTimeout(() =>
|
|
6088
|
+
killProcessGroup(state.process, "SIGTERM");
|
|
6089
|
+
state.killTimer = setTimeout(() => {
|
|
6090
|
+
if (state.process) killProcessGroup(state.process, "SIGKILL");
|
|
6091
|
+
}, 2e3);
|
|
6031
6092
|
}
|
|
6032
6093
|
return true;
|
|
6033
6094
|
}
|
|
6034
|
-
function isAgentActive(chatId) {
|
|
6035
|
-
return activeChats.has(chatId);
|
|
6036
|
-
}
|
|
6037
6095
|
function spawnQuery(adapter, config2, model2, cancelState, onStream, onToolAction, thinkingLevel, timeoutMs) {
|
|
6038
6096
|
const effectiveTimeout = timeoutMs ?? SPAWN_TIMEOUT_MS;
|
|
6039
6097
|
return new Promise((resolve, reject) => {
|
|
@@ -6044,21 +6102,18 @@ function spawnQuery(adapter, config2, model2, cancelState, onStream, onToolActio
|
|
|
6044
6102
|
const proc = spawn4(config2.executable, finalArgs, {
|
|
6045
6103
|
env,
|
|
6046
6104
|
stdio: ["ignore", "pipe", "pipe"],
|
|
6105
|
+
detached: true,
|
|
6047
6106
|
...config2.cwd ? { cwd: config2.cwd } : {}
|
|
6048
6107
|
});
|
|
6108
|
+
proc.unref();
|
|
6049
6109
|
cancelState.process = proc;
|
|
6050
6110
|
let timedOut = false;
|
|
6051
6111
|
let sigkillTimer;
|
|
6052
6112
|
const spawnTimeout = setTimeout(() => {
|
|
6053
6113
|
timedOut = true;
|
|
6054
6114
|
warn(`[agent] Spawn timeout after ${effectiveTimeout / 1e3}s for ${adapter.id} \u2014 killing process`);
|
|
6055
|
-
proc
|
|
6056
|
-
sigkillTimer = setTimeout(() =>
|
|
6057
|
-
try {
|
|
6058
|
-
proc.kill("SIGKILL");
|
|
6059
|
-
} catch {
|
|
6060
|
-
}
|
|
6061
|
-
}, 3e3);
|
|
6115
|
+
killProcessGroup(proc, "SIGTERM");
|
|
6116
|
+
sigkillTimer = setTimeout(() => killProcessGroup(proc, "SIGKILL"), 3e3);
|
|
6062
6117
|
}, effectiveTimeout);
|
|
6063
6118
|
let resultText = "";
|
|
6064
6119
|
let accumulatedText = "";
|
|
@@ -6146,7 +6201,7 @@ function spawnQuery(adapter, config2, model2, cancelState, onStream, onToolActio
|
|
|
6146
6201
|
rl2.close();
|
|
6147
6202
|
} catch {
|
|
6148
6203
|
}
|
|
6149
|
-
proc
|
|
6204
|
+
killProcessGroup(proc, "SIGTERM");
|
|
6150
6205
|
}
|
|
6151
6206
|
break;
|
|
6152
6207
|
}
|
|
@@ -6288,7 +6343,7 @@ function injectMcpConfig(adapterId, args, mcpConfigPath) {
|
|
|
6288
6343
|
if (!flag) return args;
|
|
6289
6344
|
return [...args, ...flag, mcpConfigPath];
|
|
6290
6345
|
}
|
|
6291
|
-
var
|
|
6346
|
+
var activeChats, chatLocks, SPAWN_TIMEOUT_MS, MCP_CONFIG_FLAG;
|
|
6292
6347
|
var init_agent = __esm({
|
|
6293
6348
|
"src/agent.ts"() {
|
|
6294
6349
|
"use strict";
|
|
@@ -6301,8 +6356,6 @@ var init_agent = __esm({
|
|
|
6301
6356
|
init_summarize();
|
|
6302
6357
|
init_server();
|
|
6303
6358
|
init_mcp_config();
|
|
6304
|
-
__filename2 = fileURLToPath2(import.meta.url);
|
|
6305
|
-
__dirname2 = dirname2(__filename2);
|
|
6306
6359
|
activeChats = /* @__PURE__ */ new Map();
|
|
6307
6360
|
chatLocks = /* @__PURE__ */ new Map();
|
|
6308
6361
|
SPAWN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
@@ -6384,7 +6437,7 @@ ${responseText.slice(0, 500)}`);
|
|
|
6384
6437
|
if (!cleanText) return true;
|
|
6385
6438
|
if (channelName === "telegram") {
|
|
6386
6439
|
const parsed = parseTelegramTarget(targetChatId);
|
|
6387
|
-
await channel.sendText(parsed.chatId, cleanText);
|
|
6440
|
+
await channel.sendText(parsed.chatId, cleanText, void 0, parsed.threadId);
|
|
6388
6441
|
} else {
|
|
6389
6442
|
await channel.sendText(targetChatId, cleanText);
|
|
6390
6443
|
}
|
|
@@ -6410,7 +6463,8 @@ async function deliverWebhook(job, responseText) {
|
|
|
6410
6463
|
description: job.description,
|
|
6411
6464
|
text: responseText,
|
|
6412
6465
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6413
|
-
})
|
|
6466
|
+
}),
|
|
6467
|
+
signal: AbortSignal.timeout(3e4)
|
|
6414
6468
|
});
|
|
6415
6469
|
if (!resp.ok) {
|
|
6416
6470
|
error(`[delivery] Webhook POST to ${url} failed: ${resp.status} ${resp.statusText}`);
|
|
@@ -6815,6 +6869,9 @@ async function executeJob(job) {
|
|
|
6815
6869
|
}
|
|
6816
6870
|
} finally {
|
|
6817
6871
|
runningJobs.delete(job.id);
|
|
6872
|
+
if (job.sessionType === "isolated" && job.thinking && job.thinking !== "auto") {
|
|
6873
|
+
clearThinkingLevel(`cron:${job.id}:${runId}`);
|
|
6874
|
+
}
|
|
6818
6875
|
}
|
|
6819
6876
|
}
|
|
6820
6877
|
async function runWithRetry(job, model2, runId, t0) {
|
|
@@ -6911,7 +6968,7 @@ var init_cron = __esm({
|
|
|
6911
6968
|
});
|
|
6912
6969
|
|
|
6913
6970
|
// src/agents/runners/wrap-backend.ts
|
|
6914
|
-
import { join as
|
|
6971
|
+
import { join as join7 } from "path";
|
|
6915
6972
|
function buildMcpCommands(backendId) {
|
|
6916
6973
|
const exe = backendId;
|
|
6917
6974
|
return {
|
|
@@ -6972,7 +7029,8 @@ function wrapBackendAdapter(adapter) {
|
|
|
6972
7029
|
sessionId: opts.sessionId,
|
|
6973
7030
|
permMode: opts.permMode ?? "plan",
|
|
6974
7031
|
allowedTools: opts.allowedTools ?? [],
|
|
6975
|
-
cwd: opts.cwd
|
|
7032
|
+
cwd: opts.cwd,
|
|
7033
|
+
model: opts.model
|
|
6976
7034
|
});
|
|
6977
7035
|
return config2.args;
|
|
6978
7036
|
},
|
|
@@ -7001,7 +7059,7 @@ function wrapBackendAdapter(adapter) {
|
|
|
7001
7059
|
const configPath = writeMcpConfigFile(server);
|
|
7002
7060
|
return ["--mcp-config", configPath];
|
|
7003
7061
|
},
|
|
7004
|
-
getSkillPath: () =>
|
|
7062
|
+
getSkillPath: () => join7(SKILLS_PATH, `agent-${adapter.id}.md`)
|
|
7005
7063
|
};
|
|
7006
7064
|
}
|
|
7007
7065
|
var BACKEND_CAPABILITIES;
|
|
@@ -7044,7 +7102,7 @@ var init_wrap_backend = __esm({
|
|
|
7044
7102
|
|
|
7045
7103
|
// src/agents/runners/config-loader.ts
|
|
7046
7104
|
import { readFileSync as readFileSync6, readdirSync as readdirSync4, existsSync as existsSync9, mkdirSync as mkdirSync4, watchFile, unwatchFile } from "fs";
|
|
7047
|
-
import { join as
|
|
7105
|
+
import { join as join8 } from "path";
|
|
7048
7106
|
import { execFileSync } from "child_process";
|
|
7049
7107
|
function resolveExecutable(config2) {
|
|
7050
7108
|
if (existsSync9(config2.executable)) return config2.executable;
|
|
@@ -7180,7 +7238,7 @@ function configToRunner(config2) {
|
|
|
7180
7238
|
prepareMcpInjection() {
|
|
7181
7239
|
return [];
|
|
7182
7240
|
},
|
|
7183
|
-
getSkillPath: () =>
|
|
7241
|
+
getSkillPath: () => join8(SKILLS_PATH, `agent-${config2.id}.md`)
|
|
7184
7242
|
};
|
|
7185
7243
|
}
|
|
7186
7244
|
function loadRunnerConfig(filePath) {
|
|
@@ -7200,7 +7258,7 @@ function loadAllRunnerConfigs() {
|
|
|
7200
7258
|
const files = readdirSync4(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
7201
7259
|
const configs = [];
|
|
7202
7260
|
for (const file of files) {
|
|
7203
|
-
const config2 = loadRunnerConfig(
|
|
7261
|
+
const config2 = loadRunnerConfig(join8(RUNNERS_PATH, file));
|
|
7204
7262
|
if (config2) configs.push(config2);
|
|
7205
7263
|
}
|
|
7206
7264
|
return configs;
|
|
@@ -7230,7 +7288,7 @@ function watchRunnerConfigs(onChange) {
|
|
|
7230
7288
|
}
|
|
7231
7289
|
const files = readdirSync4(RUNNERS_PATH).filter((f) => f.endsWith(".json"));
|
|
7232
7290
|
for (const file of files) {
|
|
7233
|
-
const fullPath =
|
|
7291
|
+
const fullPath = join8(RUNNERS_PATH, file);
|
|
7234
7292
|
if (watchedFiles.has(fullPath)) continue;
|
|
7235
7293
|
watchedFiles.add(fullPath);
|
|
7236
7294
|
watchFile(fullPath, { interval: 5e3 }, () => {
|
|
@@ -7571,6 +7629,8 @@ var init_telegram2 = __esm({
|
|
|
7571
7629
|
return;
|
|
7572
7630
|
}
|
|
7573
7631
|
const data = ctx.callbackQuery.data;
|
|
7632
|
+
await ctx.answerCallbackQuery().catch(() => {
|
|
7633
|
+
});
|
|
7574
7634
|
try {
|
|
7575
7635
|
for (const handler2 of this.callbackHandlers) {
|
|
7576
7636
|
await handler2(chatId, data, this);
|
|
@@ -7578,8 +7638,6 @@ var init_telegram2 = __esm({
|
|
|
7578
7638
|
} catch (err) {
|
|
7579
7639
|
error("[telegram] Callback handler error:", err);
|
|
7580
7640
|
}
|
|
7581
|
-
await ctx.answerCallbackQuery().catch(() => {
|
|
7582
|
-
});
|
|
7583
7641
|
});
|
|
7584
7642
|
this.bot.catch((err) => {
|
|
7585
7643
|
error("[telegram] Unhandled error:", err);
|
|
@@ -7599,11 +7657,12 @@ var init_telegram2 = __esm({
|
|
|
7599
7657
|
async sendTyping(chatId) {
|
|
7600
7658
|
await this.bot.api.sendChatAction(numericChatId(chatId), "typing");
|
|
7601
7659
|
}
|
|
7602
|
-
async sendText(chatId, text, parseMode) {
|
|
7660
|
+
async sendText(chatId, text, parseMode, threadId) {
|
|
7661
|
+
const threadOpts = threadId ? { message_thread_id: threadId } : {};
|
|
7603
7662
|
if (parseMode === "plain") {
|
|
7604
7663
|
const plainChunks = splitMessage(text);
|
|
7605
7664
|
for (const chunk of plainChunks) {
|
|
7606
|
-
await this.bot.api.sendMessage(numericChatId(chatId), chunk);
|
|
7665
|
+
await this.bot.api.sendMessage(numericChatId(chatId), chunk, { ...threadOpts });
|
|
7607
7666
|
}
|
|
7608
7667
|
return;
|
|
7609
7668
|
}
|
|
@@ -7612,12 +7671,14 @@ var init_telegram2 = __esm({
|
|
|
7612
7671
|
for (const chunk of chunks) {
|
|
7613
7672
|
try {
|
|
7614
7673
|
await this.bot.api.sendMessage(numericChatId(chatId), chunk, {
|
|
7615
|
-
parse_mode: "HTML"
|
|
7674
|
+
parse_mode: "HTML",
|
|
7675
|
+
...threadOpts
|
|
7616
7676
|
});
|
|
7617
7677
|
} catch {
|
|
7618
7678
|
await this.bot.api.sendMessage(
|
|
7619
7679
|
numericChatId(chatId),
|
|
7620
|
-
chunk.replace(/<[^>]+>/g, "")
|
|
7680
|
+
chunk.replace(/<[^>]+>/g, ""),
|
|
7681
|
+
{ ...threadOpts }
|
|
7621
7682
|
);
|
|
7622
7683
|
}
|
|
7623
7684
|
}
|
|
@@ -7642,7 +7703,9 @@ var init_telegram2 = __esm({
|
|
|
7642
7703
|
}
|
|
7643
7704
|
async sendTextReturningId(chatId, text, parseMode) {
|
|
7644
7705
|
try {
|
|
7645
|
-
const
|
|
7706
|
+
const formatted = parseMode === "html" ? text : parseMode === "plain" ? text : formatForTelegram(text);
|
|
7707
|
+
const opts = parseMode === "plain" ? {} : { parse_mode: "HTML" };
|
|
7708
|
+
const msg = await this.bot.api.sendMessage(numericChatId(chatId), formatted, opts);
|
|
7646
7709
|
return msg.message_id.toString();
|
|
7647
7710
|
} catch {
|
|
7648
7711
|
return void 0;
|
|
@@ -7816,13 +7879,13 @@ __export(discover_exports, {
|
|
|
7816
7879
|
});
|
|
7817
7880
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
7818
7881
|
import { createHash } from "crypto";
|
|
7819
|
-
import { homedir as
|
|
7820
|
-
import { join as
|
|
7882
|
+
import { homedir as homedir4 } from "os";
|
|
7883
|
+
import { join as join9 } from "path";
|
|
7821
7884
|
async function discoverAllSkills() {
|
|
7822
7885
|
const rawSkills = [];
|
|
7823
7886
|
rawSkills.push(...await scanSkillDir(SKILLS_PATH, "cc-claw"));
|
|
7824
7887
|
for (const backendId of getAllBackendIds()) {
|
|
7825
|
-
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [
|
|
7888
|
+
const dirs = BACKEND_SKILL_DIRS[backendId] ?? [join9(homedir4(), `.${backendId}`, "skills")];
|
|
7826
7889
|
for (const dir of dirs) {
|
|
7827
7890
|
rawSkills.push(...await scanSkillDir(dir, backendId));
|
|
7828
7891
|
}
|
|
@@ -7842,7 +7905,7 @@ async function scanSkillDir(skillsDir, source) {
|
|
|
7842
7905
|
let content;
|
|
7843
7906
|
let resolvedPath;
|
|
7844
7907
|
for (const candidate of SKILL_FILE_CANDIDATES) {
|
|
7845
|
-
const p =
|
|
7908
|
+
const p = join9(skillsDir, entry.name, candidate);
|
|
7846
7909
|
try {
|
|
7847
7910
|
content = await readFile2(p, "utf-8");
|
|
7848
7911
|
resolvedPath = p;
|
|
@@ -7945,11 +8008,11 @@ var init_discover = __esm({
|
|
|
7945
8008
|
init_backends();
|
|
7946
8009
|
SKILL_FILE_CANDIDATES = ["SKILL.md", "skill.md"];
|
|
7947
8010
|
BACKEND_SKILL_DIRS = {
|
|
7948
|
-
claude: [
|
|
7949
|
-
gemini: [
|
|
8011
|
+
claude: [join9(homedir4(), ".claude", "skills")],
|
|
8012
|
+
gemini: [join9(homedir4(), ".gemini", "skills")],
|
|
7950
8013
|
codex: [
|
|
7951
|
-
|
|
7952
|
-
|
|
8014
|
+
join9(homedir4(), ".agents", "skills"),
|
|
8015
|
+
join9(homedir4(), ".codex", "skills")
|
|
7953
8016
|
]
|
|
7954
8017
|
};
|
|
7955
8018
|
}
|
|
@@ -7962,7 +8025,7 @@ __export(install_exports, {
|
|
|
7962
8025
|
});
|
|
7963
8026
|
import { mkdir, readdir as readdir2, readFile as readFile3, cp } from "fs/promises";
|
|
7964
8027
|
import { existsSync as existsSync10 } from "fs";
|
|
7965
|
-
import { join as
|
|
8028
|
+
import { join as join10, basename } from "path";
|
|
7966
8029
|
import { execSync as execSync4 } from "child_process";
|
|
7967
8030
|
async function installSkillFromGitHub(urlOrShorthand) {
|
|
7968
8031
|
let repoUrl;
|
|
@@ -7973,23 +8036,23 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
7973
8036
|
}
|
|
7974
8037
|
repoUrl = parsed.cloneUrl;
|
|
7975
8038
|
subPath = parsed.subPath;
|
|
7976
|
-
const tmpDir =
|
|
8039
|
+
const tmpDir = join10("/tmp", `cc-claw-skill-${Date.now()}`);
|
|
7977
8040
|
try {
|
|
7978
8041
|
log(`[skill-install] Cloning ${repoUrl} to ${tmpDir}`);
|
|
7979
8042
|
execSync4(`git clone --depth 1 ${repoUrl} ${tmpDir}`, {
|
|
7980
8043
|
stdio: "pipe",
|
|
7981
8044
|
timeout: 3e4
|
|
7982
8045
|
});
|
|
7983
|
-
if (!existsSync10(
|
|
8046
|
+
if (!existsSync10(join10(tmpDir, ".git"))) {
|
|
7984
8047
|
return { success: false, error: "Git clone failed: no .git directory produced" };
|
|
7985
8048
|
}
|
|
7986
|
-
const searchRoot = subPath ?
|
|
8049
|
+
const searchRoot = subPath ? join10(tmpDir, subPath) : tmpDir;
|
|
7987
8050
|
const skillDir = await findSkillDir(searchRoot);
|
|
7988
8051
|
if (!skillDir) {
|
|
7989
8052
|
return { success: false, error: "No SKILL.md found in the repository." };
|
|
7990
8053
|
}
|
|
7991
8054
|
const skillFolderName = basename(skillDir);
|
|
7992
|
-
const destDir =
|
|
8055
|
+
const destDir = join10(SKILLS_PATH, skillFolderName);
|
|
7993
8056
|
if (existsSync10(destDir)) {
|
|
7994
8057
|
log(`[skill-install] Overwriting existing skill at ${destDir}`);
|
|
7995
8058
|
}
|
|
@@ -7997,12 +8060,12 @@ async function installSkillFromGitHub(urlOrShorthand) {
|
|
|
7997
8060
|
await cp(skillDir, destDir, { recursive: true });
|
|
7998
8061
|
let skillName = skillFolderName;
|
|
7999
8062
|
try {
|
|
8000
|
-
const content = await readFile3(
|
|
8063
|
+
const content = await readFile3(join10(destDir, "SKILL.md"), "utf-8");
|
|
8001
8064
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
8002
8065
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
8003
8066
|
} catch {
|
|
8004
8067
|
try {
|
|
8005
|
-
const content = await readFile3(
|
|
8068
|
+
const content = await readFile3(join10(destDir, "skill.md"), "utf-8");
|
|
8006
8069
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
8007
8070
|
if (nameMatch) skillName = nameMatch[1].trim().replace(/^["']|["']$/g, "");
|
|
8008
8071
|
} catch {
|
|
@@ -8037,15 +8100,15 @@ function parseGitHubUrl(input) {
|
|
|
8037
8100
|
async function findSkillDir(root) {
|
|
8038
8101
|
const candidates = ["SKILL.md", "skill.md"];
|
|
8039
8102
|
for (const c of candidates) {
|
|
8040
|
-
if (existsSync10(
|
|
8103
|
+
if (existsSync10(join10(root, c))) return root;
|
|
8041
8104
|
}
|
|
8042
8105
|
try {
|
|
8043
8106
|
const entries = await readdir2(root, { withFileTypes: true });
|
|
8044
8107
|
for (const entry of entries) {
|
|
8045
8108
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
8046
8109
|
for (const c of candidates) {
|
|
8047
|
-
if (existsSync10(
|
|
8048
|
-
return
|
|
8110
|
+
if (existsSync10(join10(root, entry.name, c))) {
|
|
8111
|
+
return join10(root, entry.name);
|
|
8049
8112
|
}
|
|
8050
8113
|
}
|
|
8051
8114
|
}
|
|
@@ -8057,15 +8120,15 @@ async function findSkillDir(root) {
|
|
|
8057
8120
|
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
8058
8121
|
let subEntries;
|
|
8059
8122
|
try {
|
|
8060
|
-
subEntries = await readdir2(
|
|
8123
|
+
subEntries = await readdir2(join10(root, entry.name), { withFileTypes: true });
|
|
8061
8124
|
} catch {
|
|
8062
8125
|
continue;
|
|
8063
8126
|
}
|
|
8064
8127
|
for (const sub of subEntries) {
|
|
8065
8128
|
if (!sub.isDirectory() || sub.name.startsWith(".")) continue;
|
|
8066
8129
|
for (const c of candidates) {
|
|
8067
|
-
if (existsSync10(
|
|
8068
|
-
return
|
|
8130
|
+
if (existsSync10(join10(root, entry.name, sub.name, c))) {
|
|
8131
|
+
return join10(root, entry.name, sub.name);
|
|
8069
8132
|
}
|
|
8070
8133
|
}
|
|
8071
8134
|
}
|
|
@@ -8084,7 +8147,7 @@ var init_install = __esm({
|
|
|
8084
8147
|
|
|
8085
8148
|
// src/bootstrap/profile.ts
|
|
8086
8149
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4, existsSync as existsSync11 } from "fs";
|
|
8087
|
-
import { join as
|
|
8150
|
+
import { join as join11 } from "path";
|
|
8088
8151
|
function hasActiveProfile(chatId) {
|
|
8089
8152
|
return activeProfiles.has(chatId);
|
|
8090
8153
|
}
|
|
@@ -8229,14 +8292,14 @@ var init_profile = __esm({
|
|
|
8229
8292
|
"use strict";
|
|
8230
8293
|
init_paths();
|
|
8231
8294
|
init_log();
|
|
8232
|
-
USER_PATH2 =
|
|
8295
|
+
USER_PATH2 = join11(WORKSPACE_PATH, "USER.md");
|
|
8233
8296
|
activeProfiles = /* @__PURE__ */ new Map();
|
|
8234
8297
|
}
|
|
8235
8298
|
});
|
|
8236
8299
|
|
|
8237
8300
|
// src/bootstrap/heartbeat.ts
|
|
8238
8301
|
import { readFileSync as readFileSync8, existsSync as existsSync12 } from "fs";
|
|
8239
|
-
import { join as
|
|
8302
|
+
import { join as join12 } from "path";
|
|
8240
8303
|
function initHeartbeat(channelReg) {
|
|
8241
8304
|
registry2 = channelReg;
|
|
8242
8305
|
}
|
|
@@ -8244,8 +8307,18 @@ function startHeartbeatForChat(chatId) {
|
|
|
8244
8307
|
stopHeartbeatForChat(chatId);
|
|
8245
8308
|
const config2 = getHeartbeatConfig(chatId);
|
|
8246
8309
|
if (!config2 || !config2.enabled) return;
|
|
8310
|
+
let running = false;
|
|
8247
8311
|
const timer = setInterval(async () => {
|
|
8248
|
-
|
|
8312
|
+
if (running) {
|
|
8313
|
+
log(`[heartbeat] Skipping tick for ${chatId}: previous heartbeat still running`);
|
|
8314
|
+
return;
|
|
8315
|
+
}
|
|
8316
|
+
running = true;
|
|
8317
|
+
try {
|
|
8318
|
+
await runHeartbeat(chatId, config2);
|
|
8319
|
+
} finally {
|
|
8320
|
+
running = false;
|
|
8321
|
+
}
|
|
8249
8322
|
}, config2.intervalMs);
|
|
8250
8323
|
activeTimers2.set(chatId, timer);
|
|
8251
8324
|
const nextBeat = new Date(Date.now() + config2.intervalMs).toISOString();
|
|
@@ -8412,7 +8485,7 @@ var init_heartbeat = __esm({
|
|
|
8412
8485
|
init_backends();
|
|
8413
8486
|
init_health2();
|
|
8414
8487
|
init_log();
|
|
8415
|
-
HEARTBEAT_MD_PATH =
|
|
8488
|
+
HEARTBEAT_MD_PATH = join12(WORKSPACE_PATH, "HEARTBEAT.md");
|
|
8416
8489
|
HEARTBEAT_OK = "HEARTBEAT_OK";
|
|
8417
8490
|
registry2 = null;
|
|
8418
8491
|
activeTimers2 = /* @__PURE__ */ new Map();
|
|
@@ -8458,8 +8531,9 @@ var init_format_time = __esm({
|
|
|
8458
8531
|
});
|
|
8459
8532
|
|
|
8460
8533
|
// src/media/image-gen.ts
|
|
8461
|
-
import {
|
|
8462
|
-
import {
|
|
8534
|
+
import { mkdirSync as mkdirSync5, existsSync as existsSync13 } from "fs";
|
|
8535
|
+
import { writeFile as writeFile2 } from "fs/promises";
|
|
8536
|
+
import { join as join13 } from "path";
|
|
8463
8537
|
async function generateImage(prompt) {
|
|
8464
8538
|
const apiKey = process.env.GEMINI_API_KEY;
|
|
8465
8539
|
if (!apiKey) {
|
|
@@ -8511,9 +8585,9 @@ async function generateImage(prompt) {
|
|
|
8511
8585
|
}
|
|
8512
8586
|
const ext = mimeType.includes("jpeg") || mimeType.includes("jpg") ? "jpg" : "png";
|
|
8513
8587
|
const filename = `img_${Date.now()}.${ext}`;
|
|
8514
|
-
const filePath =
|
|
8588
|
+
const filePath = join13(IMAGE_OUTPUT_DIR, filename);
|
|
8515
8589
|
const buffer = Buffer.from(imageData, "base64");
|
|
8516
|
-
|
|
8590
|
+
await writeFile2(filePath, buffer);
|
|
8517
8591
|
log(`[image-gen] Saved ${buffer.length} bytes to ${filePath}`);
|
|
8518
8592
|
return { filePath, text: textResponse, mimeType };
|
|
8519
8593
|
}
|
|
@@ -8526,8 +8600,8 @@ var init_image_gen = __esm({
|
|
|
8526
8600
|
"use strict";
|
|
8527
8601
|
init_log();
|
|
8528
8602
|
IMAGE_MODEL = "gemini-3.1-flash-image-preview";
|
|
8529
|
-
IMAGE_OUTPUT_DIR =
|
|
8530
|
-
process.env.CC_CLAW_HOME ??
|
|
8603
|
+
IMAGE_OUTPUT_DIR = join13(
|
|
8604
|
+
process.env.CC_CLAW_HOME ?? join13(process.env.HOME ?? "/tmp", ".cc-claw"),
|
|
8531
8605
|
"data",
|
|
8532
8606
|
"images"
|
|
8533
8607
|
);
|
|
@@ -8675,8 +8749,8 @@ async function mp3ToOgg(mp3Buffer) {
|
|
|
8675
8749
|
const id = crypto.randomUUID();
|
|
8676
8750
|
const tmpMp3 = `/tmp/cc-claw-tts-${id}.mp3`;
|
|
8677
8751
|
const tmpOgg = `/tmp/cc-claw-tts-${id}.ogg`;
|
|
8678
|
-
const { writeFile:
|
|
8679
|
-
await
|
|
8752
|
+
const { writeFile: writeFile5 } = await import("fs/promises");
|
|
8753
|
+
await writeFile5(tmpMp3, mp3Buffer);
|
|
8680
8754
|
await execFileAsync2("ffmpeg", ["-y", "-i", tmpMp3, "-c:a", "libopus", "-b:a", "64k", tmpOgg]);
|
|
8681
8755
|
const oggBuffer = await readFile4(tmpOgg);
|
|
8682
8756
|
unlink(tmpMp3).catch((err) => {
|
|
@@ -8691,8 +8765,7 @@ async function macOsTts(text, voice2 = "Samantha") {
|
|
|
8691
8765
|
const id = crypto.randomUUID();
|
|
8692
8766
|
const tmpAiff = `/tmp/cc-claw-tts-${id}.aiff`;
|
|
8693
8767
|
const tmpOgg = `/tmp/cc-claw-tts-${id}.ogg`;
|
|
8694
|
-
|
|
8695
|
-
await execFileAsync2("say", ["-v", voice2, "-o", tmpAiff, sanitized]);
|
|
8768
|
+
await execFileAsync2("say", ["-v", voice2, "-o", tmpAiff, text]);
|
|
8696
8769
|
await execFileAsync2("ffmpeg", ["-y", "-i", tmpAiff, "-c:a", "libopus", "-b:a", "64k", tmpOgg]);
|
|
8697
8770
|
const oggBuffer = await readFile4(tmpOgg);
|
|
8698
8771
|
unlink(tmpAiff).catch((err) => {
|
|
@@ -9567,7 +9640,7 @@ var init_backend_cmd = __esm({
|
|
|
9567
9640
|
});
|
|
9568
9641
|
|
|
9569
9642
|
// src/router.ts
|
|
9570
|
-
import { readFile as readFile5, writeFile as
|
|
9643
|
+
import { readFile as readFile5, writeFile as writeFile3, unlink as unlink2 } from "fs/promises";
|
|
9571
9644
|
import { resolve as resolvePath } from "path";
|
|
9572
9645
|
function parseMcpListOutput(output2) {
|
|
9573
9646
|
const results = [];
|
|
@@ -10518,8 +10591,8 @@ Use /skills to see it.`, "plain");
|
|
|
10518
10591
|
if (!lim.max_input_tokens) continue;
|
|
10519
10592
|
const u = getBackendUsageInWindow(lim.backend, lim.window);
|
|
10520
10593
|
const pct = (u.input_tokens / lim.max_input_tokens * 100).toFixed(0);
|
|
10521
|
-
const
|
|
10522
|
-
lines.push(` ${lim.backend} (${lim.window}): ${pct}% of ${(lim.max_input_tokens / 1e3).toFixed(0)}K${
|
|
10594
|
+
const warn2 = u.input_tokens / lim.max_input_tokens >= lim.warn_pct;
|
|
10595
|
+
lines.push(` ${lim.backend} (${lim.window}): ${pct}% of ${(lim.max_input_tokens / 1e3).toFixed(0)}K${warn2 ? " \u26A0\uFE0F" : ""}`);
|
|
10523
10596
|
}
|
|
10524
10597
|
}
|
|
10525
10598
|
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
@@ -10719,8 +10792,8 @@ Use /skills to see it.`, "plain");
|
|
|
10719
10792
|
lines.push(` \u2705 <b>cc-claw</b> <i>Agent orchestrator (spawn, tasks, inbox)</i>`);
|
|
10720
10793
|
}
|
|
10721
10794
|
const { execFile: execFile5 } = await import("child_process");
|
|
10722
|
-
const { homedir:
|
|
10723
|
-
const discoveryCwd =
|
|
10795
|
+
const { homedir: homedir7 } = await import("os");
|
|
10796
|
+
const discoveryCwd = homedir7();
|
|
10724
10797
|
const runnerResults = await Promise.allSettled(
|
|
10725
10798
|
getAllRunners().map((runner) => {
|
|
10726
10799
|
const listCmd = runner.getMcpListCommand();
|
|
@@ -10912,8 +10985,10 @@ async function handleMedia(msg, channel) {
|
|
|
10912
10985
|
const videoMime = msg.metadata?.mimeType ?? msg.mimeType ?? "video/mp4";
|
|
10913
10986
|
const videoExt = videoMime.split("/")[1]?.replace("quicktime", "mov") || "mp4";
|
|
10914
10987
|
const tempVideoPath = `/tmp/cc-claw-video-${Date.now()}.${videoExt}`;
|
|
10915
|
-
await
|
|
10988
|
+
await writeFile3(tempVideoPath, videoBuffer);
|
|
10916
10989
|
let prompt2;
|
|
10990
|
+
const cleanupVideo = () => unlink2(tempVideoPath).catch(() => {
|
|
10991
|
+
});
|
|
10917
10992
|
if (wantsVideoAnalysis(caption)) {
|
|
10918
10993
|
const geminiPrompt = caption || "Analyze this video and describe what you see in detail.";
|
|
10919
10994
|
let analysis;
|
|
@@ -10952,6 +11027,7 @@ Acknowledge receipt. Do NOT analyze the video unless they ask you to.`;
|
|
|
10952
11027
|
const response2 = await askAgent(chatId, prompt2, { cwd: getCwd(chatId), model: vidModel, permMode: vMode, onToolAction: vidToolCb });
|
|
10953
11028
|
if (response2.usage) addUsage(chatId, response2.usage.input, response2.usage.output, response2.usage.cacheRead, vidModel);
|
|
10954
11029
|
await sendResponse(chatId, channel, response2.text, msg.messageId);
|
|
11030
|
+
cleanupVideo();
|
|
10955
11031
|
return;
|
|
10956
11032
|
}
|
|
10957
11033
|
const fileBuffer = await channel.downloadFile(fileName);
|
|
@@ -10962,7 +11038,7 @@ Acknowledge receipt. Do NOT analyze the video unless they ask you to.`;
|
|
|
10962
11038
|
if (msg.type === "photo" || isImageExt(ext)) {
|
|
10963
11039
|
const imgExt = msg.type === "photo" ? "jpg" : ext || "jpg";
|
|
10964
11040
|
tempFilePath = `/tmp/cc-claw-img-${Date.now()}.${imgExt}`;
|
|
10965
|
-
await
|
|
11041
|
+
await writeFile3(tempFilePath, fileBuffer);
|
|
10966
11042
|
prompt = caption ? `The user sent an image with caption: "${caption}"
|
|
10967
11043
|
|
|
10968
11044
|
The image has been saved to: ${tempFilePath}
|
|
@@ -11403,6 +11479,9 @@ Your conversation history is preserved. ${targetAdapter.displayName} will receiv
|
|
|
11403
11479
|
async function doBackendSwitch(chatId, backendId, channel) {
|
|
11404
11480
|
const targetAdapter = getAdapter(backendId);
|
|
11405
11481
|
const pairCount = getMessagePairCount(chatId);
|
|
11482
|
+
if (pairCount >= 2) {
|
|
11483
|
+
await channel.sendText(chatId, `\u23F3 Saving context...`, "plain");
|
|
11484
|
+
}
|
|
11406
11485
|
const summarized = await summarizeWithFallbackChain(chatId, backendId);
|
|
11407
11486
|
const bridge = buildContextBridge(chatId);
|
|
11408
11487
|
if (bridge) {
|
|
@@ -11521,7 +11600,7 @@ ${PERM_MODES[chosen]}`,
|
|
|
11521
11600
|
const pending = getPendingEscalation(chatId);
|
|
11522
11601
|
if (pending) {
|
|
11523
11602
|
removePendingEscalation(chatId);
|
|
11524
|
-
await handleMessage({ text: pending, chatId, source: "telegram" }, channel);
|
|
11603
|
+
await handleMessage({ text: pending, chatId, source: "telegram", type: "text" }, channel);
|
|
11525
11604
|
}
|
|
11526
11605
|
} else if (data === "perm:deny") {
|
|
11527
11606
|
removePendingEscalation(chatId);
|
|
@@ -11954,7 +12033,7 @@ var init_router = __esm({
|
|
|
11954
12033
|
pendingFallbackMessages = /* @__PURE__ */ new Map();
|
|
11955
12034
|
CLI_INSTALL_HINTS = {
|
|
11956
12035
|
claude: "Install: npm install -g @anthropic-ai/claude-code",
|
|
11957
|
-
gemini: "Install: npm install -g @
|
|
12036
|
+
gemini: "Install: npm install -g @google/gemini-cli",
|
|
11958
12037
|
codex: "Install: npm install -g @openai/codex"
|
|
11959
12038
|
};
|
|
11960
12039
|
BLOCKED_PATH_PATTERNS2 = [
|
|
@@ -12047,17 +12126,17 @@ var init_router = __esm({
|
|
|
12047
12126
|
|
|
12048
12127
|
// src/skills/bootstrap.ts
|
|
12049
12128
|
import { existsSync as existsSync14 } from "fs";
|
|
12050
|
-
import { readdir as readdir3, readFile as readFile6, writeFile as
|
|
12051
|
-
import { join as
|
|
12052
|
-
import { fileURLToPath as
|
|
12129
|
+
import { readdir as readdir3, readFile as readFile6, writeFile as writeFile4, copyFile } from "fs/promises";
|
|
12130
|
+
import { join as join14, dirname as dirname2 } from "path";
|
|
12131
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
12053
12132
|
async function copyAgentManifestSkills() {
|
|
12054
12133
|
if (!existsSync14(PKG_SKILLS)) return;
|
|
12055
12134
|
try {
|
|
12056
12135
|
const entries = await readdir3(PKG_SKILLS, { withFileTypes: true });
|
|
12057
12136
|
for (const entry of entries) {
|
|
12058
12137
|
if (!entry.isFile() || !entry.name.startsWith("agent-") || !entry.name.endsWith(".md")) continue;
|
|
12059
|
-
const src =
|
|
12060
|
-
const dest =
|
|
12138
|
+
const src = join14(PKG_SKILLS, entry.name);
|
|
12139
|
+
const dest = join14(SKILLS_PATH, entry.name);
|
|
12061
12140
|
if (existsSync14(dest)) continue;
|
|
12062
12141
|
await copyFile(src, dest);
|
|
12063
12142
|
log(`[skills] Bootstrapped ${entry.name} to ${SKILLS_PATH}`);
|
|
@@ -12068,7 +12147,7 @@ async function copyAgentManifestSkills() {
|
|
|
12068
12147
|
}
|
|
12069
12148
|
async function bootstrapSkills() {
|
|
12070
12149
|
await copyAgentManifestSkills();
|
|
12071
|
-
const usmDir =
|
|
12150
|
+
const usmDir = join14(SKILLS_PATH, USM_DIR_NAME);
|
|
12072
12151
|
if (existsSync14(usmDir)) return;
|
|
12073
12152
|
try {
|
|
12074
12153
|
const entries = await readdir3(SKILLS_PATH);
|
|
@@ -12091,7 +12170,7 @@ async function bootstrapSkills() {
|
|
|
12091
12170
|
}
|
|
12092
12171
|
}
|
|
12093
12172
|
async function patchUsmForCcClaw(usmDir) {
|
|
12094
|
-
const skillPath =
|
|
12173
|
+
const skillPath = join14(usmDir, "SKILL.md");
|
|
12095
12174
|
if (!existsSync14(skillPath)) return;
|
|
12096
12175
|
try {
|
|
12097
12176
|
let content = await readFile6(skillPath, "utf-8");
|
|
@@ -12120,7 +12199,7 @@ async function patchUsmForCcClaw(usmDir) {
|
|
|
12120
12199
|
}
|
|
12121
12200
|
}
|
|
12122
12201
|
if (patched) {
|
|
12123
|
-
await
|
|
12202
|
+
await writeFile4(skillPath, content, "utf-8");
|
|
12124
12203
|
log("[skills] Patched USM SKILL.md with CC-Claw support");
|
|
12125
12204
|
}
|
|
12126
12205
|
} catch (err) {
|
|
@@ -12137,8 +12216,8 @@ var init_bootstrap = __esm({
|
|
|
12137
12216
|
USM_REPO = "jacob-bd/universal-skills-manager";
|
|
12138
12217
|
USM_DIR_NAME = "universal-skills-manager";
|
|
12139
12218
|
CC_CLAW_ECOSYSTEM_PATCH = `| **CC-Claw** | \`~/.cc-claw/workspace/skills/\` | N/A (daemon, no project scope) |`;
|
|
12140
|
-
PKG_ROOT =
|
|
12141
|
-
PKG_SKILLS =
|
|
12219
|
+
PKG_ROOT = join14(dirname2(fileURLToPath2(import.meta.url)), "..", "..");
|
|
12220
|
+
PKG_SKILLS = join14(PKG_ROOT, "skills");
|
|
12142
12221
|
}
|
|
12143
12222
|
});
|
|
12144
12223
|
|
|
@@ -12352,9 +12431,9 @@ __export(ai_skill_exports, {
|
|
|
12352
12431
|
generateAiSkill: () => generateAiSkill,
|
|
12353
12432
|
installAiSkill: () => installAiSkill
|
|
12354
12433
|
});
|
|
12355
|
-
import { existsSync as existsSync15, writeFileSync as
|
|
12356
|
-
import { join as
|
|
12357
|
-
import { homedir as
|
|
12434
|
+
import { existsSync as existsSync15, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
12435
|
+
import { join as join15 } from "path";
|
|
12436
|
+
import { homedir as homedir5 } from "os";
|
|
12358
12437
|
function generateAiSkill() {
|
|
12359
12438
|
const version = VERSION;
|
|
12360
12439
|
let systemState = "";
|
|
@@ -12654,11 +12733,11 @@ function installAiSkill() {
|
|
|
12654
12733
|
const failed = [];
|
|
12655
12734
|
for (const [backend2, dirs] of Object.entries(BACKEND_SKILL_DIRS2)) {
|
|
12656
12735
|
for (const dir of dirs) {
|
|
12657
|
-
const skillDir =
|
|
12658
|
-
const skillPath =
|
|
12736
|
+
const skillDir = join15(dir, "cc-claw-cli");
|
|
12737
|
+
const skillPath = join15(skillDir, "SKILL.md");
|
|
12659
12738
|
try {
|
|
12660
12739
|
mkdirSync6(skillDir, { recursive: true });
|
|
12661
|
-
|
|
12740
|
+
writeFileSync5(skillPath, skill, "utf-8");
|
|
12662
12741
|
installed.push(skillPath);
|
|
12663
12742
|
} catch {
|
|
12664
12743
|
failed.push(skillPath);
|
|
@@ -12674,10 +12753,10 @@ var init_ai_skill = __esm({
|
|
|
12674
12753
|
init_paths();
|
|
12675
12754
|
init_version();
|
|
12676
12755
|
BACKEND_SKILL_DIRS2 = {
|
|
12677
|
-
"cc-claw": [
|
|
12678
|
-
claude: [
|
|
12679
|
-
gemini: [
|
|
12680
|
-
codex: [
|
|
12756
|
+
"cc-claw": [join15(homedir5(), ".cc-claw", "workspace", "skills")],
|
|
12757
|
+
claude: [join15(homedir5(), ".claude", "skills")],
|
|
12758
|
+
gemini: [join15(homedir5(), ".gemini", "skills")],
|
|
12759
|
+
codex: [join15(homedir5(), ".agents", "skills")]
|
|
12681
12760
|
};
|
|
12682
12761
|
}
|
|
12683
12762
|
});
|
|
@@ -12688,17 +12767,17 @@ __export(index_exports, {
|
|
|
12688
12767
|
main: () => main
|
|
12689
12768
|
});
|
|
12690
12769
|
import { mkdirSync as mkdirSync7, existsSync as existsSync16, renameSync, statSync as statSync2, readFileSync as readFileSync10 } from "fs";
|
|
12691
|
-
import { join as
|
|
12770
|
+
import { join as join16 } from "path";
|
|
12692
12771
|
import dotenv from "dotenv";
|
|
12693
12772
|
function migrateLayout() {
|
|
12694
12773
|
const moves = [
|
|
12695
|
-
[
|
|
12696
|
-
[
|
|
12697
|
-
[
|
|
12698
|
-
[
|
|
12699
|
-
[
|
|
12700
|
-
[
|
|
12701
|
-
[
|
|
12774
|
+
[join16(CC_CLAW_HOME, "cc-claw.db"), join16(DATA_PATH, "cc-claw.db")],
|
|
12775
|
+
[join16(CC_CLAW_HOME, "cc-claw.db-shm"), join16(DATA_PATH, "cc-claw.db-shm")],
|
|
12776
|
+
[join16(CC_CLAW_HOME, "cc-claw.db-wal"), join16(DATA_PATH, "cc-claw.db-wal")],
|
|
12777
|
+
[join16(CC_CLAW_HOME, "cc-claw.log"), join16(LOGS_PATH, "cc-claw.log")],
|
|
12778
|
+
[join16(CC_CLAW_HOME, "cc-claw.log.1"), join16(LOGS_PATH, "cc-claw.log.1")],
|
|
12779
|
+
[join16(CC_CLAW_HOME, "cc-claw.error.log"), join16(LOGS_PATH, "cc-claw.error.log")],
|
|
12780
|
+
[join16(CC_CLAW_HOME, "cc-claw.error.log.1"), join16(LOGS_PATH, "cc-claw.error.log.1")]
|
|
12702
12781
|
];
|
|
12703
12782
|
for (const [from, to] of moves) {
|
|
12704
12783
|
if (existsSync16(from) && !existsSync16(to)) {
|
|
@@ -12803,11 +12882,11 @@ async function main() {
|
|
|
12803
12882
|
bootstrapSkills().catch((err) => error("[cc-claw] Skill bootstrap failed:", err));
|
|
12804
12883
|
try {
|
|
12805
12884
|
const { generateAiSkill: generateAiSkill2 } = await Promise.resolve().then(() => (init_ai_skill(), ai_skill_exports));
|
|
12806
|
-
const { writeFileSync:
|
|
12807
|
-
const { join:
|
|
12808
|
-
const skillDir =
|
|
12885
|
+
const { writeFileSync: writeFileSync8, mkdirSync: mkdirSync11 } = await import("fs");
|
|
12886
|
+
const { join: join19 } = await import("path");
|
|
12887
|
+
const skillDir = join19(SKILLS_PATH, "cc-claw-cli");
|
|
12809
12888
|
mkdirSync11(skillDir, { recursive: true });
|
|
12810
|
-
|
|
12889
|
+
writeFileSync8(join19(skillDir, "SKILL.md"), generateAiSkill2(), "utf-8");
|
|
12811
12890
|
log("[cc-claw] AI skill updated");
|
|
12812
12891
|
} catch {
|
|
12813
12892
|
}
|
|
@@ -12833,7 +12912,13 @@ async function main() {
|
|
|
12833
12912
|
stopMonitor();
|
|
12834
12913
|
shutdownOrchestrator();
|
|
12835
12914
|
shutdownScheduler();
|
|
12836
|
-
await
|
|
12915
|
+
await Promise.race([
|
|
12916
|
+
summarizeAllPending(),
|
|
12917
|
+
new Promise((resolve) => setTimeout(() => {
|
|
12918
|
+
log("[cc-claw] Summarization timed out after 15s, skipping.");
|
|
12919
|
+
resolve();
|
|
12920
|
+
}, 15e3))
|
|
12921
|
+
]);
|
|
12837
12922
|
await channelRegistry.stopAll();
|
|
12838
12923
|
log("[cc-claw] Clean shutdown complete.");
|
|
12839
12924
|
} catch (err) {
|
|
@@ -12891,10 +12976,10 @@ __export(service_exports, {
|
|
|
12891
12976
|
serviceStatus: () => serviceStatus,
|
|
12892
12977
|
uninstallService: () => uninstallService
|
|
12893
12978
|
});
|
|
12894
|
-
import { existsSync as existsSync17, mkdirSync as mkdirSync8, writeFileSync as
|
|
12979
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync8, writeFileSync as writeFileSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
12895
12980
|
import { execFileSync as execFileSync2, execSync as execSync5 } from "child_process";
|
|
12896
|
-
import { homedir as
|
|
12897
|
-
import { join as
|
|
12981
|
+
import { homedir as homedir6, platform } from "os";
|
|
12982
|
+
import { join as join17, dirname as dirname3 } from "path";
|
|
12898
12983
|
function resolveExecutable2(name) {
|
|
12899
12984
|
try {
|
|
12900
12985
|
return execFileSync2("which", [name], { encoding: "utf-8" }).trim();
|
|
@@ -12903,18 +12988,18 @@ function resolveExecutable2(name) {
|
|
|
12903
12988
|
}
|
|
12904
12989
|
}
|
|
12905
12990
|
function getPathDirs() {
|
|
12906
|
-
const nodeBin =
|
|
12907
|
-
const home =
|
|
12991
|
+
const nodeBin = dirname3(process.execPath);
|
|
12992
|
+
const home = homedir6();
|
|
12908
12993
|
const dirs = /* @__PURE__ */ new Set([
|
|
12909
12994
|
nodeBin,
|
|
12910
|
-
|
|
12995
|
+
join17(home, ".local", "bin"),
|
|
12911
12996
|
"/usr/local/bin",
|
|
12912
12997
|
"/usr/bin",
|
|
12913
12998
|
"/bin"
|
|
12914
12999
|
]);
|
|
12915
13000
|
try {
|
|
12916
13001
|
const prefix = execSync5("npm config get prefix", { encoding: "utf-8" }).trim();
|
|
12917
|
-
if (prefix) dirs.add(
|
|
13002
|
+
if (prefix) dirs.add(join17(prefix, "bin"));
|
|
12918
13003
|
} catch {
|
|
12919
13004
|
}
|
|
12920
13005
|
return [...dirs].join(":");
|
|
@@ -12922,7 +13007,7 @@ function getPathDirs() {
|
|
|
12922
13007
|
function generatePlist() {
|
|
12923
13008
|
const ccClawBin = resolveExecutable2("cc-claw");
|
|
12924
13009
|
const pathDirs = getPathDirs();
|
|
12925
|
-
const home =
|
|
13010
|
+
const home = homedir6();
|
|
12926
13011
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
12927
13012
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
12928
13013
|
<plist version="1.0">
|
|
@@ -12968,7 +13053,7 @@ function generatePlist() {
|
|
|
12968
13053
|
</plist>`;
|
|
12969
13054
|
}
|
|
12970
13055
|
function installMacOS() {
|
|
12971
|
-
const agentsDir =
|
|
13056
|
+
const agentsDir = dirname3(PLIST_PATH);
|
|
12972
13057
|
if (!existsSync17(agentsDir)) mkdirSync8(agentsDir, { recursive: true });
|
|
12973
13058
|
if (!existsSync17(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
12974
13059
|
if (existsSync17(PLIST_PATH)) {
|
|
@@ -12977,7 +13062,7 @@ function installMacOS() {
|
|
|
12977
13062
|
} catch {
|
|
12978
13063
|
}
|
|
12979
13064
|
}
|
|
12980
|
-
|
|
13065
|
+
writeFileSync6(PLIST_PATH, generatePlist());
|
|
12981
13066
|
console.log(` Installed: ${PLIST_PATH}`);
|
|
12982
13067
|
execFileSync2("launchctl", ["load", PLIST_PATH]);
|
|
12983
13068
|
console.log(" Service loaded and starting.");
|
|
@@ -13027,7 +13112,7 @@ Restart=on-failure
|
|
|
13027
13112
|
RestartSec=10
|
|
13028
13113
|
WorkingDirectory=${CC_CLAW_HOME}
|
|
13029
13114
|
Environment=PATH=${pathDirs}
|
|
13030
|
-
Environment=HOME=${
|
|
13115
|
+
Environment=HOME=${homedir6()}
|
|
13031
13116
|
|
|
13032
13117
|
[Install]
|
|
13033
13118
|
WantedBy=default.target
|
|
@@ -13036,7 +13121,7 @@ WantedBy=default.target
|
|
|
13036
13121
|
function installLinux() {
|
|
13037
13122
|
if (!existsSync17(SYSTEMD_DIR)) mkdirSync8(SYSTEMD_DIR, { recursive: true });
|
|
13038
13123
|
if (!existsSync17(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
13039
|
-
|
|
13124
|
+
writeFileSync6(UNIT_PATH, generateUnit());
|
|
13040
13125
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
13041
13126
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
13042
13127
|
execFileSync2("systemctl", ["--user", "enable", "cc-claw"]);
|
|
@@ -13069,7 +13154,7 @@ function statusLinux() {
|
|
|
13069
13154
|
}
|
|
13070
13155
|
}
|
|
13071
13156
|
function installService() {
|
|
13072
|
-
if (!existsSync17(
|
|
13157
|
+
if (!existsSync17(join17(CC_CLAW_HOME, ".env"))) {
|
|
13073
13158
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
13074
13159
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
13075
13160
|
process.exitCode = 1;
|
|
@@ -13098,9 +13183,9 @@ var init_service = __esm({
|
|
|
13098
13183
|
"use strict";
|
|
13099
13184
|
init_paths();
|
|
13100
13185
|
PLIST_LABEL = "com.cc-claw";
|
|
13101
|
-
PLIST_PATH =
|
|
13102
|
-
SYSTEMD_DIR =
|
|
13103
|
-
UNIT_PATH =
|
|
13186
|
+
PLIST_PATH = join17(homedir6(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
13187
|
+
SYSTEMD_DIR = join17(homedir6(), ".config", "systemd", "user");
|
|
13188
|
+
UNIT_PATH = join17(SYSTEMD_DIR, "cc-claw.service");
|
|
13104
13189
|
}
|
|
13105
13190
|
});
|
|
13106
13191
|
|
|
@@ -13761,15 +13846,14 @@ async function logsCommand(opts) {
|
|
|
13761
13846
|
console.log(tailLines.join("\n"));
|
|
13762
13847
|
if (opts.follow) {
|
|
13763
13848
|
console.log(muted("\n Following... (Ctrl+C to stop)\n"));
|
|
13764
|
-
let
|
|
13849
|
+
let lastLength = content.length;
|
|
13765
13850
|
watchFile2(logFile, { interval: 500 }, () => {
|
|
13766
13851
|
try {
|
|
13767
13852
|
const newContent = readFileSync14(logFile, "utf-8");
|
|
13768
|
-
|
|
13769
|
-
|
|
13770
|
-
const newPart = newContent.slice(content.length);
|
|
13853
|
+
if (newContent.length > lastLength) {
|
|
13854
|
+
const newPart = newContent.slice(lastLength);
|
|
13771
13855
|
process.stdout.write(newPart);
|
|
13772
|
-
|
|
13856
|
+
lastLength = newContent.length;
|
|
13773
13857
|
}
|
|
13774
13858
|
} catch {
|
|
13775
13859
|
}
|
|
@@ -14242,8 +14326,17 @@ async function cronEdit(globalOpts, id, opts) {
|
|
|
14242
14326
|
values.push(opts.at);
|
|
14243
14327
|
}
|
|
14244
14328
|
if (opts.every) {
|
|
14245
|
-
|
|
14246
|
-
|
|
14329
|
+
const m = opts.every.match(/^(\d+)\s*(m|min|h|hr|s|sec)$/i);
|
|
14330
|
+
if (m) {
|
|
14331
|
+
const num = parseInt(m[1], 10);
|
|
14332
|
+
const unit = m[2].toLowerCase();
|
|
14333
|
+
const ms = unit.startsWith("h") ? num * 36e5 : unit.startsWith("m") ? num * 6e4 : num * 1e3;
|
|
14334
|
+
updates.push("every_ms = ?, schedule_type = 'every'");
|
|
14335
|
+
values.push(ms);
|
|
14336
|
+
} else {
|
|
14337
|
+
updates.push("every_ms = ?, schedule_type = 'every'");
|
|
14338
|
+
values.push(parseInt(opts.every, 10) || 0);
|
|
14339
|
+
}
|
|
14247
14340
|
}
|
|
14248
14341
|
if (opts.backend) {
|
|
14249
14342
|
updates.push("backend = ?");
|
|
@@ -14495,7 +14588,7 @@ __export(db_exports, {
|
|
|
14495
14588
|
dbStats: () => dbStats
|
|
14496
14589
|
});
|
|
14497
14590
|
import { existsSync as existsSync27, statSync as statSync5, copyFileSync, mkdirSync as mkdirSync9 } from "fs";
|
|
14498
|
-
import { dirname as
|
|
14591
|
+
import { dirname as dirname4 } from "path";
|
|
14499
14592
|
async function dbStats(globalOpts) {
|
|
14500
14593
|
if (!existsSync27(DB_PATH)) {
|
|
14501
14594
|
outputError("DB_NOT_FOUND", `Database not found at ${DB_PATH}`);
|
|
@@ -14545,7 +14638,7 @@ async function dbBackup(globalOpts, destPath) {
|
|
|
14545
14638
|
}
|
|
14546
14639
|
const dest = destPath ?? `${DB_PATH}.backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
14547
14640
|
try {
|
|
14548
|
-
mkdirSync9(
|
|
14641
|
+
mkdirSync9(dirname4(dest), { recursive: true });
|
|
14549
14642
|
copyFileSync(DB_PATH, dest);
|
|
14550
14643
|
const walPath = DB_PATH + "-wal";
|
|
14551
14644
|
if (existsSync27(walPath)) copyFileSync(walPath, dest + "-wal");
|
|
@@ -15917,7 +16010,7 @@ var init_completion = __esm({
|
|
|
15917
16010
|
model: ["list", "get", "set"],
|
|
15918
16011
|
thinking: ["get", "set"],
|
|
15919
16012
|
summarizer: ["get", "set"],
|
|
15920
|
-
memory: ["list", "search", "
|
|
16013
|
+
memory: ["list", "search", "history"],
|
|
15921
16014
|
cron: ["list", "create", "edit", "cancel", "pause", "resume", "run", "runs", "health"],
|
|
15922
16015
|
schedule: ["list", "create", "edit", "cancel", "pause", "resume", "run", "runs", "health"],
|
|
15923
16016
|
agents: ["list", "spawn", "cancel", "cancel-all"],
|
|
@@ -15935,7 +16028,7 @@ var init_completion = __esm({
|
|
|
15935
16028
|
chats: ["list", "alias", "remove-alias"],
|
|
15936
16029
|
skills: ["list", "install"],
|
|
15937
16030
|
mcps: ["list"],
|
|
15938
|
-
db: ["stats", "path", "backup"
|
|
16031
|
+
db: ["stats", "path", "backup"],
|
|
15939
16032
|
chat: ["send", "stop"]
|
|
15940
16033
|
};
|
|
15941
16034
|
}
|
|
@@ -15943,10 +16036,10 @@ var init_completion = __esm({
|
|
|
15943
16036
|
|
|
15944
16037
|
// src/setup.ts
|
|
15945
16038
|
var setup_exports = {};
|
|
15946
|
-
import { existsSync as existsSync38, writeFileSync as
|
|
16039
|
+
import { existsSync as existsSync38, writeFileSync as writeFileSync7, readFileSync as readFileSync17, copyFileSync as copyFileSync2, mkdirSync as mkdirSync10, statSync as statSync6 } from "fs";
|
|
15947
16040
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
15948
16041
|
import { createInterface as createInterface5 } from "readline";
|
|
15949
|
-
import { join as
|
|
16042
|
+
import { join as join18 } from "path";
|
|
15950
16043
|
function divider2() {
|
|
15951
16044
|
console.log(dim("\u2500".repeat(55)));
|
|
15952
16045
|
}
|
|
@@ -16033,7 +16126,7 @@ async function setup() {
|
|
|
16033
16126
|
if (match) env[match[1].trim()] = match[2].trim();
|
|
16034
16127
|
}
|
|
16035
16128
|
}
|
|
16036
|
-
const cwdDb =
|
|
16129
|
+
const cwdDb = join18(process.cwd(), "cc-claw.db");
|
|
16037
16130
|
if (existsSync38(cwdDb) && !existsSync38(DB_PATH)) {
|
|
16038
16131
|
const { size } = statSync6(cwdDb);
|
|
16039
16132
|
console.log(yellow(` Found existing database at ${cwdDb} (${(size / 1024).toFixed(0)}KB)`));
|
|
@@ -16247,7 +16340,7 @@ async function setup() {
|
|
|
16247
16340
|
envLines.push("", "# Video Analysis", `GEMINI_API_KEY=${env.GEMINI_API_KEY}`);
|
|
16248
16341
|
}
|
|
16249
16342
|
const envContent = envLines.join("\n") + "\n";
|
|
16250
|
-
|
|
16343
|
+
writeFileSync7(ENV_PATH, envContent, { mode: 384 });
|
|
16251
16344
|
console.log(green(` Config saved to ${ENV_PATH} (permissions: owner-only)`));
|
|
16252
16345
|
header(6, TOTAL_STEPS, "Run on Startup (Daemon)");
|
|
16253
16346
|
console.log(" CC-Claw can run automatically in the background, starting");
|
package/package.json
CHANGED