agentflow-core 0.7.0 → 0.8.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/README.md +99 -0
- package/dist/{chunk-DY7YHFIB.js → chunk-BYWLDTZK.js} +2 -1
- package/dist/{chunk-5PRHVYYD.js → chunk-NVFWBTAZ.js} +198 -89
- package/dist/cli.cjs +225 -112
- package/dist/cli.js +12 -8
- package/dist/index.cjs +1657 -166
- package/dist/index.d.cts +917 -37
- package/dist/index.d.ts +917 -37
- package/dist/index.js +1381 -10
- package/dist/{loader-LYRR6LMM.js → loader-JMFEFI3Q.js} +1 -1
- package/package.json +7 -3
package/dist/cli.cjs
CHANGED
|
@@ -62,7 +62,8 @@ function loadGraph(input) {
|
|
|
62
62
|
events: raw.events ?? [],
|
|
63
63
|
traceId: raw.traceId,
|
|
64
64
|
spanId: raw.spanId,
|
|
65
|
-
parentSpanId: raw.parentSpanId
|
|
65
|
+
parentSpanId: raw.parentSpanId,
|
|
66
|
+
metadata: raw.metadata ?? {}
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
function graphToJson(graph) {
|
|
@@ -93,7 +94,7 @@ var init_loader = __esm({
|
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
// src/cli.ts
|
|
96
|
-
var
|
|
97
|
+
var import_node_path7 = require("path");
|
|
97
98
|
|
|
98
99
|
// src/live.ts
|
|
99
100
|
var import_node_fs2 = require("fs");
|
|
@@ -191,7 +192,7 @@ function groupByTraceId(graphs) {
|
|
|
191
192
|
}
|
|
192
193
|
function stitchTrace(graphs) {
|
|
193
194
|
if (graphs.length === 0) throw new Error("No graphs to stitch");
|
|
194
|
-
const traceId = graphs[0]
|
|
195
|
+
const traceId = graphs[0]?.traceId ?? "";
|
|
195
196
|
const graphsBySpan = /* @__PURE__ */ new Map();
|
|
196
197
|
const childMap = /* @__PURE__ */ new Map();
|
|
197
198
|
let rootGraph = null;
|
|
@@ -268,7 +269,7 @@ function pidMatchesName(pid, name) {
|
|
|
268
269
|
function readPidFile(path) {
|
|
269
270
|
try {
|
|
270
271
|
const pid = parseInt((0, import_node_fs.readFileSync)(path, "utf8").trim(), 10);
|
|
271
|
-
return isNaN(pid) ? null : pid;
|
|
272
|
+
return Number.isNaN(pid) ? null : pid;
|
|
272
273
|
} catch {
|
|
273
274
|
return null;
|
|
274
275
|
}
|
|
@@ -303,8 +304,15 @@ function auditSystemd(config) {
|
|
|
303
304
|
if (config.systemdUnit === null || config.systemdUnit === void 0) return null;
|
|
304
305
|
const unit = config.systemdUnit;
|
|
305
306
|
try {
|
|
306
|
-
const raw = (0, import_node_child_process.
|
|
307
|
-
|
|
307
|
+
const raw = (0, import_node_child_process.execFileSync)(
|
|
308
|
+
"systemctl",
|
|
309
|
+
[
|
|
310
|
+
"--user",
|
|
311
|
+
"show",
|
|
312
|
+
unit,
|
|
313
|
+
"--property=ActiveState,SubState,MainPID,NRestarts,Result",
|
|
314
|
+
"--no-pager"
|
|
315
|
+
],
|
|
308
316
|
{ encoding: "utf8", timeout: 5e3 }
|
|
309
317
|
);
|
|
310
318
|
const props = {};
|
|
@@ -312,11 +320,11 @@ function auditSystemd(config) {
|
|
|
312
320
|
const [k, ...v] = line.split("=");
|
|
313
321
|
if (k) props[k.trim()] = v.join("=").trim();
|
|
314
322
|
}
|
|
315
|
-
const activeState = props
|
|
316
|
-
const subState = props
|
|
317
|
-
const mainPid = parseInt(props
|
|
318
|
-
const restarts = parseInt(props
|
|
319
|
-
const result = props
|
|
323
|
+
const activeState = props.ActiveState ?? "unknown";
|
|
324
|
+
const subState = props.SubState ?? "unknown";
|
|
325
|
+
const mainPid = parseInt(props.MainPID ?? "0", 10);
|
|
326
|
+
const restarts = parseInt(props.NRestarts ?? "0", 10);
|
|
327
|
+
const result = props.Result ?? "unknown";
|
|
320
328
|
return {
|
|
321
329
|
unit,
|
|
322
330
|
activeState,
|
|
@@ -369,10 +377,10 @@ function readCmdline(pid) {
|
|
|
369
377
|
}
|
|
370
378
|
function getOsProcesses(processName) {
|
|
371
379
|
try {
|
|
372
|
-
const raw = (0, import_node_child_process.execSync)(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
);
|
|
380
|
+
const raw = (0, import_node_child_process.execSync)(`ps -eo pid,pcpu,pmem,etime,lstart,args --no-headers`, {
|
|
381
|
+
encoding: "utf8",
|
|
382
|
+
timeout: 5e3
|
|
383
|
+
});
|
|
376
384
|
const results = [];
|
|
377
385
|
for (const line of raw.split("\n")) {
|
|
378
386
|
if (!line.includes(processName)) continue;
|
|
@@ -380,7 +388,7 @@ function getOsProcesses(processName) {
|
|
|
380
388
|
const trimmed = line.trim();
|
|
381
389
|
const parts = trimmed.split(/\s+/);
|
|
382
390
|
const pid = parseInt(parts[0] ?? "0", 10);
|
|
383
|
-
if (isNaN(pid) || pid <= 0) continue;
|
|
391
|
+
if (Number.isNaN(pid) || pid <= 0) continue;
|
|
384
392
|
const cpu = parts[1] ?? "0";
|
|
385
393
|
const mem = parts[2] ?? "0";
|
|
386
394
|
const elapsed = parts[3] ?? "";
|
|
@@ -395,9 +403,11 @@ function getOsProcesses(processName) {
|
|
|
395
403
|
}
|
|
396
404
|
}
|
|
397
405
|
function discoverProcessConfig(dirs) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
406
|
+
const configs = discoverAllProcessConfigs(dirs);
|
|
407
|
+
return configs.length > 0 ? configs[0] ?? null : null;
|
|
408
|
+
}
|
|
409
|
+
function discoverAllProcessConfigs(dirs) {
|
|
410
|
+
const configs = /* @__PURE__ */ new Map();
|
|
401
411
|
for (const dir of dirs) {
|
|
402
412
|
if (!(0, import_node_fs.existsSync)(dir)) continue;
|
|
403
413
|
let entries;
|
|
@@ -413,35 +423,63 @@ function discoverProcessConfig(dirs) {
|
|
|
413
423
|
} catch {
|
|
414
424
|
continue;
|
|
415
425
|
}
|
|
416
|
-
if (f.endsWith(".pid")
|
|
417
|
-
|
|
418
|
-
if (!
|
|
419
|
-
|
|
426
|
+
if (f.endsWith(".pid")) {
|
|
427
|
+
const name = (0, import_node_path.basename)(f, ".pid");
|
|
428
|
+
if (!configs.has(name)) {
|
|
429
|
+
configs.set(name, { processName: name });
|
|
420
430
|
}
|
|
431
|
+
const cfg = configs.get(name) ?? { processName: name };
|
|
432
|
+
if (!cfg.pidFile) cfg.pidFile = fp;
|
|
421
433
|
}
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
if (
|
|
425
|
-
|
|
434
|
+
if (f === "workers.json" || f.endsWith("-workers.json")) {
|
|
435
|
+
const name = f === "workers.json" ? "" : (0, import_node_path.basename)(f, "-workers.json");
|
|
436
|
+
if (name && !configs.has(name)) {
|
|
437
|
+
configs.set(name, { processName: name });
|
|
438
|
+
}
|
|
439
|
+
if (name) {
|
|
440
|
+
const cfg = configs.get(name) ?? { processName: name };
|
|
441
|
+
if (!cfg.workersFile) cfg.workersFile = fp;
|
|
426
442
|
}
|
|
427
443
|
}
|
|
428
444
|
}
|
|
429
445
|
}
|
|
430
|
-
if (!processName && !pidFile && !workersFile) return null;
|
|
431
|
-
if (!processName) processName = "agent";
|
|
432
|
-
let systemdUnit;
|
|
433
446
|
try {
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
{ encoding: "utf8", timeout: 3e3 }
|
|
447
|
+
const raw = (0, import_node_child_process.execSync)(
|
|
448
|
+
"systemctl --user list-units --type=service --all --no-legend --no-pager 2>/dev/null",
|
|
449
|
+
{ encoding: "utf8", timeout: 5e3 }
|
|
438
450
|
);
|
|
439
|
-
|
|
440
|
-
|
|
451
|
+
for (const line of raw.trim().split("\n")) {
|
|
452
|
+
if (!line.trim()) continue;
|
|
453
|
+
const parts = line.trim().split(/\s+/);
|
|
454
|
+
const unitName = parts[0] ?? "";
|
|
455
|
+
const loadState = parts[1] ?? "";
|
|
456
|
+
if (!unitName.endsWith(".service") || loadState !== "loaded") continue;
|
|
457
|
+
const name = unitName.replace(".service", "");
|
|
458
|
+
if (/^(dbus|gpg-agent|dirmngr|keyboxd|snapd\.|pk-|launchpadlib-)/.test(name)) continue;
|
|
459
|
+
if (!configs.has(name)) {
|
|
460
|
+
configs.set(name, { processName: name });
|
|
461
|
+
}
|
|
462
|
+
const cfg = configs.get(name) ?? { processName: name };
|
|
463
|
+
cfg.systemdUnit = unitName;
|
|
441
464
|
}
|
|
442
465
|
} catch {
|
|
443
466
|
}
|
|
444
|
-
|
|
467
|
+
for (const cfg of configs.values()) {
|
|
468
|
+
if (cfg.systemdUnit !== void 0) continue;
|
|
469
|
+
try {
|
|
470
|
+
const unitName = `${cfg.processName}.service`;
|
|
471
|
+
const result = (0, import_node_child_process.execFileSync)(
|
|
472
|
+
"systemctl",
|
|
473
|
+
["--user", "show", unitName, "--property=LoadState", "--no-pager"],
|
|
474
|
+
{ encoding: "utf8", timeout: 3e3 }
|
|
475
|
+
);
|
|
476
|
+
if (result.includes("LoadState=loaded")) {
|
|
477
|
+
cfg.systemdUnit = unitName;
|
|
478
|
+
}
|
|
479
|
+
} catch {
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return [...configs.values()];
|
|
445
483
|
}
|
|
446
484
|
function auditProcesses(config) {
|
|
447
485
|
const pidFile = auditPidFile(config);
|
|
@@ -457,16 +495,45 @@ function auditProcesses(config) {
|
|
|
457
495
|
}
|
|
458
496
|
}
|
|
459
497
|
if (systemd?.mainPid) knownPids.add(systemd.mainPid);
|
|
498
|
+
const childPids = /* @__PURE__ */ new Set();
|
|
499
|
+
for (const knownPid of knownPids) {
|
|
500
|
+
try {
|
|
501
|
+
const childrenRaw = (0, import_node_fs.readFileSync)(
|
|
502
|
+
`/proc/${knownPid}/task/${knownPid}/children`,
|
|
503
|
+
"utf8"
|
|
504
|
+
).trim();
|
|
505
|
+
if (childrenRaw) {
|
|
506
|
+
for (const c of childrenRaw.split(/\s+/)) {
|
|
507
|
+
const cp = parseInt(c, 10);
|
|
508
|
+
if (!Number.isNaN(cp)) childPids.add(cp);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
} catch {
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
for (const p of osProcesses) {
|
|
515
|
+
if (knownPids.has(p.pid)) continue;
|
|
516
|
+
try {
|
|
517
|
+
const statusContent = (0, import_node_fs.readFileSync)(`/proc/${p.pid}/status`, "utf8");
|
|
518
|
+
const ppidMatch = statusContent.match(/^PPid:\s+(\d+)/m);
|
|
519
|
+
if (ppidMatch) {
|
|
520
|
+
const ppid = parseInt(ppidMatch[1] ?? "0", 10);
|
|
521
|
+
if (knownPids.has(ppid)) childPids.add(p.pid);
|
|
522
|
+
}
|
|
523
|
+
} catch {
|
|
524
|
+
}
|
|
525
|
+
}
|
|
460
526
|
const selfPid = process.pid;
|
|
461
527
|
const selfPpid = process.ppid;
|
|
462
528
|
const orphans = osProcesses.filter(
|
|
463
|
-
(p) => !knownPids.has(p.pid) && p.pid !== selfPid && p.pid !== selfPpid
|
|
529
|
+
(p) => !knownPids.has(p.pid) && !childPids.has(p.pid) && p.pid !== selfPid && p.pid !== selfPpid
|
|
464
530
|
);
|
|
465
531
|
const problems = [];
|
|
466
532
|
if (pidFile?.stale) problems.push(`Stale PID file: ${pidFile.reason}`);
|
|
467
533
|
if (systemd?.crashLooping) problems.push("Systemd unit is crash-looping (auto-restart)");
|
|
468
534
|
if (systemd?.failed) problems.push("Systemd unit has failed");
|
|
469
|
-
if (systemd && systemd.restarts > 10)
|
|
535
|
+
if (systemd && systemd.restarts > 10)
|
|
536
|
+
problems.push(`High systemd restart count: ${systemd.restarts}`);
|
|
470
537
|
if (pidFile?.pid && systemd?.mainPid && pidFile.pid !== systemd.mainPid) {
|
|
471
538
|
problems.push(`PID mismatch: file says ${pidFile.pid}, systemd says ${systemd.mainPid}`);
|
|
472
539
|
}
|
|
@@ -475,15 +542,24 @@ function auditProcesses(config) {
|
|
|
475
542
|
if (w.stale) problems.push(`Worker "${w.name}" (pid ${w.pid}) declares running but is dead`);
|
|
476
543
|
}
|
|
477
544
|
}
|
|
478
|
-
if (orphans.length > 0)
|
|
545
|
+
if (orphans.length > 0)
|
|
546
|
+
problems.push(
|
|
547
|
+
`${orphans.length} orphan process(es) not tracked by PID file or workers registry`
|
|
548
|
+
);
|
|
479
549
|
return { pidFile, systemd, workers, osProcesses, orphans, problems };
|
|
480
550
|
}
|
|
481
551
|
function formatAuditReport(result) {
|
|
482
552
|
const lines = [];
|
|
483
553
|
lines.push("");
|
|
484
|
-
lines.push(
|
|
485
|
-
|
|
486
|
-
|
|
554
|
+
lines.push(
|
|
555
|
+
"\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"
|
|
556
|
+
);
|
|
557
|
+
lines.push(
|
|
558
|
+
"\u2551 \u{1F50D} P R O C E S S A U D I T \u2551"
|
|
559
|
+
);
|
|
560
|
+
lines.push(
|
|
561
|
+
"\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
562
|
+
);
|
|
487
563
|
if (result.pidFile) {
|
|
488
564
|
const pf = result.pidFile;
|
|
489
565
|
const icon = pf.pid && pf.alive && pf.matchesProcess ? "\u2705" : pf.stale ? "\u26A0\uFE0F " : "\u2139\uFE0F ";
|
|
@@ -501,25 +577,33 @@ function formatAuditReport(result) {
|
|
|
501
577
|
}
|
|
502
578
|
if (result.workers) {
|
|
503
579
|
const w = result.workers;
|
|
504
|
-
lines.push(
|
|
505
|
-
|
|
580
|
+
lines.push(
|
|
581
|
+
`
|
|
582
|
+
Workers (orchestrator pid ${w.orchestratorPid ?? "unknown"} ${w.orchestratorAlive ? "\u2705" : "\u274C"})`
|
|
583
|
+
);
|
|
506
584
|
for (const worker of w.workers) {
|
|
507
585
|
const icon = worker.declaredStatus === "running" && worker.alive ? "\u{1F7E2}" : worker.stale ? "\u{1F534} STALE" : "\u26AA";
|
|
508
|
-
lines.push(
|
|
586
|
+
lines.push(
|
|
587
|
+
` ${icon} ${worker.name.padEnd(14)} pid=${String(worker.pid ?? "-").padEnd(8)} status=${worker.declaredStatus}`
|
|
588
|
+
);
|
|
509
589
|
}
|
|
510
590
|
}
|
|
511
591
|
if (result.osProcesses.length > 0) {
|
|
512
592
|
lines.push(`
|
|
513
593
|
OS Processes (${result.osProcesses.length} total)`);
|
|
514
594
|
for (const p of result.osProcesses) {
|
|
515
|
-
lines.push(
|
|
595
|
+
lines.push(
|
|
596
|
+
` PID ${String(p.pid).padEnd(8)} CPU=${p.cpu.padEnd(6)} MEM=${p.mem.padEnd(6)} Up=${p.elapsed.padEnd(10)} ${p.command.substring(0, 50)}`
|
|
597
|
+
);
|
|
516
598
|
}
|
|
517
599
|
}
|
|
518
600
|
if (result.orphans.length > 0) {
|
|
519
601
|
lines.push(`
|
|
520
602
|
\u26A0\uFE0F ${result.orphans.length} ORPHAN PROCESS(ES):`);
|
|
521
603
|
for (const p of result.orphans) {
|
|
522
|
-
lines.push(
|
|
604
|
+
lines.push(
|
|
605
|
+
` PID ${String(p.pid).padEnd(8)} CPU=${p.cpu.padEnd(6)} MEM=${p.mem.padEnd(6)} Up=${p.elapsed}`
|
|
606
|
+
);
|
|
523
607
|
lines.push(` Started: ${p.started}`);
|
|
524
608
|
lines.push(` Command: ${p.cmdline || p.command}`);
|
|
525
609
|
}
|
|
@@ -557,14 +641,14 @@ function parseArgs(argv) {
|
|
|
557
641
|
if (args[0] === "live") args.shift();
|
|
558
642
|
let i = 0;
|
|
559
643
|
while (i < args.length) {
|
|
560
|
-
const arg = args[i];
|
|
644
|
+
const arg = args[i] ?? "";
|
|
561
645
|
if (arg === "--help" || arg === "-h") {
|
|
562
646
|
printUsage();
|
|
563
647
|
process.exit(0);
|
|
564
648
|
} else if (arg === "--refresh" || arg === "-r") {
|
|
565
649
|
i++;
|
|
566
650
|
const v = parseInt(args[i] ?? "", 10);
|
|
567
|
-
if (!isNaN(v) && v > 0) config.refreshMs = v * 1e3;
|
|
651
|
+
if (!Number.isNaN(v) && v > 0) config.refreshMs = v * 1e3;
|
|
568
652
|
i++;
|
|
569
653
|
} else if (arg === "--recursive" || arg === "-R") {
|
|
570
654
|
config.recursive = true;
|
|
@@ -645,12 +729,22 @@ function scanFiles(dirs, recursive) {
|
|
|
645
729
|
if (!stat.isFile()) continue;
|
|
646
730
|
if (f.endsWith(".json")) {
|
|
647
731
|
seen.add(fp);
|
|
648
|
-
const entry = {
|
|
732
|
+
const entry = {
|
|
733
|
+
filename: f,
|
|
734
|
+
path: fp,
|
|
735
|
+
mtime: stat.mtime.getTime(),
|
|
736
|
+
ext: ".json"
|
|
737
|
+
};
|
|
649
738
|
results.push(entry);
|
|
650
739
|
dirResults.push(entry);
|
|
651
740
|
} else if (f.endsWith(".jsonl")) {
|
|
652
741
|
seen.add(fp);
|
|
653
|
-
const entry = {
|
|
742
|
+
const entry = {
|
|
743
|
+
filename: f,
|
|
744
|
+
path: fp,
|
|
745
|
+
mtime: stat.mtime.getTime(),
|
|
746
|
+
ext: ".jsonl"
|
|
747
|
+
};
|
|
654
748
|
results.push(entry);
|
|
655
749
|
dirResults.push(entry);
|
|
656
750
|
}
|
|
@@ -712,7 +806,7 @@ function findTimestamp(obj) {
|
|
|
712
806
|
if (typeof val === "number") return val > 1e12 ? val : val * 1e3;
|
|
713
807
|
if (typeof val === "string") {
|
|
714
808
|
const d = Date.parse(val);
|
|
715
|
-
if (!isNaN(d)) return d;
|
|
809
|
+
if (!Number.isNaN(d)) return d;
|
|
716
810
|
}
|
|
717
811
|
}
|
|
718
812
|
return 0;
|
|
@@ -744,7 +838,7 @@ function extractDetail(obj) {
|
|
|
744
838
|
}
|
|
745
839
|
return parts.join(" | ") || "";
|
|
746
840
|
}
|
|
747
|
-
function tryLoadTrace(
|
|
841
|
+
function tryLoadTrace(_fp, raw) {
|
|
748
842
|
if (typeof raw !== "object" || raw === null) return null;
|
|
749
843
|
const obj = raw;
|
|
750
844
|
if (!("nodes" in obj)) return null;
|
|
@@ -854,7 +948,7 @@ function processJsonlFile(file) {
|
|
|
854
948
|
if (!content) return [];
|
|
855
949
|
const lines = content.split("\n");
|
|
856
950
|
const lineCount = lines.length;
|
|
857
|
-
const lastObj = JSON.parse(lines[lines.length - 1]);
|
|
951
|
+
const lastObj = JSON.parse(lines[lines.length - 1] ?? "{}");
|
|
858
952
|
const name = lastObj.jobId ?? lastObj.agentId ?? lastObj.name ?? lastObj.id ?? nameFromFile(file.filename);
|
|
859
953
|
if (lastObj.action !== void 0 || lastObj.jobId !== void 0) {
|
|
860
954
|
const status2 = findStatus(lastObj);
|
|
@@ -950,7 +1044,7 @@ function processJsonlFile(file) {
|
|
|
950
1044
|
}
|
|
951
1045
|
const parts = [];
|
|
952
1046
|
if (model) {
|
|
953
|
-
const shortModel = model.includes("/") ? model.split("/").pop() : model;
|
|
1047
|
+
const shortModel = model.includes("/") ? model.split("/").pop() ?? model : model;
|
|
954
1048
|
parts.push(shortModel.slice(0, 20));
|
|
955
1049
|
}
|
|
956
1050
|
if (toolCalls.length > 0) {
|
|
@@ -995,7 +1089,8 @@ function writeLine(lines, text) {
|
|
|
995
1089
|
}
|
|
996
1090
|
function flushLines(lines) {
|
|
997
1091
|
process.stdout.write("\x1B[H");
|
|
998
|
-
process.stdout.write(lines.join("\n")
|
|
1092
|
+
process.stdout.write(`${lines.join("\n")}
|
|
1093
|
+
`);
|
|
999
1094
|
process.stdout.write("\x1B[J");
|
|
1000
1095
|
}
|
|
1001
1096
|
var prevFileCount = 0;
|
|
@@ -1089,7 +1184,7 @@ function render(config) {
|
|
|
1089
1184
|
const status = fail > 0 ? "error" : running > 0 ? "running" : ok > 0 ? "ok" : "unknown";
|
|
1090
1185
|
groups.push({
|
|
1091
1186
|
name: groupName,
|
|
1092
|
-
source: records[0]
|
|
1187
|
+
source: records[0]?.source ?? "trace",
|
|
1093
1188
|
status,
|
|
1094
1189
|
lastTs,
|
|
1095
1190
|
detail: `${records.length} agents`,
|
|
@@ -1114,15 +1209,15 @@ function render(config) {
|
|
|
1114
1209
|
if (age > 36e5 || age < 0) continue;
|
|
1115
1210
|
const idx = 11 - Math.floor(age / 3e5);
|
|
1116
1211
|
if (idx >= 0 && idx < 12) {
|
|
1117
|
-
buckets[idx]
|
|
1118
|
-
if (r.status === "error") failBuckets[idx]
|
|
1212
|
+
buckets[idx] = (buckets[idx] ?? 0) + 1;
|
|
1213
|
+
if (r.status === "error") failBuckets[idx] = (failBuckets[idx] ?? 0) + 1;
|
|
1119
1214
|
}
|
|
1120
1215
|
}
|
|
1121
1216
|
const maxBucket = Math.max(...buckets, 1);
|
|
1122
1217
|
const sparkChars = " \u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
|
|
1123
1218
|
const spark = buckets.map((v, i) => {
|
|
1124
1219
|
const level = Math.round(v / maxBucket * 8);
|
|
1125
|
-
return (failBuckets[i] > 0 ? C.red : C.green) + sparkChars[level] + C.reset;
|
|
1220
|
+
return ((failBuckets[i] ?? 0) > 0 ? C.red : C.green) + sparkChars[level] + C.reset;
|
|
1126
1221
|
}).join("");
|
|
1127
1222
|
let auditResult = null;
|
|
1128
1223
|
if (now - lastAuditTime > 1e4) {
|
|
@@ -1135,8 +1230,10 @@ function render(config) {
|
|
|
1135
1230
|
cachedAuditResult = auditResult;
|
|
1136
1231
|
lastAuditTime = now;
|
|
1137
1232
|
} catch (err) {
|
|
1138
|
-
process.stderr.write(
|
|
1139
|
-
`
|
|
1233
|
+
process.stderr.write(
|
|
1234
|
+
`[agentflow] process audit error: ${err instanceof Error ? err.message : err}
|
|
1235
|
+
`
|
|
1236
|
+
);
|
|
1140
1237
|
}
|
|
1141
1238
|
}
|
|
1142
1239
|
} else {
|
|
@@ -1193,7 +1290,7 @@ function render(config) {
|
|
|
1193
1290
|
return new Date(ts).toLocaleTimeString();
|
|
1194
1291
|
}
|
|
1195
1292
|
function truncate(s, max) {
|
|
1196
|
-
return s.length > max ? s.slice(0, max - 1)
|
|
1293
|
+
return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
|
|
1197
1294
|
}
|
|
1198
1295
|
const termWidth = process.stdout.columns || 120;
|
|
1199
1296
|
const detailWidth = Math.max(20, termWidth - 60);
|
|
@@ -1234,7 +1331,8 @@ function render(config) {
|
|
|
1234
1331
|
if (ar.systemd) {
|
|
1235
1332
|
const si = ar.systemd.activeState === "active" ? `${C.green}\u25CF${C.reset}` : ar.systemd.crashLooping ? `${C.yellow}\u25CF${C.reset}` : ar.systemd.failed ? `${C.red}\u25CF${C.reset}` : `${C.dim}\u25CB${C.reset}`;
|
|
1236
1333
|
sysdLabel = ` ${C.bold}Systemd${C.reset} ${si} ${ar.systemd.activeState}`;
|
|
1237
|
-
if (ar.systemd.restarts > 0)
|
|
1334
|
+
if (ar.systemd.restarts > 0)
|
|
1335
|
+
sysdLabel += ` ${C.dim}(${ar.systemd.restarts} restarts)${C.reset}`;
|
|
1238
1336
|
}
|
|
1239
1337
|
let pidLabel = "";
|
|
1240
1338
|
if (ar.pidFile?.pid) {
|
|
@@ -1243,7 +1341,10 @@ function render(config) {
|
|
|
1243
1341
|
}
|
|
1244
1342
|
writeLine(L, "");
|
|
1245
1343
|
writeLine(L, ` ${C.bold}${C.under}Process Health${C.reset}`);
|
|
1246
|
-
writeLine(
|
|
1344
|
+
writeLine(
|
|
1345
|
+
L,
|
|
1346
|
+
` ${healthIcon} ${healthLabel}${pidLabel}${sysdLabel} ${C.bold}Procs${C.reset} ${C.dim}${ar.osProcesses.length}${C.reset} ${ar.orphans.length > 0 ? `${C.red}Orphans ${ar.orphans.length}${C.reset}` : `${C.dim}Orphans 0${C.reset}`}`
|
|
1347
|
+
);
|
|
1247
1348
|
if (workerParts.length > 0) {
|
|
1248
1349
|
writeLine(L, ` ${C.dim}Workers${C.reset} ${workerParts.join(" ")}`);
|
|
1249
1350
|
}
|
|
@@ -1255,7 +1356,10 @@ function render(config) {
|
|
|
1255
1356
|
if (ar.orphans.length > 0) {
|
|
1256
1357
|
for (const o of ar.orphans.slice(0, 5)) {
|
|
1257
1358
|
const cmd = (o.cmdline || o.command).substring(0, detailWidth);
|
|
1258
|
-
writeLine(
|
|
1359
|
+
writeLine(
|
|
1360
|
+
L,
|
|
1361
|
+
` ${C.red}?${C.reset} ${C.dim}pid=${o.pid} cpu=${o.cpu} mem=${o.mem} up=${o.elapsed}${C.reset} ${C.dim}${cmd}${C.reset}`
|
|
1362
|
+
);
|
|
1259
1363
|
}
|
|
1260
1364
|
if (ar.orphans.length > 5) {
|
|
1261
1365
|
writeLine(L, ` ${C.dim}... +${ar.orphans.length - 5} more orphans${C.reset}`);
|
|
@@ -1329,7 +1433,7 @@ function render(config) {
|
|
|
1329
1433
|
for (let i = 0; i < Math.min(tree.length, 6); i++) {
|
|
1330
1434
|
const tg = tree[i];
|
|
1331
1435
|
const depth = getDistDepth(dt, tg.spanId);
|
|
1332
|
-
const indent =
|
|
1436
|
+
const indent = ` ${"\u2502 ".repeat(Math.max(0, depth - 1))}`;
|
|
1333
1437
|
const isLast = i === tree.length - 1 || getDistDepth(dt, tree[i + 1]?.spanId) <= depth;
|
|
1334
1438
|
const conn = depth === 0 ? " " : isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
1335
1439
|
const gs = tg.status === "completed" ? `${C.green}\u2713${C.reset}` : tg.status === "failed" ? `${C.red}\u2717${C.reset}` : `${C.yellow}\u23F3${C.reset}`;
|
|
@@ -1350,7 +1454,7 @@ function render(config) {
|
|
|
1350
1454
|
const t = new Date(r.lastActive).toLocaleTimeString();
|
|
1351
1455
|
const agent = truncate(r.id, 26).padEnd(26);
|
|
1352
1456
|
const age = Math.floor((Date.now() - r.lastActive) / 1e3);
|
|
1353
|
-
const ageStr = age < 60 ? age
|
|
1457
|
+
const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
|
|
1354
1458
|
const det = truncate(r.detail, detailWidth);
|
|
1355
1459
|
writeLine(
|
|
1356
1460
|
L,
|
|
@@ -1364,7 +1468,7 @@ function render(config) {
|
|
|
1364
1468
|
for (const d of config.dirs) writeLine(L, ` ${C.dim} ${d}${C.reset}`);
|
|
1365
1469
|
}
|
|
1366
1470
|
writeLine(L, "");
|
|
1367
|
-
const dirLabel = config.dirs.length === 1 ? config.dirs[0] : `${config.dirs.length} directories`;
|
|
1471
|
+
const dirLabel = config.dirs.length === 1 ? config.dirs[0] ?? "" : `${config.dirs.length} directories`;
|
|
1368
1472
|
writeLine(L, ` ${C.dim}Watching: ${dirLabel}${C.reset}`);
|
|
1369
1473
|
writeLine(L, ` ${C.dim}Press Ctrl+C to exit${C.reset}`);
|
|
1370
1474
|
flushLines(L);
|
|
@@ -1415,7 +1519,7 @@ function startLive(argv) {
|
|
|
1415
1519
|
};
|
|
1416
1520
|
process.on("SIGINT", () => {
|
|
1417
1521
|
cleanup();
|
|
1418
|
-
console.log(C.dim
|
|
1522
|
+
console.log(`${C.dim}Monitor stopped.${C.reset}`);
|
|
1419
1523
|
process.exit(0);
|
|
1420
1524
|
});
|
|
1421
1525
|
process.on("SIGTERM", () => {
|
|
@@ -1430,7 +1534,7 @@ var import_node_fs3 = require("fs");
|
|
|
1430
1534
|
var import_node_path3 = require("path");
|
|
1431
1535
|
|
|
1432
1536
|
// src/graph-builder.ts
|
|
1433
|
-
var
|
|
1537
|
+
var import_node_crypto = require("crypto");
|
|
1434
1538
|
function deepFreeze(obj) {
|
|
1435
1539
|
if (obj === null || typeof obj !== "object") return obj;
|
|
1436
1540
|
if (obj instanceof Map) {
|
|
@@ -1461,8 +1565,8 @@ function createGraphBuilder(config) {
|
|
|
1461
1565
|
const generateId = config?.idGenerator ?? createCounterIdGenerator();
|
|
1462
1566
|
const agentId = config?.agentId ?? "unknown";
|
|
1463
1567
|
const trigger = config?.trigger ?? "manual";
|
|
1464
|
-
const spanId = (0,
|
|
1465
|
-
const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? (0,
|
|
1568
|
+
const spanId = (0, import_node_crypto.randomUUID)();
|
|
1569
|
+
const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? (0, import_node_crypto.randomUUID)();
|
|
1466
1570
|
const parentSpanId = config?.parentSpanId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_PARENT_SPAN_ID : void 0) ?? null;
|
|
1467
1571
|
const graphId = generateId();
|
|
1468
1572
|
const startTime = Date.now();
|
|
@@ -1682,7 +1786,7 @@ function agentIdFromFilename(filePath) {
|
|
|
1682
1786
|
const cleaned = base.replace(/-state$/, "");
|
|
1683
1787
|
return `alfred-${cleaned}`;
|
|
1684
1788
|
}
|
|
1685
|
-
function deriveAgentId(
|
|
1789
|
+
function deriveAgentId(_command) {
|
|
1686
1790
|
return "orchestrator";
|
|
1687
1791
|
}
|
|
1688
1792
|
function fileTimestamp() {
|
|
@@ -1792,14 +1896,18 @@ async function runTraced(config) {
|
|
|
1792
1896
|
const filename = `${graph.agentId}-${ts}.json`;
|
|
1793
1897
|
const outPath = (0, import_node_path3.join)(resolvedTracesDir, filename);
|
|
1794
1898
|
const resolvedOut = (0, import_node_path3.resolve)(outPath);
|
|
1795
|
-
if (!resolvedOut.startsWith(resolvedTracesDir
|
|
1796
|
-
throw new Error(
|
|
1899
|
+
if (!resolvedOut.startsWith(`${resolvedTracesDir}/`) && resolvedOut !== resolvedTracesDir) {
|
|
1900
|
+
throw new Error(
|
|
1901
|
+
`Path traversal detected: agentId "${graph.agentId}" escapes traces directory`
|
|
1902
|
+
);
|
|
1797
1903
|
}
|
|
1798
1904
|
(0, import_node_fs3.writeFileSync)(outPath, JSON.stringify(graphToJson(graph), null, 2), "utf-8");
|
|
1799
1905
|
tracePaths.push(outPath);
|
|
1800
1906
|
}
|
|
1801
1907
|
if (tracePaths.length > 0) {
|
|
1802
|
-
console.log(
|
|
1908
|
+
console.log(
|
|
1909
|
+
`\u{1F50D} Run "agentflow trace show ${orchestratorGraph.id} --traces-dir ${resolvedTracesDir}" to inspect`
|
|
1910
|
+
);
|
|
1803
1911
|
}
|
|
1804
1912
|
return {
|
|
1805
1913
|
exitCode,
|
|
@@ -1812,11 +1920,11 @@ async function runTraced(config) {
|
|
|
1812
1920
|
}
|
|
1813
1921
|
|
|
1814
1922
|
// src/trace-cli.ts
|
|
1815
|
-
var
|
|
1923
|
+
var import_node_path5 = require("path");
|
|
1816
1924
|
|
|
1817
1925
|
// src/trace-store.ts
|
|
1818
1926
|
var import_promises = require("fs/promises");
|
|
1819
|
-
var
|
|
1927
|
+
var import_node_path4 = require("path");
|
|
1820
1928
|
init_loader();
|
|
1821
1929
|
function createTraceStore(dir) {
|
|
1822
1930
|
async function ensureDir() {
|
|
@@ -1834,7 +1942,7 @@ function createTraceStore(dir) {
|
|
|
1834
1942
|
for (const file of files) {
|
|
1835
1943
|
if (!file.endsWith(".json")) continue;
|
|
1836
1944
|
try {
|
|
1837
|
-
const content = await (0, import_promises.readFile)((0,
|
|
1945
|
+
const content = await (0, import_promises.readFile)((0, import_node_path4.join)(dir, file), "utf-8");
|
|
1838
1946
|
const graph = loadGraph(content);
|
|
1839
1947
|
graphs.push(graph);
|
|
1840
1948
|
} catch {
|
|
@@ -1846,10 +1954,10 @@ function createTraceStore(dir) {
|
|
|
1846
1954
|
async save(graph) {
|
|
1847
1955
|
await ensureDir();
|
|
1848
1956
|
const json = graphToJson(graph);
|
|
1849
|
-
const filePath = (0,
|
|
1850
|
-
const resolvedBase = (0,
|
|
1851
|
-
const resolvedPath = (0,
|
|
1852
|
-
if (!resolvedPath.startsWith(resolvedBase
|
|
1957
|
+
const filePath = (0, import_node_path4.join)(dir, `${graph.id}.json`);
|
|
1958
|
+
const resolvedBase = (0, import_node_path4.resolve)(dir);
|
|
1959
|
+
const resolvedPath = (0, import_node_path4.resolve)(filePath);
|
|
1960
|
+
if (!resolvedPath.startsWith(`${resolvedBase}/`) && resolvedPath !== resolvedBase) {
|
|
1853
1961
|
throw new Error(`Path traversal detected: "${graph.id}" escapes base directory`);
|
|
1854
1962
|
}
|
|
1855
1963
|
await (0, import_promises.writeFile)(filePath, JSON.stringify(json, null, 2), "utf-8");
|
|
@@ -1857,7 +1965,7 @@ function createTraceStore(dir) {
|
|
|
1857
1965
|
},
|
|
1858
1966
|
async get(graphId) {
|
|
1859
1967
|
await ensureDir();
|
|
1860
|
-
const filePath = (0,
|
|
1968
|
+
const filePath = (0, import_node_path4.join)(dir, `${graphId}.json`);
|
|
1861
1969
|
try {
|
|
1862
1970
|
const content = await (0, import_promises.readFile)(filePath, "utf-8");
|
|
1863
1971
|
return loadGraph(content);
|
|
@@ -1979,7 +2087,8 @@ function toAsciiTree(graph) {
|
|
|
1979
2087
|
const children = getChildren(graph, nodeId);
|
|
1980
2088
|
const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
|
|
1981
2089
|
for (let i = 0; i < children.length; i++) {
|
|
1982
|
-
|
|
2090
|
+
const childId = children[i]?.id;
|
|
2091
|
+
if (childId) renderNode(childId, childPrefix, i === children.length - 1, false);
|
|
1983
2092
|
}
|
|
1984
2093
|
}
|
|
1985
2094
|
renderNode(graph.rootNodeId, "", true, true);
|
|
@@ -2053,9 +2162,9 @@ function toTimeline(graph) {
|
|
|
2053
2162
|
function getTracesDir(argv) {
|
|
2054
2163
|
const idx = argv.indexOf("--traces-dir");
|
|
2055
2164
|
if (idx !== -1 && argv[idx + 1]) {
|
|
2056
|
-
return (0,
|
|
2165
|
+
return (0, import_node_path5.resolve)(argv[idx + 1]);
|
|
2057
2166
|
}
|
|
2058
|
-
return (0,
|
|
2167
|
+
return (0, import_node_path5.resolve)("./traces");
|
|
2059
2168
|
}
|
|
2060
2169
|
function getFlag(argv, name) {
|
|
2061
2170
|
const idx = argv.indexOf(name);
|
|
@@ -2241,7 +2350,7 @@ async function handleTrace(argv) {
|
|
|
2241
2350
|
// src/watch.ts
|
|
2242
2351
|
var import_node_fs5 = require("fs");
|
|
2243
2352
|
var import_node_os = require("os");
|
|
2244
|
-
var
|
|
2353
|
+
var import_node_path6 = require("path");
|
|
2245
2354
|
|
|
2246
2355
|
// src/watch-alerts.ts
|
|
2247
2356
|
var import_node_child_process3 = require("child_process");
|
|
@@ -2367,10 +2476,10 @@ function parseDuration(input) {
|
|
|
2367
2476
|
const match = input.match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d)$/i);
|
|
2368
2477
|
if (!match) {
|
|
2369
2478
|
const n = parseInt(input, 10);
|
|
2370
|
-
return isNaN(n) ? 0 : n * 1e3;
|
|
2479
|
+
return Number.isNaN(n) ? 0 : n * 1e3;
|
|
2371
2480
|
}
|
|
2372
|
-
const value = parseFloat(match[1]);
|
|
2373
|
-
switch (match[2]
|
|
2481
|
+
const value = parseFloat(match[1] ?? "0");
|
|
2482
|
+
switch (match[2]?.toLowerCase()) {
|
|
2374
2483
|
case "s":
|
|
2375
2484
|
return value * 1e3;
|
|
2376
2485
|
case "m":
|
|
@@ -2397,7 +2506,7 @@ function loadWatchState(filePath) {
|
|
|
2397
2506
|
}
|
|
2398
2507
|
}
|
|
2399
2508
|
function saveWatchState(filePath, state) {
|
|
2400
|
-
const tmp = filePath
|
|
2509
|
+
const tmp = `${filePath}.tmp`;
|
|
2401
2510
|
try {
|
|
2402
2511
|
(0, import_node_fs4.writeFileSync)(tmp, JSON.stringify(state, null, 2), "utf8");
|
|
2403
2512
|
(0, import_node_fs4.renameSync)(tmp, filePath);
|
|
@@ -2413,12 +2522,12 @@ function estimateInterval(history) {
|
|
|
2413
2522
|
const sorted = [...history].sort((a, b) => a - b);
|
|
2414
2523
|
const deltas = [];
|
|
2415
2524
|
for (let i = 1; i < sorted.length; i++) {
|
|
2416
|
-
const d = sorted[i] - sorted[i - 1];
|
|
2525
|
+
const d = (sorted[i] ?? 0) - (sorted[i - 1] ?? 0);
|
|
2417
2526
|
if (d > 0) deltas.push(d);
|
|
2418
2527
|
}
|
|
2419
2528
|
if (deltas.length === 0) return 0;
|
|
2420
2529
|
deltas.sort((a, b) => a - b);
|
|
2421
|
-
return deltas[Math.floor(deltas.length / 2)];
|
|
2530
|
+
return deltas[Math.floor(deltas.length / 2)] ?? 0;
|
|
2422
2531
|
}
|
|
2423
2532
|
function detectTransitions(previous, currentRecords, config, now) {
|
|
2424
2533
|
const alerts = [];
|
|
@@ -2575,7 +2684,7 @@ function parseWatchArgs(argv) {
|
|
|
2575
2684
|
if (args[0] === "watch") args.shift();
|
|
2576
2685
|
let i = 0;
|
|
2577
2686
|
while (i < args.length) {
|
|
2578
|
-
const arg = args[i];
|
|
2687
|
+
const arg = args[i] ?? "";
|
|
2579
2688
|
if (arg === "--help" || arg === "-h") {
|
|
2580
2689
|
printWatchUsage();
|
|
2581
2690
|
process.exit(0);
|
|
@@ -2598,8 +2707,8 @@ function parseWatchArgs(argv) {
|
|
|
2598
2707
|
i++;
|
|
2599
2708
|
const val = args[i] ?? "";
|
|
2600
2709
|
if (val === "telegram") {
|
|
2601
|
-
const botToken = process.env
|
|
2602
|
-
const chatId = process.env
|
|
2710
|
+
const botToken = process.env.AGENTFLOW_TELEGRAM_BOT_TOKEN ?? "";
|
|
2711
|
+
const chatId = process.env.AGENTFLOW_TELEGRAM_CHAT_ID ?? "";
|
|
2603
2712
|
if (botToken && chatId) {
|
|
2604
2713
|
notifyChannels.push({ type: "telegram", botToken, chatId });
|
|
2605
2714
|
} else {
|
|
@@ -2616,7 +2725,7 @@ function parseWatchArgs(argv) {
|
|
|
2616
2725
|
} else if (arg === "--poll") {
|
|
2617
2726
|
i++;
|
|
2618
2727
|
const v = parseInt(args[i] ?? "", 10);
|
|
2619
|
-
if (!isNaN(v) && v > 0) pollIntervalMs = v * 1e3;
|
|
2728
|
+
if (!Number.isNaN(v) && v > 0) pollIntervalMs = v * 1e3;
|
|
2620
2729
|
i++;
|
|
2621
2730
|
} else if (arg === "--cooldown") {
|
|
2622
2731
|
i++;
|
|
@@ -2631,20 +2740,20 @@ function parseWatchArgs(argv) {
|
|
|
2631
2740
|
recursive = true;
|
|
2632
2741
|
i++;
|
|
2633
2742
|
} else if (!arg.startsWith("-")) {
|
|
2634
|
-
dirs.push((0,
|
|
2743
|
+
dirs.push((0, import_node_path6.resolve)(arg));
|
|
2635
2744
|
i++;
|
|
2636
2745
|
} else {
|
|
2637
2746
|
i++;
|
|
2638
2747
|
}
|
|
2639
2748
|
}
|
|
2640
|
-
if (dirs.length === 0) dirs.push((0,
|
|
2749
|
+
if (dirs.length === 0) dirs.push((0, import_node_path6.resolve)("."));
|
|
2641
2750
|
if (alertConditions.length === 0) {
|
|
2642
2751
|
alertConditions.push({ type: "error" });
|
|
2643
2752
|
alertConditions.push({ type: "recovery" });
|
|
2644
2753
|
}
|
|
2645
2754
|
notifyChannels.unshift({ type: "stdout" });
|
|
2646
2755
|
if (!stateFilePath) {
|
|
2647
|
-
stateFilePath = (0,
|
|
2756
|
+
stateFilePath = (0, import_node_path6.join)(dirs[0] ?? ".", ".agentflow-watch-state.json");
|
|
2648
2757
|
}
|
|
2649
2758
|
return {
|
|
2650
2759
|
dirs,
|
|
@@ -2652,7 +2761,7 @@ function parseWatchArgs(argv) {
|
|
|
2652
2761
|
pollIntervalMs,
|
|
2653
2762
|
alertConditions,
|
|
2654
2763
|
notifyChannels,
|
|
2655
|
-
stateFilePath: (0,
|
|
2764
|
+
stateFilePath: (0, import_node_path6.resolve)(stateFilePath),
|
|
2656
2765
|
cooldownMs
|
|
2657
2766
|
};
|
|
2658
2767
|
}
|
|
@@ -2732,7 +2841,7 @@ agentflow watch started`);
|
|
|
2732
2841
|
console.log(` Poll: ${config.pollIntervalMs / 1e3}s`);
|
|
2733
2842
|
console.log(` Alert on: ${condLabels.join(", ")}`);
|
|
2734
2843
|
console.log(
|
|
2735
|
-
` Notify: stdout${channelLabels.length > 0 ?
|
|
2844
|
+
` Notify: stdout${channelLabels.length > 0 ? `, ${channelLabels.join(", ")}` : ""}`
|
|
2736
2845
|
);
|
|
2737
2846
|
console.log(` Cooldown: ${Math.floor(config.cooldownMs / 6e4)}m`);
|
|
2738
2847
|
console.log(` State: ${config.stateFilePath}`);
|
|
@@ -2936,11 +3045,11 @@ async function runCommand(argv) {
|
|
|
2936
3045
|
if (result.tracePaths.length > 0) {
|
|
2937
3046
|
console.log("\u{1F4DD} Traces saved:");
|
|
2938
3047
|
const orchPath = result.tracePaths[0];
|
|
2939
|
-
const orchName = (0,
|
|
3048
|
+
const orchName = (0, import_node_path7.basename)(orchPath, ".json").split("-")[0] ?? "orchestrator";
|
|
2940
3049
|
console.log(` ${orchName.padEnd(14)} \u2192 ${orchPath}`);
|
|
2941
3050
|
for (let i = 1; i < result.tracePaths.length; i++) {
|
|
2942
3051
|
const tPath = result.tracePaths[i];
|
|
2943
|
-
const name = (0,
|
|
3052
|
+
const name = (0, import_node_path7.basename)(tPath, ".json").replace(/-\d{4}-.*$/, "");
|
|
2944
3053
|
const isLast = i === result.tracePaths.length - 1;
|
|
2945
3054
|
const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
2946
3055
|
console.log(` ${prefix} ${name.padEnd(12)} \u2192 ${tPath} (state changed)`);
|
|
@@ -2965,7 +3074,7 @@ function parseAuditArgs(argv) {
|
|
|
2965
3074
|
if (args[0] === "audit") args.shift();
|
|
2966
3075
|
let i = 0;
|
|
2967
3076
|
while (i < args.length) {
|
|
2968
|
-
const arg = args[i];
|
|
3077
|
+
const arg = args[i] ?? "";
|
|
2969
3078
|
if (arg === "--help" || arg === "-h") {
|
|
2970
3079
|
printAuditUsage();
|
|
2971
3080
|
process.exit(0);
|
|
@@ -2989,7 +3098,7 @@ function parseAuditArgs(argv) {
|
|
|
2989
3098
|
systemdUnit = null;
|
|
2990
3099
|
i++;
|
|
2991
3100
|
} else if (!arg.startsWith("-")) {
|
|
2992
|
-
discoverDirs.push((0,
|
|
3101
|
+
discoverDirs.push((0, import_node_path7.resolve)(arg));
|
|
2993
3102
|
i++;
|
|
2994
3103
|
} else {
|
|
2995
3104
|
i++;
|
|
@@ -2998,12 +3107,16 @@ function parseAuditArgs(argv) {
|
|
|
2998
3107
|
if (!processName && !pidFile && !workersFile && discoverDirs.length > 0) {
|
|
2999
3108
|
const discovered = discoverProcessConfig(discoverDirs);
|
|
3000
3109
|
if (discovered) {
|
|
3001
|
-
console.log(
|
|
3110
|
+
console.log(
|
|
3111
|
+
`Auto-discovered: process="${discovered.processName}"${discovered.pidFile ? ` pid-file=${discovered.pidFile}` : ""}${discovered.workersFile ? ` workers=${discovered.workersFile}` : ""}`
|
|
3112
|
+
);
|
|
3002
3113
|
return { ...discovered, systemdUnit };
|
|
3003
3114
|
}
|
|
3004
3115
|
}
|
|
3005
3116
|
if (!processName) {
|
|
3006
|
-
console.error(
|
|
3117
|
+
console.error(
|
|
3118
|
+
"Error: --process <name> is required, or provide directories for auto-discovery."
|
|
3119
|
+
);
|
|
3007
3120
|
console.error("Examples:");
|
|
3008
3121
|
console.error(" agentflow audit --process alfred --pid-file ./data/alfred.pid");
|
|
3009
3122
|
console.error(" agentflow audit ./data # auto-discovers *.pid and workers.json");
|
|
@@ -3051,7 +3164,7 @@ function runAudit(argv) {
|
|
|
3051
3164
|
async function main() {
|
|
3052
3165
|
const argv = process.argv.slice(2);
|
|
3053
3166
|
const knownCommands = ["run", "live", "watch", "trace", "audit"];
|
|
3054
|
-
if (argv.length === 0 || !knownCommands.includes(argv[0]) && (argv.includes("--help") || argv.includes("-h"))) {
|
|
3167
|
+
if (argv.length === 0 || !knownCommands.includes(argv[0] ?? "") && (argv.includes("--help") || argv.includes("-h"))) {
|
|
3055
3168
|
printHelp();
|
|
3056
3169
|
process.exit(0);
|
|
3057
3170
|
}
|