cc-claw 0.5.0 → 0.5.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 +240 -193
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -49,7 +49,7 @@ var VERSION;
|
|
|
49
49
|
var init_version = __esm({
|
|
50
50
|
"src/version.ts"() {
|
|
51
51
|
"use strict";
|
|
52
|
-
VERSION = true ? "0.5.
|
|
52
|
+
VERSION = true ? "0.5.1" : (() => {
|
|
53
53
|
try {
|
|
54
54
|
return JSON.parse(readFileSync(join2(process.cwd(), "package.json"), "utf-8")).version ?? "unknown";
|
|
55
55
|
} catch {
|
|
@@ -69,14 +69,14 @@ function ts() {
|
|
|
69
69
|
const absM = Math.abs(offset) % 60;
|
|
70
70
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}${sign}${pad(absH)}${pad(absM)}`;
|
|
71
71
|
}
|
|
72
|
-
function log(...
|
|
73
|
-
console.log(`[${ts()}]`, ...
|
|
72
|
+
function log(...args) {
|
|
73
|
+
console.log(`[${ts()}]`, ...args);
|
|
74
74
|
}
|
|
75
|
-
function warn(...
|
|
76
|
-
console.warn(`[${ts()}]`, ...
|
|
75
|
+
function warn(...args) {
|
|
76
|
+
console.warn(`[${ts()}]`, ...args);
|
|
77
77
|
}
|
|
78
|
-
function error(...
|
|
79
|
-
console.error(`[${ts()}]`, ...
|
|
78
|
+
function error(...args) {
|
|
79
|
+
console.error(`[${ts()}]`, ...args);
|
|
80
80
|
}
|
|
81
81
|
function errorMessage(err) {
|
|
82
82
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -2639,7 +2639,7 @@ var init_claude = __esm({
|
|
|
2639
2639
|
return { envOverrides: { MAX_THINKING_TOKENS: budgets[level] ?? "16384" } };
|
|
2640
2640
|
}
|
|
2641
2641
|
buildSpawnConfig(opts) {
|
|
2642
|
-
const
|
|
2642
|
+
const args = [
|
|
2643
2643
|
"-p",
|
|
2644
2644
|
opts.prompt,
|
|
2645
2645
|
"--output-format",
|
|
@@ -2648,32 +2648,32 @@ var init_claude = __esm({
|
|
|
2648
2648
|
"--max-turns",
|
|
2649
2649
|
String(opts.maxTurns ?? 25)
|
|
2650
2650
|
];
|
|
2651
|
-
if (opts.sessionId)
|
|
2652
|
-
if (opts.model)
|
|
2651
|
+
if (opts.sessionId) args.push("--resume", opts.sessionId);
|
|
2652
|
+
if (opts.model) args.push("--model", opts.model);
|
|
2653
2653
|
switch (opts.permMode) {
|
|
2654
2654
|
case "plan":
|
|
2655
|
-
|
|
2656
|
-
|
|
2655
|
+
args.push("--permission-mode", "plan");
|
|
2656
|
+
args.push("--strict-mcp-config");
|
|
2657
2657
|
break;
|
|
2658
2658
|
case "safe":
|
|
2659
|
-
|
|
2659
|
+
args.push("--permission-mode", "bypassPermissions");
|
|
2660
2660
|
if (opts.allowedTools.length > 0) {
|
|
2661
|
-
|
|
2661
|
+
args.push("--tools", opts.allowedTools.join(","));
|
|
2662
2662
|
} else {
|
|
2663
|
-
|
|
2663
|
+
args.push("--tools", "Read,Glob,Grep");
|
|
2664
2664
|
}
|
|
2665
2665
|
break;
|
|
2666
2666
|
case "yolo":
|
|
2667
2667
|
default:
|
|
2668
|
-
|
|
2669
|
-
|
|
2668
|
+
args.push("--permission-mode", "bypassPermissions");
|
|
2669
|
+
args.push("--allow-dangerously-skip-permissions");
|
|
2670
2670
|
break;
|
|
2671
2671
|
}
|
|
2672
2672
|
const identityFile = join3(IDENTITY_PATH, "CC-CLAW.md");
|
|
2673
2673
|
if (existsSync(identityFile)) {
|
|
2674
|
-
|
|
2674
|
+
args.push("--append-system-prompt-file", identityFile);
|
|
2675
2675
|
}
|
|
2676
|
-
return { executable: this.getExecutablePath(), args
|
|
2676
|
+
return { executable: this.getExecutablePath(), args, cwd: opts.cwd };
|
|
2677
2677
|
}
|
|
2678
2678
|
parseLine(raw) {
|
|
2679
2679
|
if (typeof raw !== "object" || raw === null) return [];
|
|
@@ -2818,7 +2818,7 @@ var init_gemini = __esm({
|
|
|
2818
2818
|
return {};
|
|
2819
2819
|
}
|
|
2820
2820
|
buildSpawnConfig(opts) {
|
|
2821
|
-
const
|
|
2821
|
+
const args = [
|
|
2822
2822
|
"-p",
|
|
2823
2823
|
opts.prompt,
|
|
2824
2824
|
"-o",
|
|
@@ -2826,21 +2826,21 @@ var init_gemini = __esm({
|
|
|
2826
2826
|
"--allowed-mcp-server-names=__none__"
|
|
2827
2827
|
// nonexistent name = skip all user MCP servers (avoids crash/hang from broken servers)
|
|
2828
2828
|
];
|
|
2829
|
-
if (opts.sessionId)
|
|
2830
|
-
if (opts.model)
|
|
2829
|
+
if (opts.sessionId) args.push("--resume", opts.sessionId);
|
|
2830
|
+
if (opts.model) args.push("-m", opts.model);
|
|
2831
2831
|
switch (opts.permMode) {
|
|
2832
2832
|
case "plan":
|
|
2833
|
-
|
|
2833
|
+
args.push("--approval-mode", "plan");
|
|
2834
2834
|
break;
|
|
2835
2835
|
case "safe":
|
|
2836
|
-
|
|
2836
|
+
args.push("--approval-mode", "plan");
|
|
2837
2837
|
break;
|
|
2838
2838
|
case "yolo":
|
|
2839
2839
|
default:
|
|
2840
|
-
|
|
2840
|
+
args.push("--yolo");
|
|
2841
2841
|
break;
|
|
2842
2842
|
}
|
|
2843
|
-
return { executable: this.getExecutablePath(), args
|
|
2843
|
+
return { executable: this.getExecutablePath(), args, cwd: opts.cwd };
|
|
2844
2844
|
}
|
|
2845
2845
|
parseLine(raw) {
|
|
2846
2846
|
if (typeof raw !== "object" || raw === null) return [];
|
|
@@ -2975,31 +2975,31 @@ var init_codex = __esm({
|
|
|
2975
2975
|
}
|
|
2976
2976
|
buildSpawnConfig(opts) {
|
|
2977
2977
|
const isResume = !!opts.sessionId;
|
|
2978
|
-
const
|
|
2978
|
+
const args = [];
|
|
2979
2979
|
if (isResume) {
|
|
2980
|
-
|
|
2980
|
+
args.push("exec", "resume", opts.sessionId, opts.prompt, "--json");
|
|
2981
2981
|
} else {
|
|
2982
|
-
|
|
2982
|
+
args.push("exec", opts.prompt, "--json");
|
|
2983
2983
|
}
|
|
2984
|
-
if (opts.model)
|
|
2984
|
+
if (opts.model) args.push("-m", opts.model);
|
|
2985
2985
|
switch (opts.permMode) {
|
|
2986
2986
|
case "plan":
|
|
2987
|
-
|
|
2987
|
+
args.push("--sandbox", "read-only");
|
|
2988
2988
|
break;
|
|
2989
2989
|
case "safe":
|
|
2990
|
-
|
|
2990
|
+
args.push("--sandbox", "read-only");
|
|
2991
2991
|
break;
|
|
2992
2992
|
case "yolo":
|
|
2993
2993
|
default:
|
|
2994
|
-
|
|
2994
|
+
args.push("--dangerously-bypass-approvals-and-sandbox");
|
|
2995
2995
|
break;
|
|
2996
2996
|
}
|
|
2997
2997
|
if (!isResume && opts.cwd) {
|
|
2998
|
-
|
|
2998
|
+
args.push("-C", opts.cwd);
|
|
2999
2999
|
}
|
|
3000
3000
|
return {
|
|
3001
3001
|
executable: this.getExecutablePath(),
|
|
3002
|
-
args
|
|
3002
|
+
args,
|
|
3003
3003
|
// For resume, pass cwd via spawn option since -C isn't supported
|
|
3004
3004
|
cwd: isResume ? opts.cwd : void 0
|
|
3005
3005
|
};
|
|
@@ -4130,8 +4130,8 @@ function spawnAgentProcess(runner, opts, callbacks) {
|
|
|
4130
4130
|
permMode: opts.permMode,
|
|
4131
4131
|
allowedTools: opts.allowedTools
|
|
4132
4132
|
});
|
|
4133
|
-
const
|
|
4134
|
-
const child = spawn2(runner.getExecutablePath(),
|
|
4133
|
+
const args = opts.extraArgs?.length ? [...baseArgs, ...opts.extraArgs] : baseArgs;
|
|
4134
|
+
const child = spawn2(runner.getExecutablePath(), args, {
|
|
4135
4135
|
env: buildSpawnEnv(runner, opts.isSubAgent),
|
|
4136
4136
|
cwd: opts.cwd,
|
|
4137
4137
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -4252,8 +4252,8 @@ async function discoverExistingMcps(runner) {
|
|
|
4252
4252
|
try {
|
|
4253
4253
|
const listCmd = runner.getMcpListCommand();
|
|
4254
4254
|
const exe = runner.getExecutablePath();
|
|
4255
|
-
const
|
|
4256
|
-
const result = await execFileAsync(exe,
|
|
4255
|
+
const args = listCmd.slice(1);
|
|
4256
|
+
const result = await execFileAsync(exe, args, {
|
|
4257
4257
|
encoding: "utf-8",
|
|
4258
4258
|
env: runner.getEnv(),
|
|
4259
4259
|
cwd: homedir3(),
|
|
@@ -4301,8 +4301,8 @@ async function injectMcps(runner, mcpNames, db3, scope) {
|
|
|
4301
4301
|
try {
|
|
4302
4302
|
const config2 = defToConfig(def);
|
|
4303
4303
|
const addCmd = runner.getMcpAddCommand(config2);
|
|
4304
|
-
const
|
|
4305
|
-
await execFileAsync(exe,
|
|
4304
|
+
const args = addCmd.slice(1);
|
|
4305
|
+
await execFileAsync(exe, args, { encoding: "utf-8" });
|
|
4306
4306
|
addPropagation(db3, name, runnerId, scope);
|
|
4307
4307
|
added.push(name);
|
|
4308
4308
|
} catch {
|
|
@@ -4316,8 +4316,8 @@ async function cleanupMcps(runner, mcps2, db3, scope) {
|
|
|
4316
4316
|
for (const name of mcps2) {
|
|
4317
4317
|
try {
|
|
4318
4318
|
const removeCmd = runner.getMcpRemoveCommand(name);
|
|
4319
|
-
const
|
|
4320
|
-
await execFileAsync(exe,
|
|
4319
|
+
const args = removeCmd.slice(1);
|
|
4320
|
+
await execFileAsync(exe, args, { encoding: "utf-8" });
|
|
4321
4321
|
} catch {
|
|
4322
4322
|
}
|
|
4323
4323
|
removePropagation(db3, name, runnerId, scope);
|
|
@@ -4673,8 +4673,8 @@ async function startAgent(agentId, chatId, opts) {
|
|
|
4673
4673
|
const addCmd = runner.getMcpAddCommand(mcpConfig);
|
|
4674
4674
|
const { execFileSync: execFileSync5 } = await import("child_process");
|
|
4675
4675
|
const exe = addCmd[0];
|
|
4676
|
-
const
|
|
4677
|
-
execFileSync5(exe,
|
|
4676
|
+
const args = addCmd.slice(1);
|
|
4677
|
+
execFileSync5(exe, args, { encoding: "utf-8", timeout: 15e3, env: runner.getEnv() });
|
|
4678
4678
|
});
|
|
4679
4679
|
mcpsAdded = [...mcpsAdded, orchestratorMcpName];
|
|
4680
4680
|
updateAgentMcpsAdded(db3, agentId, mcpsAdded);
|
|
@@ -5177,13 +5177,13 @@ __export(health_exports, {
|
|
|
5177
5177
|
stopHealthMonitor: () => stopHealthMonitor
|
|
5178
5178
|
});
|
|
5179
5179
|
import { spawn as spawn3 } from "child_process";
|
|
5180
|
-
async function checkStdioHealth(command,
|
|
5180
|
+
async function checkStdioHealth(command, args) {
|
|
5181
5181
|
return new Promise((resolve) => {
|
|
5182
5182
|
const timer = setTimeout(() => {
|
|
5183
5183
|
child.kill("SIGKILL");
|
|
5184
5184
|
resolve("timeout");
|
|
5185
5185
|
}, CHECK_TIMEOUT_MS);
|
|
5186
|
-
const child = spawn3(command,
|
|
5186
|
+
const child = spawn3(command, args, {
|
|
5187
5187
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5188
5188
|
});
|
|
5189
5189
|
let responded = false;
|
|
@@ -5238,8 +5238,8 @@ async function runHealthChecks(db3) {
|
|
|
5238
5238
|
let status = "unhealthy";
|
|
5239
5239
|
try {
|
|
5240
5240
|
if (mcp.transport === "stdio" && mcp.command) {
|
|
5241
|
-
const
|
|
5242
|
-
status = await checkStdioHealth(mcp.command,
|
|
5241
|
+
const args = mcp.args ? JSON.parse(mcp.args) : [];
|
|
5242
|
+
status = await checkStdioHealth(mcp.command, args);
|
|
5243
5243
|
} else if ((mcp.transport === "sse" || mcp.transport === "streamable-http") && mcp.url) {
|
|
5244
5244
|
status = await checkHttpHealth(mcp.url);
|
|
5245
5245
|
} else {
|
|
@@ -6480,10 +6480,10 @@ function getMcpConfigPath(chatId) {
|
|
|
6480
6480
|
const config2 = generateOrchestratorMcpConfig({ chatId, agentId: "main", token });
|
|
6481
6481
|
return writeMcpConfigFile(config2);
|
|
6482
6482
|
}
|
|
6483
|
-
function injectMcpConfig(adapterId,
|
|
6483
|
+
function injectMcpConfig(adapterId, args, mcpConfigPath) {
|
|
6484
6484
|
const flag = MCP_CONFIG_FLAG[adapterId];
|
|
6485
|
-
if (!flag) return
|
|
6486
|
-
return [...
|
|
6485
|
+
if (!flag) return args;
|
|
6486
|
+
return [...args, ...flag, mcpConfigPath];
|
|
6487
6487
|
}
|
|
6488
6488
|
var activeChats, chatLocks, SPAWN_TIMEOUT_MS, MCP_CONFIG_FLAG;
|
|
6489
6489
|
var init_agent = __esm({
|
|
@@ -7187,17 +7187,17 @@ function wrapBackendAdapter(adapter) {
|
|
|
7187
7187
|
if (method !== "config-file") return [];
|
|
7188
7188
|
if (adapter.id === "codex") {
|
|
7189
7189
|
const safeName = server.name.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
7190
|
-
const
|
|
7191
|
-
|
|
7190
|
+
const args = [];
|
|
7191
|
+
args.push("-c", `mcp_servers.${safeName}.command="${server.command}"`);
|
|
7192
7192
|
if (server.args?.length) {
|
|
7193
|
-
|
|
7193
|
+
args.push("-c", `mcp_servers.${safeName}.args=${JSON.stringify(server.args)}`);
|
|
7194
7194
|
}
|
|
7195
7195
|
if (server.env) {
|
|
7196
7196
|
for (const [k, v] of Object.entries(server.env)) {
|
|
7197
|
-
|
|
7197
|
+
args.push("-c", `mcp_servers.${safeName}.env.${k}="${v}"`);
|
|
7198
7198
|
}
|
|
7199
7199
|
}
|
|
7200
|
-
return
|
|
7200
|
+
return args;
|
|
7201
7201
|
}
|
|
7202
7202
|
const configPath = writeMcpConfigFile(server);
|
|
7203
7203
|
return ["--mcp-config", configPath];
|
|
@@ -7316,8 +7316,8 @@ function buildGenericParser(config2) {
|
|
|
7316
7316
|
return events;
|
|
7317
7317
|
};
|
|
7318
7318
|
}
|
|
7319
|
-
function templateReplace(
|
|
7320
|
-
return
|
|
7319
|
+
function templateReplace(args, vars) {
|
|
7320
|
+
return args.map((a) => {
|
|
7321
7321
|
let result = a;
|
|
7322
7322
|
for (const [key, val] of Object.entries(vars)) {
|
|
7323
7323
|
result = result.replace(`{${key}}`, val);
|
|
@@ -7343,23 +7343,23 @@ function configToRunner(config2) {
|
|
|
7343
7343
|
getExecutablePath: () => exePath,
|
|
7344
7344
|
getEnv: () => buildBaseEnv(config2.env),
|
|
7345
7345
|
buildSpawnArgs(opts) {
|
|
7346
|
-
const
|
|
7347
|
-
if (config2.spawnPattern.extraArgs)
|
|
7348
|
-
if (config2.spawnPattern.outputFormatFlag)
|
|
7349
|
-
|
|
7346
|
+
const args = [];
|
|
7347
|
+
if (config2.spawnPattern.extraArgs) args.push(...config2.spawnPattern.extraArgs);
|
|
7348
|
+
if (config2.spawnPattern.outputFormatFlag) args.push(...config2.spawnPattern.outputFormatFlag);
|
|
7349
|
+
args.push(...config2.spawnPattern.promptFlag, opts.prompt);
|
|
7350
7350
|
if (opts.model && config2.spawnPattern.modelFlag) {
|
|
7351
|
-
|
|
7351
|
+
args.push(...config2.spawnPattern.modelFlag, opts.model);
|
|
7352
7352
|
}
|
|
7353
7353
|
if (opts.cwd && config2.spawnPattern.cwdFlag) {
|
|
7354
|
-
|
|
7354
|
+
args.push(...config2.spawnPattern.cwdFlag, opts.cwd);
|
|
7355
7355
|
}
|
|
7356
7356
|
if (opts.sessionId && config2.spawnPattern.sessionResumeFlag) {
|
|
7357
|
-
|
|
7357
|
+
args.push(...config2.spawnPattern.sessionResumeFlag, opts.sessionId);
|
|
7358
7358
|
}
|
|
7359
7359
|
if (opts.permMode && config2.spawnPattern.permModes?.[opts.permMode]) {
|
|
7360
|
-
|
|
7360
|
+
args.push(...config2.spawnPattern.permModes[opts.permMode]);
|
|
7361
7361
|
}
|
|
7362
|
-
return
|
|
7362
|
+
return args;
|
|
7363
7363
|
},
|
|
7364
7364
|
parseLine,
|
|
7365
7365
|
shouldKillOnResult: () => config2.shouldKillOnResult,
|
|
@@ -8642,8 +8642,8 @@ function formatHeartbeatStatus(chatId) {
|
|
|
8642
8642
|
}
|
|
8643
8643
|
return lines.join("\n");
|
|
8644
8644
|
}
|
|
8645
|
-
function parseHeartbeatCommand(chatId,
|
|
8646
|
-
const parts =
|
|
8645
|
+
function parseHeartbeatCommand(chatId, args) {
|
|
8646
|
+
const parts = args.trim().toLowerCase().split(/\s+/);
|
|
8647
8647
|
return { action: parts[0] ?? "status", value: parts.slice(1).join(" ") };
|
|
8648
8648
|
}
|
|
8649
8649
|
var HEARTBEAT_MD_PATH, HEARTBEAT_OK, registry2, activeTimers2;
|
|
@@ -10602,13 +10602,19 @@ ${lines.join("\n")}`, "plain");
|
|
|
10602
10602
|
}
|
|
10603
10603
|
case "model_signature": {
|
|
10604
10604
|
const currentSig = getModelSignature(chatId);
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10605
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
10606
|
+
await channel.sendKeyboard(chatId, `Model Signature: ${currentSig === "on" ? "ON" : "OFF"}
|
|
10607
|
+
Appends model + thinking level to each response.`, [
|
|
10608
|
+
[
|
|
10609
|
+
{ label: currentSig === "on" ? "\u2713 On" : "On", data: "model_sig:on" },
|
|
10610
|
+
{ label: currentSig !== "on" ? "\u2713 Off" : "Off", data: "model_sig:off" }
|
|
10611
|
+
]
|
|
10612
|
+
]);
|
|
10613
|
+
} else {
|
|
10614
|
+
const newSig = currentSig === "on" ? "off" : "on";
|
|
10615
|
+
setModelSignature(chatId, newSig);
|
|
10616
|
+
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", "plain");
|
|
10617
|
+
}
|
|
10612
10618
|
break;
|
|
10613
10619
|
}
|
|
10614
10620
|
case "imagine":
|
|
@@ -11251,7 +11257,7 @@ Use /skills to see it.`, "plain");
|
|
|
11251
11257
|
break;
|
|
11252
11258
|
}
|
|
11253
11259
|
case "intent": {
|
|
11254
|
-
const testMsg =
|
|
11260
|
+
const testMsg = commandArgs?.trim() || "hey";
|
|
11255
11261
|
const result = classifyIntent(testMsg, chatId);
|
|
11256
11262
|
await channel.sendText(chatId, `Intent: ${result}
|
|
11257
11263
|
Message: "${testMsg}"`, "plain");
|
|
@@ -12086,6 +12092,14 @@ ${PERM_MODES[chosen]}`,
|
|
|
12086
12092
|
}
|
|
12087
12093
|
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, "plain");
|
|
12088
12094
|
}
|
|
12095
|
+
} else if (data.startsWith("model_sig:")) {
|
|
12096
|
+
const value = data.slice(10);
|
|
12097
|
+
setModelSignature(chatId, value);
|
|
12098
|
+
await channel.sendText(
|
|
12099
|
+
chatId,
|
|
12100
|
+
value === "on" ? "\u{1F9E0} Model signature enabled. Each response will show the active model and thinking level." : "Model signature disabled.",
|
|
12101
|
+
"plain"
|
|
12102
|
+
);
|
|
12089
12103
|
} else if (data.startsWith("vcfg:")) {
|
|
12090
12104
|
const parts = data.slice(5).split(":");
|
|
12091
12105
|
const action = parts[0];
|
|
@@ -13312,6 +13326,106 @@ var init_index = __esm({
|
|
|
13312
13326
|
}
|
|
13313
13327
|
});
|
|
13314
13328
|
|
|
13329
|
+
// src/cli/api-client.ts
|
|
13330
|
+
var api_client_exports = {};
|
|
13331
|
+
__export(api_client_exports, {
|
|
13332
|
+
apiGet: () => apiGet,
|
|
13333
|
+
apiPost: () => apiPost,
|
|
13334
|
+
isDaemonRunning: () => isDaemonRunning
|
|
13335
|
+
});
|
|
13336
|
+
import { readFileSync as readFileSync11, existsSync as existsSync17 } from "fs";
|
|
13337
|
+
import { request as httpRequest } from "http";
|
|
13338
|
+
function getToken() {
|
|
13339
|
+
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
13340
|
+
try {
|
|
13341
|
+
if (existsSync17(TOKEN_PATH)) return readFileSync11(TOKEN_PATH, "utf-8").trim();
|
|
13342
|
+
} catch {
|
|
13343
|
+
}
|
|
13344
|
+
return null;
|
|
13345
|
+
}
|
|
13346
|
+
async function isDaemonRunning() {
|
|
13347
|
+
try {
|
|
13348
|
+
const res = await apiGet("/api/health");
|
|
13349
|
+
return res.ok;
|
|
13350
|
+
} catch {
|
|
13351
|
+
return false;
|
|
13352
|
+
}
|
|
13353
|
+
}
|
|
13354
|
+
async function apiGet(path) {
|
|
13355
|
+
const token = getToken();
|
|
13356
|
+
return new Promise((resolve, reject) => {
|
|
13357
|
+
const url = new URL(path, BASE_URL);
|
|
13358
|
+
const req = httpRequest(url, {
|
|
13359
|
+
method: "GET",
|
|
13360
|
+
headers: token ? { "Authorization": `Bearer ${token}` } : {},
|
|
13361
|
+
timeout: 3e3
|
|
13362
|
+
}, (res) => {
|
|
13363
|
+
const chunks = [];
|
|
13364
|
+
res.on("data", (c) => chunks.push(c));
|
|
13365
|
+
res.on("end", () => {
|
|
13366
|
+
const body = Buffer.concat(chunks).toString();
|
|
13367
|
+
try {
|
|
13368
|
+
const data = JSON.parse(body);
|
|
13369
|
+
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13370
|
+
} catch {
|
|
13371
|
+
resolve({ ok: false, status: res.statusCode ?? 0, data: body });
|
|
13372
|
+
}
|
|
13373
|
+
});
|
|
13374
|
+
});
|
|
13375
|
+
req.on("error", reject);
|
|
13376
|
+
req.on("timeout", () => {
|
|
13377
|
+
req.destroy();
|
|
13378
|
+
reject(new Error("Request timed out"));
|
|
13379
|
+
});
|
|
13380
|
+
req.end();
|
|
13381
|
+
});
|
|
13382
|
+
}
|
|
13383
|
+
async function apiPost(path, body) {
|
|
13384
|
+
const token = getToken();
|
|
13385
|
+
const payload = JSON.stringify(body);
|
|
13386
|
+
return new Promise((resolve, reject) => {
|
|
13387
|
+
const url = new URL(path, BASE_URL);
|
|
13388
|
+
const req = httpRequest(url, {
|
|
13389
|
+
method: "POST",
|
|
13390
|
+
headers: {
|
|
13391
|
+
"Content-Type": "application/json",
|
|
13392
|
+
"Content-Length": Buffer.byteLength(payload).toString(),
|
|
13393
|
+
...token ? { "Authorization": `Bearer ${token}` } : {}
|
|
13394
|
+
},
|
|
13395
|
+
timeout: 3e4
|
|
13396
|
+
}, (res) => {
|
|
13397
|
+
const chunks = [];
|
|
13398
|
+
res.on("data", (c) => chunks.push(c));
|
|
13399
|
+
res.on("end", () => {
|
|
13400
|
+
const responseBody = Buffer.concat(chunks).toString();
|
|
13401
|
+
try {
|
|
13402
|
+
const data = JSON.parse(responseBody);
|
|
13403
|
+
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13404
|
+
} catch {
|
|
13405
|
+
resolve({ ok: false, status: res.statusCode ?? 0, data: responseBody });
|
|
13406
|
+
}
|
|
13407
|
+
});
|
|
13408
|
+
});
|
|
13409
|
+
req.on("error", reject);
|
|
13410
|
+
req.on("timeout", () => {
|
|
13411
|
+
req.destroy();
|
|
13412
|
+
reject(new Error("Request timed out"));
|
|
13413
|
+
});
|
|
13414
|
+
req.write(payload);
|
|
13415
|
+
req.end();
|
|
13416
|
+
});
|
|
13417
|
+
}
|
|
13418
|
+
var TOKEN_PATH, DEFAULT_PORT, BASE_URL;
|
|
13419
|
+
var init_api_client = __esm({
|
|
13420
|
+
"src/cli/api-client.ts"() {
|
|
13421
|
+
"use strict";
|
|
13422
|
+
init_paths();
|
|
13423
|
+
TOKEN_PATH = `${DATA_PATH}/api-token`;
|
|
13424
|
+
DEFAULT_PORT = parseInt(process.env.DASHBOARD_PORT ?? "3141", 10);
|
|
13425
|
+
BASE_URL = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
13426
|
+
}
|
|
13427
|
+
});
|
|
13428
|
+
|
|
13315
13429
|
// src/service.ts
|
|
13316
13430
|
var service_exports = {};
|
|
13317
13431
|
__export(service_exports, {
|
|
@@ -13319,7 +13433,7 @@ __export(service_exports, {
|
|
|
13319
13433
|
serviceStatus: () => serviceStatus,
|
|
13320
13434
|
uninstallService: () => uninstallService
|
|
13321
13435
|
});
|
|
13322
|
-
import { existsSync as
|
|
13436
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3 } from "fs";
|
|
13323
13437
|
import { execFileSync as execFileSync2, execSync as execSync5 } from "child_process";
|
|
13324
13438
|
import { homedir as homedir6, platform } from "os";
|
|
13325
13439
|
import { join as join19, dirname as dirname3 } from "path";
|
|
@@ -13397,9 +13511,9 @@ function generatePlist() {
|
|
|
13397
13511
|
}
|
|
13398
13512
|
function installMacOS() {
|
|
13399
13513
|
const agentsDir = dirname3(PLIST_PATH);
|
|
13400
|
-
if (!
|
|
13401
|
-
if (!
|
|
13402
|
-
if (
|
|
13514
|
+
if (!existsSync18(agentsDir)) mkdirSync8(agentsDir, { recursive: true });
|
|
13515
|
+
if (!existsSync18(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
13516
|
+
if (existsSync18(PLIST_PATH)) {
|
|
13403
13517
|
try {
|
|
13404
13518
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
13405
13519
|
} catch {
|
|
@@ -13411,7 +13525,7 @@ function installMacOS() {
|
|
|
13411
13525
|
console.log(" Service loaded and starting.");
|
|
13412
13526
|
}
|
|
13413
13527
|
function uninstallMacOS() {
|
|
13414
|
-
if (!
|
|
13528
|
+
if (!existsSync18(PLIST_PATH)) {
|
|
13415
13529
|
console.log(" No service found to uninstall.");
|
|
13416
13530
|
return;
|
|
13417
13531
|
}
|
|
@@ -13422,6 +13536,24 @@ function uninstallMacOS() {
|
|
|
13422
13536
|
unlinkSync3(PLIST_PATH);
|
|
13423
13537
|
console.log(" Service uninstalled.");
|
|
13424
13538
|
}
|
|
13539
|
+
function formatUptime(seconds) {
|
|
13540
|
+
seconds = Math.floor(seconds);
|
|
13541
|
+
if (seconds < 60) return `${seconds}s`;
|
|
13542
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
13543
|
+
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
13544
|
+
return `${Math.floor(seconds / 86400)}d ${Math.floor(seconds % 86400 / 3600)}h`;
|
|
13545
|
+
}
|
|
13546
|
+
async function getUptimeFromDaemon() {
|
|
13547
|
+
try {
|
|
13548
|
+
const { isDaemonRunning: isDaemonRunning2, apiGet: apiGet2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
13549
|
+
if (!await isDaemonRunning2()) return null;
|
|
13550
|
+
const res = await apiGet2("/api/health");
|
|
13551
|
+
const sec = res.data?.uptime;
|
|
13552
|
+
return sec ? formatUptime(sec) : null;
|
|
13553
|
+
} catch {
|
|
13554
|
+
return null;
|
|
13555
|
+
}
|
|
13556
|
+
}
|
|
13425
13557
|
function statusMacOS() {
|
|
13426
13558
|
try {
|
|
13427
13559
|
const out = execSync5("launchctl list | grep cc-claw", { shell: "/bin/sh", encoding: "utf-8" }).trim();
|
|
@@ -13430,7 +13562,12 @@ function statusMacOS() {
|
|
|
13430
13562
|
const pid = parts[0];
|
|
13431
13563
|
const exitCode = parts[1];
|
|
13432
13564
|
if (pid !== "-") {
|
|
13433
|
-
|
|
13565
|
+
getUptimeFromDaemon().then((uptime) => {
|
|
13566
|
+
const uptimeStr = uptime ? `, uptime ${uptime}` : "";
|
|
13567
|
+
console.log(` Running (PID ${pid}${uptimeStr})`);
|
|
13568
|
+
}).catch(() => {
|
|
13569
|
+
console.log(` Running (PID ${pid})`);
|
|
13570
|
+
});
|
|
13434
13571
|
} else {
|
|
13435
13572
|
console.log(` Not running (last exit code: ${exitCode})`);
|
|
13436
13573
|
}
|
|
@@ -13462,8 +13599,8 @@ WantedBy=default.target
|
|
|
13462
13599
|
`;
|
|
13463
13600
|
}
|
|
13464
13601
|
function installLinux() {
|
|
13465
|
-
if (!
|
|
13466
|
-
if (!
|
|
13602
|
+
if (!existsSync18(SYSTEMD_DIR)) mkdirSync8(SYSTEMD_DIR, { recursive: true });
|
|
13603
|
+
if (!existsSync18(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
13467
13604
|
writeFileSync6(UNIT_PATH, generateUnit());
|
|
13468
13605
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
13469
13606
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -13472,7 +13609,7 @@ function installLinux() {
|
|
|
13472
13609
|
console.log(" Service enabled and started.");
|
|
13473
13610
|
}
|
|
13474
13611
|
function uninstallLinux() {
|
|
13475
|
-
if (!
|
|
13612
|
+
if (!existsSync18(UNIT_PATH)) {
|
|
13476
13613
|
console.log(" No service found to uninstall.");
|
|
13477
13614
|
return;
|
|
13478
13615
|
}
|
|
@@ -13497,7 +13634,7 @@ function statusLinux() {
|
|
|
13497
13634
|
}
|
|
13498
13635
|
}
|
|
13499
13636
|
function installService() {
|
|
13500
|
-
if (!
|
|
13637
|
+
if (!existsSync18(join19(CC_CLAW_HOME, ".env"))) {
|
|
13501
13638
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
13502
13639
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
13503
13640
|
process.exitCode = 1;
|
|
@@ -13695,13 +13832,13 @@ var init_daemon = __esm({
|
|
|
13695
13832
|
});
|
|
13696
13833
|
|
|
13697
13834
|
// src/cli/resolve-chat.ts
|
|
13698
|
-
import { readFileSync as
|
|
13835
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
13699
13836
|
function resolveChatId(globalOpts) {
|
|
13700
13837
|
const explicit = globalOpts.chat;
|
|
13701
13838
|
if (explicit) return explicit;
|
|
13702
13839
|
if (_cachedDefault) return _cachedDefault;
|
|
13703
13840
|
try {
|
|
13704
|
-
const content =
|
|
13841
|
+
const content = readFileSync13(ENV_PATH, "utf-8");
|
|
13705
13842
|
const match = content.match(/^ALLOWED_CHAT_ID=(.+)$/m);
|
|
13706
13843
|
if (match) {
|
|
13707
13844
|
_cachedDefault = match[1].split(",")[0].trim();
|
|
@@ -13720,106 +13857,6 @@ var init_resolve_chat = __esm({
|
|
|
13720
13857
|
}
|
|
13721
13858
|
});
|
|
13722
13859
|
|
|
13723
|
-
// src/cli/api-client.ts
|
|
13724
|
-
var api_client_exports = {};
|
|
13725
|
-
__export(api_client_exports, {
|
|
13726
|
-
apiGet: () => apiGet,
|
|
13727
|
-
apiPost: () => apiPost,
|
|
13728
|
-
isDaemonRunning: () => isDaemonRunning
|
|
13729
|
-
});
|
|
13730
|
-
import { readFileSync as readFileSync13, existsSync as existsSync18 } from "fs";
|
|
13731
|
-
import { request as httpRequest } from "http";
|
|
13732
|
-
function getToken() {
|
|
13733
|
-
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
13734
|
-
try {
|
|
13735
|
-
if (existsSync18(TOKEN_PATH)) return readFileSync13(TOKEN_PATH, "utf-8").trim();
|
|
13736
|
-
} catch {
|
|
13737
|
-
}
|
|
13738
|
-
return null;
|
|
13739
|
-
}
|
|
13740
|
-
async function isDaemonRunning() {
|
|
13741
|
-
try {
|
|
13742
|
-
const res = await apiGet("/api/health");
|
|
13743
|
-
return res.ok;
|
|
13744
|
-
} catch {
|
|
13745
|
-
return false;
|
|
13746
|
-
}
|
|
13747
|
-
}
|
|
13748
|
-
async function apiGet(path) {
|
|
13749
|
-
const token = getToken();
|
|
13750
|
-
return new Promise((resolve, reject) => {
|
|
13751
|
-
const url = new URL(path, BASE_URL);
|
|
13752
|
-
const req = httpRequest(url, {
|
|
13753
|
-
method: "GET",
|
|
13754
|
-
headers: token ? { "Authorization": `Bearer ${token}` } : {},
|
|
13755
|
-
timeout: 3e3
|
|
13756
|
-
}, (res) => {
|
|
13757
|
-
const chunks = [];
|
|
13758
|
-
res.on("data", (c) => chunks.push(c));
|
|
13759
|
-
res.on("end", () => {
|
|
13760
|
-
const body = Buffer.concat(chunks).toString();
|
|
13761
|
-
try {
|
|
13762
|
-
const data = JSON.parse(body);
|
|
13763
|
-
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13764
|
-
} catch {
|
|
13765
|
-
resolve({ ok: false, status: res.statusCode ?? 0, data: body });
|
|
13766
|
-
}
|
|
13767
|
-
});
|
|
13768
|
-
});
|
|
13769
|
-
req.on("error", reject);
|
|
13770
|
-
req.on("timeout", () => {
|
|
13771
|
-
req.destroy();
|
|
13772
|
-
reject(new Error("Request timed out"));
|
|
13773
|
-
});
|
|
13774
|
-
req.end();
|
|
13775
|
-
});
|
|
13776
|
-
}
|
|
13777
|
-
async function apiPost(path, body) {
|
|
13778
|
-
const token = getToken();
|
|
13779
|
-
const payload = JSON.stringify(body);
|
|
13780
|
-
return new Promise((resolve, reject) => {
|
|
13781
|
-
const url = new URL(path, BASE_URL);
|
|
13782
|
-
const req = httpRequest(url, {
|
|
13783
|
-
method: "POST",
|
|
13784
|
-
headers: {
|
|
13785
|
-
"Content-Type": "application/json",
|
|
13786
|
-
"Content-Length": Buffer.byteLength(payload).toString(),
|
|
13787
|
-
...token ? { "Authorization": `Bearer ${token}` } : {}
|
|
13788
|
-
},
|
|
13789
|
-
timeout: 3e4
|
|
13790
|
-
}, (res) => {
|
|
13791
|
-
const chunks = [];
|
|
13792
|
-
res.on("data", (c) => chunks.push(c));
|
|
13793
|
-
res.on("end", () => {
|
|
13794
|
-
const responseBody = Buffer.concat(chunks).toString();
|
|
13795
|
-
try {
|
|
13796
|
-
const data = JSON.parse(responseBody);
|
|
13797
|
-
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13798
|
-
} catch {
|
|
13799
|
-
resolve({ ok: false, status: res.statusCode ?? 0, data: responseBody });
|
|
13800
|
-
}
|
|
13801
|
-
});
|
|
13802
|
-
});
|
|
13803
|
-
req.on("error", reject);
|
|
13804
|
-
req.on("timeout", () => {
|
|
13805
|
-
req.destroy();
|
|
13806
|
-
reject(new Error("Request timed out"));
|
|
13807
|
-
});
|
|
13808
|
-
req.write(payload);
|
|
13809
|
-
req.end();
|
|
13810
|
-
});
|
|
13811
|
-
}
|
|
13812
|
-
var TOKEN_PATH, DEFAULT_PORT, BASE_URL;
|
|
13813
|
-
var init_api_client = __esm({
|
|
13814
|
-
"src/cli/api-client.ts"() {
|
|
13815
|
-
"use strict";
|
|
13816
|
-
init_paths();
|
|
13817
|
-
TOKEN_PATH = `${DATA_PATH}/api-token`;
|
|
13818
|
-
DEFAULT_PORT = parseInt(process.env.DASHBOARD_PORT ?? "3141", 10);
|
|
13819
|
-
BASE_URL = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
13820
|
-
}
|
|
13821
|
-
});
|
|
13822
|
-
|
|
13823
13860
|
// src/cli/commands/status.ts
|
|
13824
13861
|
var status_exports = {};
|
|
13825
13862
|
__export(status_exports, {
|
|
@@ -13917,7 +13954,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
13917
13954
|
kvLine("Voice", s.voice ? success("on") : muted("off"))
|
|
13918
13955
|
];
|
|
13919
13956
|
if (localOpts.deep) {
|
|
13920
|
-
lines.push(kvLine("Daemon", s.daemon.running ? success(`running${s.daemon.uptime_seconds ? ` (uptime ${
|
|
13957
|
+
lines.push(kvLine("Daemon", s.daemon.running ? success(`running${s.daemon.uptime_seconds ? ` (uptime ${formatUptime2(s.daemon.uptime_seconds)})` : ""}`) : error2("offline")));
|
|
13921
13958
|
}
|
|
13922
13959
|
lines.push(
|
|
13923
13960
|
"",
|
|
@@ -13935,7 +13972,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
13935
13972
|
process.exit(1);
|
|
13936
13973
|
}
|
|
13937
13974
|
}
|
|
13938
|
-
function
|
|
13975
|
+
function formatUptime2(seconds) {
|
|
13939
13976
|
if (seconds < 60) return `${seconds}s`;
|
|
13940
13977
|
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
13941
13978
|
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
@@ -14007,10 +14044,12 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14007
14044
|
const { isDaemonRunning: isDaemonRunning2, apiGet: apiGet2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
14008
14045
|
const running = await isDaemonRunning2();
|
|
14009
14046
|
if (running) {
|
|
14010
|
-
checks.push({ name: "Daemon", status: "ok", message: "running" });
|
|
14011
14047
|
try {
|
|
14012
14048
|
const health = await apiGet2("/api/health");
|
|
14013
14049
|
const daemonVersion = health.data?.version;
|
|
14050
|
+
const uptimeSec = health.data?.uptime;
|
|
14051
|
+
const uptimeStr = uptimeSec ? ` (uptime ${formatUptime3(uptimeSec)})` : "";
|
|
14052
|
+
checks.push({ name: "Daemon", status: "ok", message: `running${uptimeStr}` });
|
|
14014
14053
|
if (daemonVersion && daemonVersion !== VERSION) {
|
|
14015
14054
|
checks.push({
|
|
14016
14055
|
name: "Version",
|
|
@@ -14022,6 +14061,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14022
14061
|
checks.push({ name: "Version", status: "ok", message: `v${VERSION}` });
|
|
14023
14062
|
}
|
|
14024
14063
|
} catch {
|
|
14064
|
+
checks.push({ name: "Daemon", status: "ok", message: "running" });
|
|
14025
14065
|
}
|
|
14026
14066
|
} else {
|
|
14027
14067
|
checks.push({ name: "Daemon", status: "warning", message: "not running", fix: "cc-claw service start" });
|
|
@@ -14160,6 +14200,13 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14160
14200
|
});
|
|
14161
14201
|
process.exit(errors > 0 ? 1 : warnings > 0 ? 2 : 0);
|
|
14162
14202
|
}
|
|
14203
|
+
function formatUptime3(seconds) {
|
|
14204
|
+
seconds = Math.floor(seconds);
|
|
14205
|
+
if (seconds < 60) return `${seconds}s`;
|
|
14206
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
14207
|
+
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
14208
|
+
return `${Math.floor(seconds / 86400)}d ${Math.floor(seconds % 86400 / 3600)}h`;
|
|
14209
|
+
}
|
|
14163
14210
|
var init_doctor = __esm({
|
|
14164
14211
|
"src/cli/commands/doctor.ts"() {
|
|
14165
14212
|
"use strict";
|
package/package.json
CHANGED