@cosmicstack/mercury-agent 1.0.4 → 1.0.6
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/index.js +101 -77
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2409,27 +2409,53 @@ var CLIChannel = class extends BaseChannel {
|
|
|
2409
2409
|
this.endOutput();
|
|
2410
2410
|
return full2;
|
|
2411
2411
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2412
|
+
const startTime = Date.now();
|
|
2413
|
+
const headerLines = ["", chalk3.cyan(` ${this.agentName}:`), ""];
|
|
2414
|
+
for (const line of headerLines) {
|
|
2415
|
+
console.log(line);
|
|
2416
|
+
}
|
|
2417
|
+
const indent = " ";
|
|
2418
|
+
const cols = process.stdout.columns || 80;
|
|
2419
|
+
const contentCols = Math.max(1, cols - indent.length);
|
|
2420
|
+
let visualLines = headerLines.length;
|
|
2421
|
+
let pendingIndent = true;
|
|
2422
|
+
let lineLen = 0;
|
|
2416
2423
|
let full = "";
|
|
2417
2424
|
for await (const chunk of content) {
|
|
2418
|
-
process.stdout.write(chunk);
|
|
2419
2425
|
full += chunk;
|
|
2426
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
2427
|
+
const ch = chunk[i];
|
|
2428
|
+
if (ch === "\n") {
|
|
2429
|
+
visualLines += Math.max(1, Math.ceil((lineLen + indent.length) / cols));
|
|
2430
|
+
process.stdout.write("\n");
|
|
2431
|
+
lineLen = 0;
|
|
2432
|
+
pendingIndent = true;
|
|
2433
|
+
} else {
|
|
2434
|
+
if (pendingIndent) {
|
|
2435
|
+
process.stdout.write(indent);
|
|
2436
|
+
pendingIndent = false;
|
|
2437
|
+
}
|
|
2438
|
+
process.stdout.write(ch);
|
|
2439
|
+
lineLen++;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2420
2442
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
process.stdout.write("\
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
return full;
|
|
2443
|
+
if (lineLen > 0) {
|
|
2444
|
+
visualLines += Math.max(1, Math.ceil((lineLen + indent.length) / cols));
|
|
2445
|
+
process.stdout.write("\n");
|
|
2446
|
+
} else {
|
|
2447
|
+
visualLines += 1;
|
|
2427
2448
|
}
|
|
2428
|
-
|
|
2449
|
+
this.streamActive = false;
|
|
2450
|
+
process.stdout.write(`\x1B[${visualLines}A`);
|
|
2429
2451
|
process.stdout.write("\x1B[J");
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2452
|
+
if (full.trim()) {
|
|
2453
|
+
const block = this.formatBlock(this.agentName, "", full);
|
|
2454
|
+
for (const line of block) {
|
|
2455
|
+
console.log(line);
|
|
2456
|
+
}
|
|
2457
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
2458
|
+
console.log(chalk3.dim(" " + "\u2500".repeat(50 - elapsed.length - 4) + " " + elapsed + "s"));
|
|
2433
2459
|
}
|
|
2434
2460
|
this.endOutput();
|
|
2435
2461
|
return full;
|
|
@@ -7491,21 +7517,20 @@ function isProcessRunning(pid) {
|
|
|
7491
7517
|
function getDaemonStatus() {
|
|
7492
7518
|
const pid = readPid();
|
|
7493
7519
|
if (!pid) return { running: false, pid: null, logPath: logPath() };
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
function startBackground() {
|
|
7497
|
-
const status = getDaemonStatus();
|
|
7498
|
-
if (status.running && status.pid) {
|
|
7499
|
-
console.log(chalk5.yellow(` Mercury is already running (PID: ${status.pid})`));
|
|
7500
|
-
console.log(chalk5.dim(` Use \`mercury stop\` to stop it first.`));
|
|
7501
|
-
console.log("");
|
|
7502
|
-
process2.exit(1);
|
|
7503
|
-
}
|
|
7504
|
-
if (status.pid && !status.running) {
|
|
7520
|
+
const running = isProcessRunning(pid);
|
|
7521
|
+
if (!running) {
|
|
7505
7522
|
try {
|
|
7506
7523
|
unlinkSync4(pidPath());
|
|
7507
7524
|
} catch {
|
|
7508
7525
|
}
|
|
7526
|
+
return { running: false, pid: null, logPath: logPath() };
|
|
7527
|
+
}
|
|
7528
|
+
return { running, pid, logPath: logPath() };
|
|
7529
|
+
}
|
|
7530
|
+
function ensureDaemonRunning() {
|
|
7531
|
+
const status = getDaemonStatus();
|
|
7532
|
+
if (status.running && status.pid) {
|
|
7533
|
+
return { pid: status.pid, fresh: false };
|
|
7509
7534
|
}
|
|
7510
7535
|
const home = getMercuryHome();
|
|
7511
7536
|
if (!existsSync17(home)) {
|
|
@@ -7521,13 +7546,25 @@ function startBackground() {
|
|
|
7521
7546
|
windowsHide: isWin
|
|
7522
7547
|
});
|
|
7523
7548
|
child.unref();
|
|
7549
|
+
if (!child.pid) {
|
|
7550
|
+
throw new Error("Failed to spawn daemon process");
|
|
7551
|
+
}
|
|
7524
7552
|
writeFileSync12(pidPath(), String(child.pid));
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7553
|
+
return { pid: child.pid, fresh: true };
|
|
7554
|
+
}
|
|
7555
|
+
function startBackground() {
|
|
7556
|
+
try {
|
|
7557
|
+
const result = ensureDaemonRunning();
|
|
7558
|
+
console.log("");
|
|
7559
|
+
console.log(chalk5.green(` Mercury started in background (PID: ${result.pid})`));
|
|
7560
|
+
console.log(chalk5.dim(` Logs: ${logPath()}`));
|
|
7561
|
+
console.log(chalk5.dim(` Use \`mercury stop\` to stop.`));
|
|
7562
|
+
console.log(chalk5.dim(` Use \`mercury logs\` to view logs.`));
|
|
7563
|
+
console.log("");
|
|
7564
|
+
} catch (err) {
|
|
7565
|
+
console.log(chalk5.red(` Failed to start: ${err.message}`));
|
|
7566
|
+
process2.exit(1);
|
|
7567
|
+
}
|
|
7531
7568
|
}
|
|
7532
7569
|
function stopDaemon() {
|
|
7533
7570
|
const status = getDaemonStatus();
|
|
@@ -7578,11 +7615,6 @@ function restartDaemon() {
|
|
|
7578
7615
|
} catch {
|
|
7579
7616
|
}
|
|
7580
7617
|
console.log(chalk5.green(" Mercury stopped."));
|
|
7581
|
-
} else if (status.pid) {
|
|
7582
|
-
try {
|
|
7583
|
-
unlinkSync4(pidPath());
|
|
7584
|
-
} catch {
|
|
7585
|
-
}
|
|
7586
7618
|
}
|
|
7587
7619
|
console.log(chalk5.yellow(" Starting Mercury..."));
|
|
7588
7620
|
startBackground();
|
|
@@ -7595,40 +7627,13 @@ function showLogs() {
|
|
|
7595
7627
|
return;
|
|
7596
7628
|
}
|
|
7597
7629
|
const content = readFileSync11(logFile, "utf-8");
|
|
7598
|
-
const lines = content.split(
|
|
7630
|
+
const lines = content.split(/\r?\n/).slice(-100);
|
|
7599
7631
|
console.log(lines.join("\n"));
|
|
7600
7632
|
}
|
|
7601
7633
|
function tryAutoDaemonize() {
|
|
7602
7634
|
try {
|
|
7603
|
-
const
|
|
7604
|
-
|
|
7605
|
-
return true;
|
|
7606
|
-
}
|
|
7607
|
-
if (status.pid && !status.running) {
|
|
7608
|
-
try {
|
|
7609
|
-
unlinkSync4(pidPath());
|
|
7610
|
-
} catch {
|
|
7611
|
-
}
|
|
7612
|
-
}
|
|
7613
|
-
const home = getMercuryHome();
|
|
7614
|
-
if (!existsSync17(home)) {
|
|
7615
|
-
mkdirSync10(home, { recursive: true });
|
|
7616
|
-
}
|
|
7617
|
-
const logFile = logPath();
|
|
7618
|
-
const isWin = process2.platform === "win32";
|
|
7619
|
-
const outFd = openSync(logFile, "a");
|
|
7620
|
-
const child = spawn(process2.execPath, [process2.argv[1], "start", "--daemon"], {
|
|
7621
|
-
detached: true,
|
|
7622
|
-
stdio: ["ignore", outFd, outFd],
|
|
7623
|
-
env: { ...process2.env },
|
|
7624
|
-
windowsHide: isWin
|
|
7625
|
-
});
|
|
7626
|
-
child.unref();
|
|
7627
|
-
if (!child.pid) {
|
|
7628
|
-
return false;
|
|
7629
|
-
}
|
|
7630
|
-
writeFileSync12(pidPath(), String(child.pid));
|
|
7631
|
-
return true;
|
|
7635
|
+
const result = ensureDaemonRunning();
|
|
7636
|
+
return result.pid > 0;
|
|
7632
7637
|
} catch {
|
|
7633
7638
|
return false;
|
|
7634
7639
|
}
|
|
@@ -8798,7 +8803,7 @@ async function configure(existingConfig) {
|
|
|
8798
8803
|
}
|
|
8799
8804
|
function autoDaemonize() {
|
|
8800
8805
|
const daemon = getDaemonStatus();
|
|
8801
|
-
if (daemon.running) {
|
|
8806
|
+
if (daemon.running && daemon.pid) {
|
|
8802
8807
|
return;
|
|
8803
8808
|
}
|
|
8804
8809
|
console.log(chalk7.dim(" Setting up background mode..."));
|
|
@@ -8816,7 +8821,7 @@ function autoDaemonize() {
|
|
|
8816
8821
|
console.log(chalk7.green(" \u2713 Auto-starts on login. Auto-restarts on crash."));
|
|
8817
8822
|
console.log(chalk7.dim(" Use `mercury stop` to stop. `mercury restart` to restart."));
|
|
8818
8823
|
} else {
|
|
8819
|
-
console.log(chalk7.
|
|
8824
|
+
console.log(chalk7.yellow(" Background mode not available. Run `mercury start` to set it up."));
|
|
8820
8825
|
}
|
|
8821
8826
|
console.log("");
|
|
8822
8827
|
}
|
|
@@ -9006,6 +9011,22 @@ async function runAgent(isDaemon = false) {
|
|
|
9006
9011
|
};
|
|
9007
9012
|
process.on("SIGINT", shutdown);
|
|
9008
9013
|
process.on("SIGTERM", shutdown);
|
|
9014
|
+
if (!isDaemon && process.platform !== "win32") {
|
|
9015
|
+
process.on("SIGHUP", () => {
|
|
9016
|
+
logger.info("SIGHUP received \u2014 terminal closed. Daemonizing.");
|
|
9017
|
+
try {
|
|
9018
|
+
const result = tryAutoDaemonize();
|
|
9019
|
+
if (result) {
|
|
9020
|
+
logger.info(`Forked daemon. Foreground process exiting.`);
|
|
9021
|
+
} else {
|
|
9022
|
+
logger.warn("SIGHUP received but daemonization failed. Shutting down.");
|
|
9023
|
+
}
|
|
9024
|
+
} catch {
|
|
9025
|
+
logger.warn("SIGHUP received but daemonization failed. Shutting down.");
|
|
9026
|
+
}
|
|
9027
|
+
process.exit(0);
|
|
9028
|
+
});
|
|
9029
|
+
}
|
|
9009
9030
|
}
|
|
9010
9031
|
var program = new Command();
|
|
9011
9032
|
program.name("mercury").description("Mercury \u2014 Soul-driven AI agent with permission-hardened tools, token budgets, and multi-channel access.").version(pkgVersion).option("-v, --verbose", "Show debug logs").action(async () => {
|
|
@@ -9014,22 +9035,24 @@ program.name("mercury").description("Mercury \u2014 Soul-driven AI agent with pe
|
|
|
9014
9035
|
autoDaemonize();
|
|
9015
9036
|
return;
|
|
9016
9037
|
}
|
|
9038
|
+
autoDaemonize();
|
|
9017
9039
|
await runAgent();
|
|
9018
9040
|
});
|
|
9019
|
-
program.command("start").description("Start Mercury
|
|
9041
|
+
program.command("start").description("Start Mercury \u2014 runs as a daemon by default, use --foreground to attach to terminal").option("-v, --verbose", "Show debug logs").option("-f, --foreground", "Run in foreground (attached to terminal)").option("-d, --detached", "Run in background (daemon mode) \u2014 same as default").option("--daemon", "Internal flag for daemon child process").action(async (opts) => {
|
|
9020
9042
|
if (opts.daemon) {
|
|
9021
9043
|
await runWithWatchdog(() => runAgent(true));
|
|
9022
9044
|
return;
|
|
9023
9045
|
}
|
|
9024
|
-
if (opts.detached) {
|
|
9025
|
-
startBackground();
|
|
9026
|
-
return;
|
|
9027
|
-
}
|
|
9028
9046
|
if (!isSetupComplete()) {
|
|
9029
9047
|
await configure();
|
|
9048
|
+
autoDaemonize();
|
|
9030
9049
|
return;
|
|
9031
9050
|
}
|
|
9032
|
-
|
|
9051
|
+
if (opts.foreground) {
|
|
9052
|
+
await runAgent();
|
|
9053
|
+
return;
|
|
9054
|
+
}
|
|
9055
|
+
startBackground();
|
|
9033
9056
|
});
|
|
9034
9057
|
program.command("stop").description("Stop a background Mercury process").action(() => {
|
|
9035
9058
|
stopDaemon();
|
|
@@ -9037,9 +9060,11 @@ program.command("stop").description("Stop a background Mercury process").action(
|
|
|
9037
9060
|
program.command("restart").description("Restart a background Mercury process").action(() => {
|
|
9038
9061
|
restartDaemon();
|
|
9039
9062
|
});
|
|
9040
|
-
program.command("up").description("
|
|
9063
|
+
program.command("up").description("Start Mercury as a persistent daemon (same as `mercury start`)").action(async () => {
|
|
9041
9064
|
if (!isSetupComplete()) {
|
|
9042
9065
|
await configure();
|
|
9066
|
+
autoDaemonize();
|
|
9067
|
+
return;
|
|
9043
9068
|
}
|
|
9044
9069
|
const daemon = getDaemonStatus();
|
|
9045
9070
|
if (daemon.running && daemon.pid) {
|
|
@@ -9054,7 +9079,6 @@ program.command("up").description("Ensure Mercury is running persistently \u2014
|
|
|
9054
9079
|
console.log(chalk7.cyan(" Installing Mercury as a system service..."));
|
|
9055
9080
|
installService();
|
|
9056
9081
|
}
|
|
9057
|
-
console.log(chalk7.cyan(" Starting Mercury in background..."));
|
|
9058
9082
|
startBackground();
|
|
9059
9083
|
});
|
|
9060
9084
|
program.command("logs").description("Show recent daemon logs").action(() => {
|