@songsid/agend 2.1.4-beta.9 → 2.1.4
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/README.md +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-cli-instructions.md +2 -2
- package/dist/agent-endpoint.js +1 -1
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/backend/antigravity.d.ts +12 -8
- package/dist/backend/antigravity.js +189 -42
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.d.ts +87 -23
- package/dist/backend/claude-code.js +361 -46
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.d.ts +18 -0
- package/dist/backend/codex.js +139 -5
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/gemini-cli.js +2 -2
- package/dist/backend/gemini-cli.js.map +1 -1
- package/dist/backend/grok.js +2 -2
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro.d.ts +52 -2
- package/dist/backend/kiro.js +267 -12
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/opencode.js +17 -4
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/types.d.ts +122 -3
- package/dist/backend/types.js +5 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/backend-outage.d.ts +61 -0
- package/dist/backend-outage.js +71 -0
- package/dist/backend-outage.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +44 -2
- package/dist/channel/adapters/discord.js +523 -90
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +30 -0
- package/dist/channel/adapters/telegram.js +221 -19
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/agy-mcp-launcher.d.ts +2 -0
- package/dist/channel/agy-mcp-launcher.js +28 -0
- package/dist/channel/agy-mcp-launcher.js.map +1 -0
- package/dist/channel/ipc-bridge.d.ts +2 -1
- package/dist/channel/ipc-bridge.js +33 -4
- package/dist/channel/ipc-bridge.js.map +1 -1
- package/dist/channel/markdown-chunk.d.ts +42 -0
- package/dist/channel/markdown-chunk.js +205 -0
- package/dist/channel/markdown-chunk.js.map +1 -0
- package/dist/channel/mcp-server.js +34 -5
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.js +5 -3
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js +64 -8
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/types.d.ts +31 -1
- package/dist/classic-channel-manager.d.ts +65 -0
- package/dist/classic-channel-manager.js +172 -3
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +124 -83
- package/dist/cli.js.map +1 -1
- package/dist/config-validator.js +13 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +12 -1
- package/dist/config.js.map +1 -1
- package/dist/cross-instance-envelope.d.ts +6 -0
- package/dist/cross-instance-envelope.js +30 -0
- package/dist/cross-instance-envelope.js.map +1 -0
- package/dist/daemon.d.ts +491 -14
- package/dist/daemon.js +2121 -276
- package/dist/daemon.js.map +1 -1
- package/dist/doctor.d.ts +41 -0
- package/dist/doctor.js +267 -0
- package/dist/doctor.js.map +1 -0
- package/dist/fleet-context.d.ts +63 -0
- package/dist/fleet-context.js.map +1 -1
- package/dist/fleet-manager.d.ts +402 -11
- package/dist/fleet-manager.js +2594 -422
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-yaml-slim.d.ts +10 -0
- package/dist/fleet-yaml-slim.js +59 -0
- package/dist/fleet-yaml-slim.js.map +1 -0
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +1 -0
- package/dist/general-knowledge/skills/model-discovery/SKILL.md +63 -16
- package/dist/general-knowledge/skills/session-management/SKILL.md +171 -8
- package/dist/instance-lifecycle.d.ts +114 -1
- package/dist/instance-lifecycle.js +404 -14
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.js +42 -4
- package/dist/instructions.js.map +1 -1
- package/dist/locale.js +1024 -320
- package/dist/locale.js.map +1 -1
- package/dist/login-flows.d.ts +91 -0
- package/dist/login-flows.js +170 -0
- package/dist/login-flows.js.map +1 -0
- package/dist/login-manager.d.ts +63 -0
- package/dist/login-manager.js +134 -0
- package/dist/login-manager.js.map +1 -0
- package/dist/network-family.d.ts +18 -0
- package/dist/network-family.js +20 -0
- package/dist/network-family.js.map +1 -0
- package/dist/outbound-handlers.d.ts +16 -1
- package/dist/outbound-handlers.js +174 -40
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +10 -3
- package/dist/outbound-schemas.js +10 -0
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/pane-input-residue.d.ts +52 -0
- package/dist/pane-input-residue.js +107 -0
- package/dist/pane-input-residue.js.map +1 -0
- package/dist/process-memory.d.ts +6 -0
- package/dist/process-memory.js +45 -0
- package/dist/process-memory.js.map +1 -1
- package/dist/reply-dedup.d.ts +7 -8
- package/dist/reply-dedup.js +0 -0
- package/dist/reply-dedup.js.map +1 -1
- package/dist/restart-progress.d.ts +2 -0
- package/dist/restart-progress.js +3 -0
- package/dist/restart-progress.js.map +1 -1
- package/dist/scheduler/db.d.ts +12 -0
- package/dist/scheduler/db.js +59 -0
- package/dist/scheduler/db.js.map +1 -1
- package/dist/service-installer.d.ts +11 -0
- package/dist/service-installer.js +84 -18
- package/dist/service-installer.js.map +1 -1
- package/dist/settings-api.js +1 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/setup-wizard.js +2 -2
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +30 -0
- package/dist/spawn-gate.js +79 -0
- package/dist/spawn-gate.js.map +1 -0
- package/dist/steer-capability.d.ts +1 -0
- package/dist/steer-capability.js +6 -0
- package/dist/steer-capability.js.map +1 -0
- package/dist/storm-window.d.ts +83 -0
- package/dist/storm-window.js +251 -0
- package/dist/storm-window.js.map +1 -0
- package/dist/tips.d.ts +44 -0
- package/dist/tips.js +355 -0
- package/dist/tips.js.map +1 -0
- package/dist/tmux-manager.d.ts +16 -0
- package/dist/tmux-manager.js +110 -25
- package/dist/tmux-manager.js.map +1 -1
- package/dist/topic-commands.d.ts +31 -7
- package/dist/topic-commands.js +342 -70
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-sources.d.ts +35 -10
- package/dist/transcript-sources.js +190 -38
- package/dist/transcript-sources.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/ui/dashboard.html +55 -32
- package/dist/ui/settings.html +200 -60
- package/dist/ui/view.html +147 -30
- package/dist/usage/format-rich.d.ts +1 -1
- package/dist/usage/format-rich.js +28 -24
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +7 -0
- package/dist/usage/i18n-keys.js +34 -0
- package/dist/usage/i18n-keys.js.map +1 -0
- package/dist/usage/i18n.d.ts +5 -0
- package/dist/usage/i18n.js +27 -0
- package/dist/usage/i18n.js.map +1 -0
- package/dist/usage/providers.d.ts +21 -0
- package/dist/usage/providers.js +153 -75
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/usage-api.d.ts +11 -3
- package/dist/usage/usage-api.js +61 -24
- package/dist/usage/usage-api.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { applyNetworkReliabilityDefaults } from "./network-family.js";
|
|
3
|
+
// Preserve Node's dual-stack Happy Eyeballs behavior, but avoid its 250ms
|
|
4
|
+
// premature-connect failure on WSL/VPN/high-load hosts (#658).
|
|
5
|
+
applyNetworkReliabilityDefaults();
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
import { join, dirname } from "node:path";
|
|
7
8
|
import { SchedulerDb } from "./scheduler/db.js";
|
|
@@ -19,6 +20,8 @@ import { getUpdateSelector, lookupTargetVersion, reportUpdateRestart, shouldSkip
|
|
|
19
20
|
import { clearUpdateMarker, markUpdateInProgress, setUpdateProgressStage } from "./update-marker.js";
|
|
20
21
|
import { acquireFleetLock, releaseProcessFleetLock, setProcessFleetLock } from "./fleet-lock.js";
|
|
21
22
|
import { SYSTEMD_RESTART_TIMEOUT_MS } from "./service-installer.js";
|
|
23
|
+
import { loadRawFleetConfig } from "./config.js";
|
|
24
|
+
import { setLocale, t } from "./locale.js";
|
|
22
25
|
/** Prefix tmux args with -L when socket isolation is active. */
|
|
23
26
|
function tmuxArgs(args) {
|
|
24
27
|
const socket = getTmuxSocketName();
|
|
@@ -28,6 +31,14 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
28
31
|
const __dirname = dirname(__filename);
|
|
29
32
|
const DATA_DIR = getAgendHome();
|
|
30
33
|
const FLEET_CONFIG_PATH = join(DATA_DIR, "fleet.yaml");
|
|
34
|
+
// CLI commands run outside FleetManager. Honor an explicit fleet locale while
|
|
35
|
+
// keeping the historical English CLI default when config is missing/unset.
|
|
36
|
+
try {
|
|
37
|
+
const configuredLocale = loadRawFleetConfig(FLEET_CONFIG_PATH).defaults?.locale;
|
|
38
|
+
if (configuredLocale === "en" || configuredLocale === "zh-TW")
|
|
39
|
+
setLocale(configuredLocale);
|
|
40
|
+
}
|
|
41
|
+
catch { /* malformed or missing config: keep the English CLI default */ }
|
|
31
42
|
const program = new Command();
|
|
32
43
|
function claimFleetSingleton() {
|
|
33
44
|
try {
|
|
@@ -549,7 +560,7 @@ function generateMermaid(rows) {
|
|
|
549
560
|
}
|
|
550
561
|
fleet
|
|
551
562
|
.command("cleanup")
|
|
552
|
-
.description("Remove orphaned instance directories
|
|
563
|
+
.description("Remove orphaned instance directories and stale instance files")
|
|
553
564
|
.option("--dry-run", "List orphans without deleting")
|
|
554
565
|
.action(async (opts) => {
|
|
555
566
|
const { FleetManager } = await import("./fleet-manager.js");
|
|
@@ -818,15 +829,24 @@ backend
|
|
|
818
829
|
// ── doctor mcp ──
|
|
819
830
|
program
|
|
820
831
|
.command("doctor")
|
|
821
|
-
.description("
|
|
822
|
-
.argument("[check]", "
|
|
832
|
+
.description("Diagnose backends, tmux, service, D-Bus, fleet, IPC, and network; use `mcp` for a deep MCP check")
|
|
833
|
+
.argument("[check]", "Optional deep check: mcp (omit for the full fleet diagnostic)")
|
|
823
834
|
.action(async (check) => {
|
|
824
835
|
if (check === "mcp") {
|
|
825
836
|
await doctorMcp();
|
|
826
837
|
}
|
|
827
|
-
else {
|
|
838
|
+
else if (check) {
|
|
828
839
|
console.log("Usage: agend doctor mcp");
|
|
829
840
|
console.log(" mcp — Check fleet MCP health (IPC sockets, MCP configs, backends)");
|
|
841
|
+
process.exitCode = 2;
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
const { inspectService } = await import("./service-installer.js");
|
|
845
|
+
const { collectDoctorReport, formatDoctorReport } = await import("./doctor.js");
|
|
846
|
+
const report = await collectDoctorReport(DATA_DIR, inspectService());
|
|
847
|
+
console.log(formatDoctorReport(report));
|
|
848
|
+
if (report.errors > 0)
|
|
849
|
+
process.exitCode = 1;
|
|
830
850
|
}
|
|
831
851
|
});
|
|
832
852
|
async function doctorMcp() {
|
|
@@ -959,8 +979,8 @@ async function doctorMcp() {
|
|
|
959
979
|
}
|
|
960
980
|
backend
|
|
961
981
|
.command("trust")
|
|
962
|
-
.description("Pre-trust working directories
|
|
963
|
-
.argument("<backend>", "Backend (gemini-cli)")
|
|
982
|
+
.description("Pre-trust Gemini CLI working directories (prevents trust dialogs)")
|
|
983
|
+
.argument("<backend>", "Backend (gemini-cli only)")
|
|
964
984
|
.argument("[directories...]", "Directories to trust (defaults to all fleet instance dirs)")
|
|
965
985
|
.action(async (backendName, directories) => {
|
|
966
986
|
if (backendName !== "gemini-cli") {
|
|
@@ -1146,7 +1166,7 @@ access
|
|
|
1146
1166
|
// === Update + Reload ===
|
|
1147
1167
|
program
|
|
1148
1168
|
.command("update")
|
|
1149
|
-
.description("Update AgEnD to
|
|
1169
|
+
.description("Update AgEnD to the selected release and restart the fleet service")
|
|
1150
1170
|
.option("--version <ver>", "Specific version to install")
|
|
1151
1171
|
.option("--beta", "Install beta version")
|
|
1152
1172
|
.option("--force", "Force reinstall and restart even when already up to date")
|
|
@@ -1273,7 +1293,10 @@ program
|
|
|
1273
1293
|
if (agendPath) {
|
|
1274
1294
|
try {
|
|
1275
1295
|
// Use the NEW binary to install service (old binary's templates may be deleted)
|
|
1276
|
-
|
|
1296
|
+
// `agend install` activates by default. During update the existing
|
|
1297
|
+
// restart stage owns stop/start and progress reporting, so only refresh
|
|
1298
|
+
// the service file here to avoid restarting the fleet twice.
|
|
1299
|
+
const installResult = spawnSync(agendPath, ["install", "--no-activate"], { encoding: "utf-8", timeout: 15000 });
|
|
1277
1300
|
if (installResult.status === 0) {
|
|
1278
1301
|
console.log(` ✓ Service updated`);
|
|
1279
1302
|
}
|
|
@@ -1326,7 +1349,7 @@ program
|
|
|
1326
1349
|
});
|
|
1327
1350
|
program
|
|
1328
1351
|
.command("reload")
|
|
1329
|
-
.description("Hot-reload fleet
|
|
1352
|
+
.description("Hot-reload fleet.yaml and reconcile instance configuration")
|
|
1330
1353
|
.action(async () => {
|
|
1331
1354
|
const pidPath = join(DATA_DIR, "fleet.pid");
|
|
1332
1355
|
if (!existsSync(pidPath)) {
|
|
@@ -1346,8 +1369,9 @@ program
|
|
|
1346
1369
|
// === Install/Uninstall ===
|
|
1347
1370
|
program
|
|
1348
1371
|
.command("install")
|
|
1349
|
-
.description("Install
|
|
1350
|
-
.option("--activate", "
|
|
1372
|
+
.description("Install the AgEnD system service and start it by default")
|
|
1373
|
+
.option("--activate", "Deprecated; service activation is now the default")
|
|
1374
|
+
.option("--no-activate", "Write the service file without activating it")
|
|
1351
1375
|
.action(async (opts) => {
|
|
1352
1376
|
const { installService, activateService, detectPlatform } = await import("./service-installer.js");
|
|
1353
1377
|
const execPath = process.argv[1];
|
|
@@ -1358,38 +1382,86 @@ program
|
|
|
1358
1382
|
workingDirectory: DATA_DIR,
|
|
1359
1383
|
logPath: join(DATA_DIR, "fleet.log"),
|
|
1360
1384
|
});
|
|
1361
|
-
console.log(
|
|
1362
|
-
if (opts.activate) {
|
|
1385
|
+
console.log(t("install.path", svcPath));
|
|
1386
|
+
if (opts.activate !== false) {
|
|
1363
1387
|
const pidPath = join(DATA_DIR, "fleet.pid");
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
else {
|
|
1368
|
-
const plat = detectPlatform();
|
|
1369
|
-
if (plat === "macos") {
|
|
1370
|
-
console.log(`Run: launchctl load ${svcPath}`);
|
|
1388
|
+
try {
|
|
1389
|
+
activateService(svcPath, pidPath);
|
|
1390
|
+
console.log(t("install.running"));
|
|
1371
1391
|
}
|
|
1372
|
-
|
|
1373
|
-
console.
|
|
1392
|
+
catch (err) {
|
|
1393
|
+
console.error(t("install.start_failed", err.message));
|
|
1394
|
+
const plat = detectPlatform();
|
|
1395
|
+
if (plat === "macos") {
|
|
1396
|
+
console.error(`Run manually: launchctl load ${svcPath}`);
|
|
1397
|
+
}
|
|
1398
|
+
else {
|
|
1399
|
+
console.error("Run manually: systemctl --user daemon-reload && systemctl --user enable --now com.agend.fleet");
|
|
1400
|
+
}
|
|
1401
|
+
process.exitCode = 1;
|
|
1374
1402
|
}
|
|
1375
1403
|
}
|
|
1404
|
+
else {
|
|
1405
|
+
console.log(t("install.updated"));
|
|
1406
|
+
}
|
|
1376
1407
|
});
|
|
1377
1408
|
program
|
|
1378
1409
|
.command("uninstall")
|
|
1379
|
-
.description("Remove system service")
|
|
1380
|
-
.
|
|
1381
|
-
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
|
|
1410
|
+
.description("Remove the AgEnD system service")
|
|
1411
|
+
.option("-f, --force", "Skip confirmation (for CI/automation)")
|
|
1412
|
+
.action(async (opts) => {
|
|
1413
|
+
const { inspectService, isServiceRemovalConfirmed, uninstallService } = await import("./service-installer.js");
|
|
1414
|
+
const service = inspectService("com.agend.fleet");
|
|
1415
|
+
if (!service.installed) {
|
|
1416
|
+
console.log(t("uninstall.none"));
|
|
1417
|
+
return;
|
|
1385
1418
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1419
|
+
const state = (value, yes, no) => value == null ? t("uninstall.unknown") : value ? yes : no;
|
|
1420
|
+
console.log(t("uninstall.found"));
|
|
1421
|
+
console.log(` ${t("uninstall.manager", service.manager ?? t("uninstall.unknown"))}`);
|
|
1422
|
+
console.log(` ${t("uninstall.path", service.path ?? t("uninstall.unknown"))}`);
|
|
1423
|
+
console.log(` ${t("uninstall.enabled", state(service.enabled, t("uninstall.yes"), t("uninstall.no")))}`);
|
|
1424
|
+
console.log(` ${t("uninstall.active", state(service.active, t("uninstall.running"), t("uninstall.inactive")))}`);
|
|
1425
|
+
if (!opts.force && !process.stdin.isTTY) {
|
|
1426
|
+
console.log(t("uninstall.non_interactive"));
|
|
1427
|
+
process.exitCode = 1;
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
if (!opts.force) {
|
|
1431
|
+
const { createInterface } = await import("node:readline/promises");
|
|
1432
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1433
|
+
let answer = "";
|
|
1434
|
+
try {
|
|
1435
|
+
answer = await rl.question(t("uninstall.confirm"));
|
|
1436
|
+
}
|
|
1437
|
+
catch {
|
|
1438
|
+
console.log(t("uninstall.cancelled_force"));
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
finally {
|
|
1442
|
+
rl.close();
|
|
1443
|
+
}
|
|
1444
|
+
if (!isServiceRemovalConfirmed(answer)) {
|
|
1445
|
+
console.log(t("uninstall.cancelled"));
|
|
1446
|
+
return;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
try {
|
|
1450
|
+
if (uninstallService("com.agend.fleet")) {
|
|
1451
|
+
console.log(t("uninstall.removed"));
|
|
1452
|
+
}
|
|
1453
|
+
else {
|
|
1454
|
+
console.log(t("uninstall.none"));
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
catch (err) {
|
|
1458
|
+
console.error(t("uninstall.failed", err.message));
|
|
1459
|
+
process.exitCode = 1;
|
|
1388
1460
|
}
|
|
1389
1461
|
});
|
|
1390
1462
|
program
|
|
1391
1463
|
.command("stop")
|
|
1392
|
-
.description("Stop the AgEnD service")
|
|
1464
|
+
.description("Stop the AgEnD service or detached fleet")
|
|
1393
1465
|
.action(async () => {
|
|
1394
1466
|
const { getServicePath, stopService } = await import("./service-installer.js");
|
|
1395
1467
|
if (!getServicePath()) {
|
|
@@ -1433,7 +1505,7 @@ program
|
|
|
1433
1505
|
});
|
|
1434
1506
|
program
|
|
1435
1507
|
.command("start")
|
|
1436
|
-
.description("Start the AgEnD service
|
|
1508
|
+
.description("Start the AgEnD service, or start a detached fleet if no service is installed")
|
|
1437
1509
|
.action(async () => {
|
|
1438
1510
|
const { getServicePath, getSystemServicePath, startService, startSystemService } = await import("./service-installer.js");
|
|
1439
1511
|
const userServicePath = getServicePath();
|
|
@@ -1589,7 +1661,7 @@ program
|
|
|
1589
1661
|
});
|
|
1590
1662
|
program
|
|
1591
1663
|
.command("quickstart")
|
|
1592
|
-
.description("
|
|
1664
|
+
.description("Guided setup for a Backend, chat channel, projects, and fleet service")
|
|
1593
1665
|
.action(async () => {
|
|
1594
1666
|
const { runQuickstart } = await import("./quickstart.js");
|
|
1595
1667
|
await runQuickstart();
|
|
@@ -1862,7 +1934,7 @@ schedule
|
|
|
1862
1934
|
});
|
|
1863
1935
|
schedule
|
|
1864
1936
|
.command("trigger")
|
|
1865
|
-
.description("
|
|
1937
|
+
.description("Show how to manually trigger a schedule")
|
|
1866
1938
|
.argument("<id>", "Schedule ID")
|
|
1867
1939
|
.action((id) => {
|
|
1868
1940
|
console.log("Manual trigger requires fleet manager running. Use the Telegram interface instead.");
|
|
@@ -1959,46 +2031,8 @@ async function resolveInstance(query, config) {
|
|
|
1959
2031
|
}
|
|
1960
2032
|
return match;
|
|
1961
2033
|
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
if (depth > 10)
|
|
1965
|
-
return 0;
|
|
1966
|
-
if (!Number.isInteger(pid) || pid <= 0)
|
|
1967
|
-
return 0;
|
|
1968
|
-
let total = 0;
|
|
1969
|
-
try {
|
|
1970
|
-
// Try PSS from smaps_rollup (more accurate — excludes shared page double-counting)
|
|
1971
|
-
const smaps = readFileSync(`/proc/${pid}/smaps_rollup`, "utf-8");
|
|
1972
|
-
const match = smaps.match(/^Pss:\s+(\d+)/m);
|
|
1973
|
-
if (match) {
|
|
1974
|
-
total += parseInt(match[1], 10);
|
|
1975
|
-
}
|
|
1976
|
-
else {
|
|
1977
|
-
throw new Error("no Pss line");
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
catch {
|
|
1981
|
-
// Fallback to RSS via ps
|
|
1982
|
-
try {
|
|
1983
|
-
const rss = parseInt(execFileSync("ps", ["-o", "rss=", "-p", String(pid)], { stdio: "pipe" }).toString().trim(), 10);
|
|
1984
|
-
if (!isNaN(rss))
|
|
1985
|
-
total += rss;
|
|
1986
|
-
}
|
|
1987
|
-
catch {
|
|
1988
|
-
return 0;
|
|
1989
|
-
}
|
|
1990
|
-
}
|
|
1991
|
-
try {
|
|
1992
|
-
const children = execFileSync("pgrep", ["-P", String(pid)], { stdio: "pipe" }).toString().trim();
|
|
1993
|
-
for (const line of children.split("\n")) {
|
|
1994
|
-
const childPid = parseInt(line, 10);
|
|
1995
|
-
if (!isNaN(childPid))
|
|
1996
|
-
total += getTreeRssKb(childPid, depth + 1);
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
catch { /* no children */ }
|
|
2000
|
-
return total;
|
|
2001
|
-
}
|
|
2034
|
+
// Imported from process-memory.ts — see that module for implementation
|
|
2035
|
+
import { getTreeRssKb } from "./process-memory.js";
|
|
2002
2036
|
function getInstanceStatusStandalone(name) {
|
|
2003
2037
|
if (hasPausedMarker(join(DATA_DIR, "instances", name)))
|
|
2004
2038
|
return "paused";
|
|
@@ -2521,6 +2555,10 @@ program
|
|
|
2521
2555
|
if (procStatus === "stopped") {
|
|
2522
2556
|
return { name, status: "stopped", issues: ["Not running"], general: isGeneral };
|
|
2523
2557
|
}
|
|
2558
|
+
// Paused instances have no tmux window by design — skip running-only checks
|
|
2559
|
+
if (procStatus === "paused") {
|
|
2560
|
+
return { name, status: "paused", issues: [], general: isGeneral };
|
|
2561
|
+
}
|
|
2524
2562
|
// Tmux window alive?
|
|
2525
2563
|
if (!tmuxWindows.has(name))
|
|
2526
2564
|
issues.push("Tmux window missing");
|
|
@@ -2552,10 +2590,11 @@ program
|
|
|
2552
2590
|
});
|
|
2553
2591
|
// Fleet classification
|
|
2554
2592
|
const crashed = results.filter(r => r.status === "crash");
|
|
2555
|
-
const problems = results.filter(r => r.status !== "ok" && r.status !== "idle" && r.status !== "stopped");
|
|
2593
|
+
const problems = results.filter(r => r.status !== "ok" && r.status !== "idle" && r.status !== "stopped" && r.status !== "paused");
|
|
2556
2594
|
const healthy = results.filter(r => r.status === "ok" || r.status === "idle");
|
|
2557
2595
|
const stopped = results.filter(r => r.status === "stopped");
|
|
2558
|
-
const
|
|
2596
|
+
const paused = results.filter(r => r.status === "paused");
|
|
2597
|
+
const generalDown = results.some(r => r.general && r.status !== "ok" && r.status !== "idle" && r.status !== "paused");
|
|
2559
2598
|
let classification;
|
|
2560
2599
|
if (generalDown || crashed.length > 0)
|
|
2561
2600
|
classification = "unhealthy";
|
|
@@ -2570,7 +2609,8 @@ program
|
|
|
2570
2609
|
}
|
|
2571
2610
|
if (opts.quiet) {
|
|
2572
2611
|
const icon = classification === "healthy" ? "✓" : classification === "degraded" ? "⚠" : "✗";
|
|
2573
|
-
|
|
2612
|
+
const pausedPart = paused.length > 0 ? `, ${paused.length} paused` : "";
|
|
2613
|
+
console.log(`${icon} ${classification}: ${healthy.length}/${names.length} healthy${problems.length > 0 ? `, ${problems.length} issues` : ""}${pausedPart}`);
|
|
2574
2614
|
process.exit(exitCode);
|
|
2575
2615
|
}
|
|
2576
2616
|
// Full output
|
|
@@ -2578,9 +2618,10 @@ program
|
|
|
2578
2618
|
const upH = Math.floor(uptime / 3600);
|
|
2579
2619
|
const upM = Math.floor((uptime % 3600) / 60);
|
|
2580
2620
|
console.log(`Fleet: ${fleetIcon} ${fleetUp ? `running (uptime ${upH}h ${upM}m, PID ${fleetPid})` : "not running"}`);
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2621
|
+
const pausedPart = paused.length > 0 ? `, ${paused.length} paused` : "";
|
|
2622
|
+
console.log(`Instances: ${healthy.length} healthy, ${problems.length + crashed.length} issues, ${stopped.length} stopped${pausedPart}\n`);
|
|
2623
|
+
// Only show instances with problems (paused is not a problem)
|
|
2624
|
+
const unhealthy = results.filter(r => r.issues.length > 0 && r.status !== "stopped" && r.status !== "paused");
|
|
2584
2625
|
if (unhealthy.length === 0) {
|
|
2585
2626
|
console.log("\x1b[32m✓ All instances healthy\x1b[0m");
|
|
2586
2627
|
}
|