cc-claw 0.5.0 → 0.5.2
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 +302 -215
- 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.2" : (() => {
|
|
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;
|
|
@@ -8702,6 +8702,9 @@ var init_format_time = __esm({
|
|
|
8702
8702
|
});
|
|
8703
8703
|
|
|
8704
8704
|
// src/intent/classify.ts
|
|
8705
|
+
function getIntentStats() {
|
|
8706
|
+
return { ...intentCounts };
|
|
8707
|
+
}
|
|
8705
8708
|
function classifyIntent(text, chatId) {
|
|
8706
8709
|
const trimmed = text.trim();
|
|
8707
8710
|
if (trimmed.startsWith(">>")) return "agentic";
|
|
@@ -8710,6 +8713,7 @@ function classifyIntent(text, chatId) {
|
|
|
8710
8713
|
for (const pattern of AGENTIC_PATTERNS) {
|
|
8711
8714
|
if (pattern.test(trimmed)) {
|
|
8712
8715
|
log(`[intent] "${trimmed.slice(0, 30)}..." -> agentic (pattern: ${pattern})`);
|
|
8716
|
+
intentCounts.agentic++;
|
|
8713
8717
|
return "agentic";
|
|
8714
8718
|
}
|
|
8715
8719
|
}
|
|
@@ -8721,6 +8725,7 @@ function classifyIntent(text, chatId) {
|
|
|
8721
8725
|
if (elapsed < 12e4) {
|
|
8722
8726
|
if (trimmed.length < 30) {
|
|
8723
8727
|
log(`[intent] "${trimmed.slice(0, 30)}" -> agentic (active session, ${(elapsed / 1e3).toFixed(0)}s ago)`);
|
|
8728
|
+
intentCounts.agentic++;
|
|
8724
8729
|
return "agentic";
|
|
8725
8730
|
}
|
|
8726
8731
|
}
|
|
@@ -8728,22 +8733,26 @@ function classifyIntent(text, chatId) {
|
|
|
8728
8733
|
}
|
|
8729
8734
|
if (CHAT_EXACT.has(lower)) {
|
|
8730
8735
|
log(`[intent] "${lower}" -> chat (exact match)`);
|
|
8736
|
+
intentCounts.chat++;
|
|
8731
8737
|
return "chat";
|
|
8732
8738
|
}
|
|
8733
8739
|
if (trimmed.length <= 4 && /^[\p{Emoji}\s]+$/u.test(trimmed)) {
|
|
8734
8740
|
log(`[intent] "${trimmed}" -> chat (emoji-only)`);
|
|
8741
|
+
intentCounts.chat++;
|
|
8735
8742
|
return "chat";
|
|
8736
8743
|
}
|
|
8737
8744
|
log(`[intent] "${trimmed.slice(0, 30)}..." -> agentic (default)`);
|
|
8745
|
+
intentCounts.agentic++;
|
|
8738
8746
|
return "agentic";
|
|
8739
8747
|
}
|
|
8740
|
-
var CHAT_EXACT, AGENTIC_PATTERNS;
|
|
8748
|
+
var intentCounts, CHAT_EXACT, AGENTIC_PATTERNS;
|
|
8741
8749
|
var init_classify = __esm({
|
|
8742
8750
|
"src/intent/classify.ts"() {
|
|
8743
8751
|
"use strict";
|
|
8744
8752
|
init_store4();
|
|
8745
8753
|
init_session_log();
|
|
8746
8754
|
init_log();
|
|
8755
|
+
intentCounts = { chat: 0, agentic: 0 };
|
|
8747
8756
|
CHAT_EXACT = /* @__PURE__ */ new Set([
|
|
8748
8757
|
"hey",
|
|
8749
8758
|
"hi",
|
|
@@ -9991,6 +10000,10 @@ function formatModelShort(modelId) {
|
|
|
9991
10000
|
};
|
|
9992
10001
|
return MAP[modelId] ?? modelId;
|
|
9993
10002
|
}
|
|
10003
|
+
function buildBar(pct) {
|
|
10004
|
+
const filled = Math.round(Math.min(100, Math.max(0, pct)) / 100 * 8);
|
|
10005
|
+
return "\u2593".repeat(filled) + "\u2591".repeat(8 - filled);
|
|
10006
|
+
}
|
|
9994
10007
|
function capitalize(s) {
|
|
9995
10008
|
if (s === "extra_high") return "xHigh";
|
|
9996
10009
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -10204,32 +10217,58 @@ Tap to toggle:`,
|
|
|
10204
10217
|
const voice2 = isVoiceEnabled(chatId);
|
|
10205
10218
|
const usage2 = getUsage(chatId);
|
|
10206
10219
|
const thinking2 = getThinkingLevel(chatId);
|
|
10207
|
-
const
|
|
10208
|
-
const
|
|
10220
|
+
const mode = getMode(chatId);
|
|
10221
|
+
const modelSig = getModelSignature(chatId);
|
|
10209
10222
|
const contextMax = adapter?.contextWindow[model2] ?? 2e5;
|
|
10210
10223
|
const contextUsed = usage2.last_input_tokens + usage2.last_cache_read_tokens;
|
|
10211
|
-
const contextPct = contextMax > 0 ?
|
|
10224
|
+
const contextPct = contextMax > 0 ? contextUsed / contextMax * 100 : 0;
|
|
10225
|
+
const ctxBar = buildBar(contextPct);
|
|
10212
10226
|
const usedK = (contextUsed / 1e3).toFixed(1);
|
|
10213
10227
|
const maxK = (contextMax / 1e3).toFixed(0);
|
|
10214
|
-
const
|
|
10228
|
+
const bootRow = getDb().prepare("SELECT value FROM meta WHERE key = 'boot_time'").get();
|
|
10229
|
+
let uptimeStr = "unknown";
|
|
10230
|
+
if (bootRow) {
|
|
10231
|
+
const bootMs = (/* @__PURE__ */ new Date(bootRow.value + "Z")).getTime();
|
|
10232
|
+
const sec = Math.floor((Date.now() - bootMs) / 1e3);
|
|
10233
|
+
uptimeStr = sec < 60 ? `${sec}s` : sec < 3600 ? `${Math.floor(sec / 60)}m` : sec < 86400 ? `${Math.floor(sec / 3600)}h ${Math.floor(sec % 3600 / 60)}m` : `${Math.floor(sec / 86400)}d ${Math.floor(sec % 86400 / 3600)}h`;
|
|
10234
|
+
}
|
|
10235
|
+
let limitsLine = "";
|
|
10236
|
+
if (adapter) {
|
|
10237
|
+
const limits2 = getAllBackendLimits().filter((l) => l.backend === adapter.id);
|
|
10238
|
+
for (const lim of limits2) {
|
|
10239
|
+
if (!lim.max_input_tokens) continue;
|
|
10240
|
+
const u = getBackendUsageInWindow(adapter.id, lim.window);
|
|
10241
|
+
const pct = u.input_tokens / lim.max_input_tokens * 100;
|
|
10242
|
+
const remaining = Math.max(0, lim.max_input_tokens - u.input_tokens);
|
|
10243
|
+
const remK = (remaining / 1e3).toFixed(0);
|
|
10244
|
+
limitsLine += `
|
|
10245
|
+
\u{1F4CA} ${lim.window}: ${buildBar(pct)} ${pct.toFixed(0)}% used \xB7 ${remK}K left`;
|
|
10246
|
+
}
|
|
10247
|
+
}
|
|
10248
|
+
const iStats = getIntentStats();
|
|
10249
|
+
const iTotal = iStats.chat + iStats.agentic;
|
|
10250
|
+
const intentLine = iTotal > 0 ? `\u26A1 ${iStats.chat} chat \xB7 ${iStats.agentic} agentic (${(iStats.chat / iTotal * 100).toFixed(0)}% fast-path)` : `\u26A1 No messages classified yet`;
|
|
10215
10251
|
const lines = [
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10252
|
+
`\u{1F43E} CC-Claw v${VERSION}`,
|
|
10253
|
+
`\u23F1 Uptime: ${uptimeStr}`,
|
|
10254
|
+
``,
|
|
10255
|
+
`\u2501\u2501 Engine \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
10256
|
+
`\u{1F9E0} ${adapter?.displayName ?? backendId ?? "not set"} \xB7 ${formatModelShort(model2)}`,
|
|
10257
|
+
`\u{1F4AD} Think: ${thinking2} \xB7 Mode: ${mode}`,
|
|
10258
|
+
`\u{1F507} Voice: ${voice2 ? "on" : "off"} \xB7 Sig: ${modelSig}`,
|
|
10259
|
+
``,
|
|
10260
|
+
`\u2501\u2501 Session \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
10261
|
+
`\u{1F4CB} ${sessionId ? sessionId.slice(0, 12) + "..." : "no active session"}`,
|
|
10262
|
+
`\u{1F4C1} ${cwd ?? "default workspace"}`,
|
|
10263
|
+
`\u{1F4D0} Context: ${ctxBar} ${usedK}K/${maxK}K (${contextPct.toFixed(1)}%)`,
|
|
10264
|
+
``,
|
|
10265
|
+
`\u2501\u2501 Usage \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
10266
|
+
`\u{1F4E8} ${usage2.request_count} requests \xB7 ${(usage2.input_tokens / 1e3).toFixed(0)}K in \xB7 ${(usage2.output_tokens / 1e3).toFixed(0)}K out`,
|
|
10267
|
+
`\u{1F4BE} ${(usage2.cache_read_tokens / 1e3).toFixed(0)}K cached`,
|
|
10268
|
+
...limitsLine ? [limitsLine] : [],
|
|
10269
|
+
``,
|
|
10270
|
+
`\u2501\u2501 Intelligence \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
10271
|
+
intentLine
|
|
10233
10272
|
];
|
|
10234
10273
|
await channel.sendText(chatId, lines.join("\n"), "plain");
|
|
10235
10274
|
break;
|
|
@@ -10602,13 +10641,19 @@ ${lines.join("\n")}`, "plain");
|
|
|
10602
10641
|
}
|
|
10603
10642
|
case "model_signature": {
|
|
10604
10643
|
const currentSig = getModelSignature(chatId);
|
|
10605
|
-
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
10644
|
+
if (typeof channel.sendKeyboard === "function") {
|
|
10645
|
+
await channel.sendKeyboard(chatId, `Model Signature: ${currentSig === "on" ? "ON" : "OFF"}
|
|
10646
|
+
Appends model + thinking level to each response.`, [
|
|
10647
|
+
[
|
|
10648
|
+
{ label: currentSig === "on" ? "\u2713 On" : "On", data: "model_sig:on" },
|
|
10649
|
+
{ label: currentSig !== "on" ? "\u2713 Off" : "Off", data: "model_sig:off" }
|
|
10650
|
+
]
|
|
10651
|
+
]);
|
|
10652
|
+
} else {
|
|
10653
|
+
const newSig = currentSig === "on" ? "off" : "on";
|
|
10654
|
+
setModelSignature(chatId, newSig);
|
|
10655
|
+
await channel.sendText(chatId, newSig === "on" ? "Model signature enabled." : "Model signature disabled.", "plain");
|
|
10656
|
+
}
|
|
10612
10657
|
break;
|
|
10613
10658
|
}
|
|
10614
10659
|
case "imagine":
|
|
@@ -11251,7 +11296,7 @@ Use /skills to see it.`, "plain");
|
|
|
11251
11296
|
break;
|
|
11252
11297
|
}
|
|
11253
11298
|
case "intent": {
|
|
11254
|
-
const testMsg =
|
|
11299
|
+
const testMsg = commandArgs?.trim() || "hey";
|
|
11255
11300
|
const result = classifyIntent(testMsg, chatId);
|
|
11256
11301
|
await channel.sendText(chatId, `Intent: ${result}
|
|
11257
11302
|
Message: "${testMsg}"`, "plain");
|
|
@@ -12086,6 +12131,14 @@ ${PERM_MODES[chosen]}`,
|
|
|
12086
12131
|
}
|
|
12087
12132
|
await channel.sendText(chatId, `Response style set to: ${selectedStyle}`, "plain");
|
|
12088
12133
|
}
|
|
12134
|
+
} else if (data.startsWith("model_sig:")) {
|
|
12135
|
+
const value = data.slice(10);
|
|
12136
|
+
setModelSignature(chatId, value);
|
|
12137
|
+
await channel.sendText(
|
|
12138
|
+
chatId,
|
|
12139
|
+
value === "on" ? "\u{1F9E0} Model signature enabled. Each response will show the active model and thinking level." : "Model signature disabled.",
|
|
12140
|
+
"plain"
|
|
12141
|
+
);
|
|
12089
12142
|
} else if (data.startsWith("vcfg:")) {
|
|
12090
12143
|
const parts = data.slice(5).split(":");
|
|
12091
12144
|
const action = parts[0];
|
|
@@ -12341,6 +12394,7 @@ var init_router = __esm({
|
|
|
12341
12394
|
init_agent();
|
|
12342
12395
|
init_retry();
|
|
12343
12396
|
init_classify();
|
|
12397
|
+
init_version();
|
|
12344
12398
|
init_image_gen();
|
|
12345
12399
|
init_stt();
|
|
12346
12400
|
init_store4();
|
|
@@ -13312,6 +13366,106 @@ var init_index = __esm({
|
|
|
13312
13366
|
}
|
|
13313
13367
|
});
|
|
13314
13368
|
|
|
13369
|
+
// src/cli/api-client.ts
|
|
13370
|
+
var api_client_exports = {};
|
|
13371
|
+
__export(api_client_exports, {
|
|
13372
|
+
apiGet: () => apiGet,
|
|
13373
|
+
apiPost: () => apiPost,
|
|
13374
|
+
isDaemonRunning: () => isDaemonRunning
|
|
13375
|
+
});
|
|
13376
|
+
import { readFileSync as readFileSync11, existsSync as existsSync17 } from "fs";
|
|
13377
|
+
import { request as httpRequest } from "http";
|
|
13378
|
+
function getToken() {
|
|
13379
|
+
if (process.env.CC_CLAW_API_TOKEN) return process.env.CC_CLAW_API_TOKEN;
|
|
13380
|
+
try {
|
|
13381
|
+
if (existsSync17(TOKEN_PATH)) return readFileSync11(TOKEN_PATH, "utf-8").trim();
|
|
13382
|
+
} catch {
|
|
13383
|
+
}
|
|
13384
|
+
return null;
|
|
13385
|
+
}
|
|
13386
|
+
async function isDaemonRunning() {
|
|
13387
|
+
try {
|
|
13388
|
+
const res = await apiGet("/api/health");
|
|
13389
|
+
return res.ok;
|
|
13390
|
+
} catch {
|
|
13391
|
+
return false;
|
|
13392
|
+
}
|
|
13393
|
+
}
|
|
13394
|
+
async function apiGet(path) {
|
|
13395
|
+
const token = getToken();
|
|
13396
|
+
return new Promise((resolve, reject) => {
|
|
13397
|
+
const url = new URL(path, BASE_URL);
|
|
13398
|
+
const req = httpRequest(url, {
|
|
13399
|
+
method: "GET",
|
|
13400
|
+
headers: token ? { "Authorization": `Bearer ${token}` } : {},
|
|
13401
|
+
timeout: 3e3
|
|
13402
|
+
}, (res) => {
|
|
13403
|
+
const chunks = [];
|
|
13404
|
+
res.on("data", (c) => chunks.push(c));
|
|
13405
|
+
res.on("end", () => {
|
|
13406
|
+
const body = Buffer.concat(chunks).toString();
|
|
13407
|
+
try {
|
|
13408
|
+
const data = JSON.parse(body);
|
|
13409
|
+
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13410
|
+
} catch {
|
|
13411
|
+
resolve({ ok: false, status: res.statusCode ?? 0, data: body });
|
|
13412
|
+
}
|
|
13413
|
+
});
|
|
13414
|
+
});
|
|
13415
|
+
req.on("error", reject);
|
|
13416
|
+
req.on("timeout", () => {
|
|
13417
|
+
req.destroy();
|
|
13418
|
+
reject(new Error("Request timed out"));
|
|
13419
|
+
});
|
|
13420
|
+
req.end();
|
|
13421
|
+
});
|
|
13422
|
+
}
|
|
13423
|
+
async function apiPost(path, body) {
|
|
13424
|
+
const token = getToken();
|
|
13425
|
+
const payload = JSON.stringify(body);
|
|
13426
|
+
return new Promise((resolve, reject) => {
|
|
13427
|
+
const url = new URL(path, BASE_URL);
|
|
13428
|
+
const req = httpRequest(url, {
|
|
13429
|
+
method: "POST",
|
|
13430
|
+
headers: {
|
|
13431
|
+
"Content-Type": "application/json",
|
|
13432
|
+
"Content-Length": Buffer.byteLength(payload).toString(),
|
|
13433
|
+
...token ? { "Authorization": `Bearer ${token}` } : {}
|
|
13434
|
+
},
|
|
13435
|
+
timeout: 3e4
|
|
13436
|
+
}, (res) => {
|
|
13437
|
+
const chunks = [];
|
|
13438
|
+
res.on("data", (c) => chunks.push(c));
|
|
13439
|
+
res.on("end", () => {
|
|
13440
|
+
const responseBody = Buffer.concat(chunks).toString();
|
|
13441
|
+
try {
|
|
13442
|
+
const data = JSON.parse(responseBody);
|
|
13443
|
+
resolve({ ok: res.statusCode === 200, status: res.statusCode ?? 0, data });
|
|
13444
|
+
} catch {
|
|
13445
|
+
resolve({ ok: false, status: res.statusCode ?? 0, data: responseBody });
|
|
13446
|
+
}
|
|
13447
|
+
});
|
|
13448
|
+
});
|
|
13449
|
+
req.on("error", reject);
|
|
13450
|
+
req.on("timeout", () => {
|
|
13451
|
+
req.destroy();
|
|
13452
|
+
reject(new Error("Request timed out"));
|
|
13453
|
+
});
|
|
13454
|
+
req.write(payload);
|
|
13455
|
+
req.end();
|
|
13456
|
+
});
|
|
13457
|
+
}
|
|
13458
|
+
var TOKEN_PATH, DEFAULT_PORT, BASE_URL;
|
|
13459
|
+
var init_api_client = __esm({
|
|
13460
|
+
"src/cli/api-client.ts"() {
|
|
13461
|
+
"use strict";
|
|
13462
|
+
init_paths();
|
|
13463
|
+
TOKEN_PATH = `${DATA_PATH}/api-token`;
|
|
13464
|
+
DEFAULT_PORT = parseInt(process.env.DASHBOARD_PORT ?? "3141", 10);
|
|
13465
|
+
BASE_URL = `http://127.0.0.1:${DEFAULT_PORT}`;
|
|
13466
|
+
}
|
|
13467
|
+
});
|
|
13468
|
+
|
|
13315
13469
|
// src/service.ts
|
|
13316
13470
|
var service_exports = {};
|
|
13317
13471
|
__export(service_exports, {
|
|
@@ -13319,7 +13473,7 @@ __export(service_exports, {
|
|
|
13319
13473
|
serviceStatus: () => serviceStatus,
|
|
13320
13474
|
uninstallService: () => uninstallService
|
|
13321
13475
|
});
|
|
13322
|
-
import { existsSync as
|
|
13476
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3 } from "fs";
|
|
13323
13477
|
import { execFileSync as execFileSync2, execSync as execSync5 } from "child_process";
|
|
13324
13478
|
import { homedir as homedir6, platform } from "os";
|
|
13325
13479
|
import { join as join19, dirname as dirname3 } from "path";
|
|
@@ -13397,9 +13551,9 @@ function generatePlist() {
|
|
|
13397
13551
|
}
|
|
13398
13552
|
function installMacOS() {
|
|
13399
13553
|
const agentsDir = dirname3(PLIST_PATH);
|
|
13400
|
-
if (!
|
|
13401
|
-
if (!
|
|
13402
|
-
if (
|
|
13554
|
+
if (!existsSync18(agentsDir)) mkdirSync8(agentsDir, { recursive: true });
|
|
13555
|
+
if (!existsSync18(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
13556
|
+
if (existsSync18(PLIST_PATH)) {
|
|
13403
13557
|
try {
|
|
13404
13558
|
execFileSync2("launchctl", ["unload", PLIST_PATH]);
|
|
13405
13559
|
} catch {
|
|
@@ -13411,7 +13565,7 @@ function installMacOS() {
|
|
|
13411
13565
|
console.log(" Service loaded and starting.");
|
|
13412
13566
|
}
|
|
13413
13567
|
function uninstallMacOS() {
|
|
13414
|
-
if (!
|
|
13568
|
+
if (!existsSync18(PLIST_PATH)) {
|
|
13415
13569
|
console.log(" No service found to uninstall.");
|
|
13416
13570
|
return;
|
|
13417
13571
|
}
|
|
@@ -13422,6 +13576,24 @@ function uninstallMacOS() {
|
|
|
13422
13576
|
unlinkSync3(PLIST_PATH);
|
|
13423
13577
|
console.log(" Service uninstalled.");
|
|
13424
13578
|
}
|
|
13579
|
+
function formatUptime(seconds) {
|
|
13580
|
+
seconds = Math.floor(seconds);
|
|
13581
|
+
if (seconds < 60) return `${seconds}s`;
|
|
13582
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
13583
|
+
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
13584
|
+
return `${Math.floor(seconds / 86400)}d ${Math.floor(seconds % 86400 / 3600)}h`;
|
|
13585
|
+
}
|
|
13586
|
+
async function getUptimeFromDaemon() {
|
|
13587
|
+
try {
|
|
13588
|
+
const { isDaemonRunning: isDaemonRunning2, apiGet: apiGet2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
13589
|
+
if (!await isDaemonRunning2()) return null;
|
|
13590
|
+
const res = await apiGet2("/api/health");
|
|
13591
|
+
const sec = res.data?.uptime;
|
|
13592
|
+
return sec ? formatUptime(sec) : null;
|
|
13593
|
+
} catch {
|
|
13594
|
+
return null;
|
|
13595
|
+
}
|
|
13596
|
+
}
|
|
13425
13597
|
function statusMacOS() {
|
|
13426
13598
|
try {
|
|
13427
13599
|
const out = execSync5("launchctl list | grep cc-claw", { shell: "/bin/sh", encoding: "utf-8" }).trim();
|
|
@@ -13430,7 +13602,12 @@ function statusMacOS() {
|
|
|
13430
13602
|
const pid = parts[0];
|
|
13431
13603
|
const exitCode = parts[1];
|
|
13432
13604
|
if (pid !== "-") {
|
|
13433
|
-
|
|
13605
|
+
getUptimeFromDaemon().then((uptime) => {
|
|
13606
|
+
const uptimeStr = uptime ? `, uptime ${uptime}` : "";
|
|
13607
|
+
console.log(` Running (PID ${pid}${uptimeStr})`);
|
|
13608
|
+
}).catch(() => {
|
|
13609
|
+
console.log(` Running (PID ${pid})`);
|
|
13610
|
+
});
|
|
13434
13611
|
} else {
|
|
13435
13612
|
console.log(` Not running (last exit code: ${exitCode})`);
|
|
13436
13613
|
}
|
|
@@ -13462,8 +13639,8 @@ WantedBy=default.target
|
|
|
13462
13639
|
`;
|
|
13463
13640
|
}
|
|
13464
13641
|
function installLinux() {
|
|
13465
|
-
if (!
|
|
13466
|
-
if (!
|
|
13642
|
+
if (!existsSync18(SYSTEMD_DIR)) mkdirSync8(SYSTEMD_DIR, { recursive: true });
|
|
13643
|
+
if (!existsSync18(LOGS_PATH)) mkdirSync8(LOGS_PATH, { recursive: true });
|
|
13467
13644
|
writeFileSync6(UNIT_PATH, generateUnit());
|
|
13468
13645
|
console.log(` Installed: ${UNIT_PATH}`);
|
|
13469
13646
|
execFileSync2("systemctl", ["--user", "daemon-reload"]);
|
|
@@ -13472,7 +13649,7 @@ function installLinux() {
|
|
|
13472
13649
|
console.log(" Service enabled and started.");
|
|
13473
13650
|
}
|
|
13474
13651
|
function uninstallLinux() {
|
|
13475
|
-
if (!
|
|
13652
|
+
if (!existsSync18(UNIT_PATH)) {
|
|
13476
13653
|
console.log(" No service found to uninstall.");
|
|
13477
13654
|
return;
|
|
13478
13655
|
}
|
|
@@ -13497,7 +13674,7 @@ function statusLinux() {
|
|
|
13497
13674
|
}
|
|
13498
13675
|
}
|
|
13499
13676
|
function installService() {
|
|
13500
|
-
if (!
|
|
13677
|
+
if (!existsSync18(join19(CC_CLAW_HOME, ".env"))) {
|
|
13501
13678
|
console.error(` Config not found at ${CC_CLAW_HOME}/.env`);
|
|
13502
13679
|
console.error(" Run 'cc-claw setup' before installing the service.");
|
|
13503
13680
|
process.exitCode = 1;
|
|
@@ -13695,13 +13872,13 @@ var init_daemon = __esm({
|
|
|
13695
13872
|
});
|
|
13696
13873
|
|
|
13697
13874
|
// src/cli/resolve-chat.ts
|
|
13698
|
-
import { readFileSync as
|
|
13875
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
13699
13876
|
function resolveChatId(globalOpts) {
|
|
13700
13877
|
const explicit = globalOpts.chat;
|
|
13701
13878
|
if (explicit) return explicit;
|
|
13702
13879
|
if (_cachedDefault) return _cachedDefault;
|
|
13703
13880
|
try {
|
|
13704
|
-
const content =
|
|
13881
|
+
const content = readFileSync13(ENV_PATH, "utf-8");
|
|
13705
13882
|
const match = content.match(/^ALLOWED_CHAT_ID=(.+)$/m);
|
|
13706
13883
|
if (match) {
|
|
13707
13884
|
_cachedDefault = match[1].split(",")[0].trim();
|
|
@@ -13720,106 +13897,6 @@ var init_resolve_chat = __esm({
|
|
|
13720
13897
|
}
|
|
13721
13898
|
});
|
|
13722
13899
|
|
|
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
13900
|
// src/cli/commands/status.ts
|
|
13824
13901
|
var status_exports = {};
|
|
13825
13902
|
__export(status_exports, {
|
|
@@ -13917,7 +13994,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
13917
13994
|
kvLine("Voice", s.voice ? success("on") : muted("off"))
|
|
13918
13995
|
];
|
|
13919
13996
|
if (localOpts.deep) {
|
|
13920
|
-
lines.push(kvLine("Daemon", s.daemon.running ? success(`running${s.daemon.uptime_seconds ? ` (uptime ${
|
|
13997
|
+
lines.push(kvLine("Daemon", s.daemon.running ? success(`running${s.daemon.uptime_seconds ? ` (uptime ${formatUptime2(s.daemon.uptime_seconds)})` : ""}`) : error2("offline")));
|
|
13921
13998
|
}
|
|
13922
13999
|
lines.push(
|
|
13923
14000
|
"",
|
|
@@ -13935,7 +14012,7 @@ async function statusCommand(globalOpts, localOpts) {
|
|
|
13935
14012
|
process.exit(1);
|
|
13936
14013
|
}
|
|
13937
14014
|
}
|
|
13938
|
-
function
|
|
14015
|
+
function formatUptime2(seconds) {
|
|
13939
14016
|
if (seconds < 60) return `${seconds}s`;
|
|
13940
14017
|
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
13941
14018
|
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
@@ -14007,10 +14084,12 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14007
14084
|
const { isDaemonRunning: isDaemonRunning2, apiGet: apiGet2 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
14008
14085
|
const running = await isDaemonRunning2();
|
|
14009
14086
|
if (running) {
|
|
14010
|
-
checks.push({ name: "Daemon", status: "ok", message: "running" });
|
|
14011
14087
|
try {
|
|
14012
14088
|
const health = await apiGet2("/api/health");
|
|
14013
14089
|
const daemonVersion = health.data?.version;
|
|
14090
|
+
const uptimeSec = health.data?.uptime;
|
|
14091
|
+
const uptimeStr = uptimeSec ? ` (uptime ${formatUptime3(uptimeSec)})` : "";
|
|
14092
|
+
checks.push({ name: "Daemon", status: "ok", message: `running${uptimeStr}` });
|
|
14014
14093
|
if (daemonVersion && daemonVersion !== VERSION) {
|
|
14015
14094
|
checks.push({
|
|
14016
14095
|
name: "Version",
|
|
@@ -14022,6 +14101,7 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14022
14101
|
checks.push({ name: "Version", status: "ok", message: `v${VERSION}` });
|
|
14023
14102
|
}
|
|
14024
14103
|
} catch {
|
|
14104
|
+
checks.push({ name: "Daemon", status: "ok", message: "running" });
|
|
14025
14105
|
}
|
|
14026
14106
|
} else {
|
|
14027
14107
|
checks.push({ name: "Daemon", status: "warning", message: "not running", fix: "cc-claw service start" });
|
|
@@ -14160,6 +14240,13 @@ async function doctorCommand(globalOpts, localOpts) {
|
|
|
14160
14240
|
});
|
|
14161
14241
|
process.exit(errors > 0 ? 1 : warnings > 0 ? 2 : 0);
|
|
14162
14242
|
}
|
|
14243
|
+
function formatUptime3(seconds) {
|
|
14244
|
+
seconds = Math.floor(seconds);
|
|
14245
|
+
if (seconds < 60) return `${seconds}s`;
|
|
14246
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
14247
|
+
if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
14248
|
+
return `${Math.floor(seconds / 86400)}d ${Math.floor(seconds % 86400 / 3600)}h`;
|
|
14249
|
+
}
|
|
14163
14250
|
var init_doctor = __esm({
|
|
14164
14251
|
"src/cli/commands/doctor.ts"() {
|
|
14165
14252
|
"use strict";
|
package/package.json
CHANGED