agentflow-core 0.6.3 → 0.8.0

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.cjs CHANGED
@@ -93,7 +93,7 @@ var init_loader = __esm({
93
93
  });
94
94
 
95
95
  // src/cli.ts
96
- var import_path3 = require("path");
96
+ var import_node_path7 = require("path");
97
97
 
98
98
  // src/live.ts
99
99
  var import_node_fs2 = require("fs");
@@ -191,7 +191,7 @@ function groupByTraceId(graphs) {
191
191
  }
192
192
  function stitchTrace(graphs) {
193
193
  if (graphs.length === 0) throw new Error("No graphs to stitch");
194
- const traceId = graphs[0].traceId ?? "";
194
+ const traceId = graphs[0]?.traceId ?? "";
195
195
  const graphsBySpan = /* @__PURE__ */ new Map();
196
196
  const childMap = /* @__PURE__ */ new Map();
197
197
  let rootGraph = null;
@@ -268,7 +268,7 @@ function pidMatchesName(pid, name) {
268
268
  function readPidFile(path) {
269
269
  try {
270
270
  const pid = parseInt((0, import_node_fs.readFileSync)(path, "utf8").trim(), 10);
271
- return isNaN(pid) ? null : pid;
271
+ return Number.isNaN(pid) ? null : pid;
272
272
  } catch {
273
273
  return null;
274
274
  }
@@ -312,11 +312,11 @@ function auditSystemd(config) {
312
312
  const [k, ...v] = line.split("=");
313
313
  if (k) props[k.trim()] = v.join("=").trim();
314
314
  }
315
- const activeState = props["ActiveState"] ?? "unknown";
316
- const subState = props["SubState"] ?? "unknown";
317
- const mainPid = parseInt(props["MainPID"] ?? "0", 10);
318
- const restarts = parseInt(props["NRestarts"] ?? "0", 10);
319
- const result = props["Result"] ?? "unknown";
315
+ const activeState = props.ActiveState ?? "unknown";
316
+ const subState = props.SubState ?? "unknown";
317
+ const mainPid = parseInt(props.MainPID ?? "0", 10);
318
+ const restarts = parseInt(props.NRestarts ?? "0", 10);
319
+ const result = props.Result ?? "unknown";
320
320
  return {
321
321
  unit,
322
322
  activeState,
@@ -369,10 +369,10 @@ function readCmdline(pid) {
369
369
  }
370
370
  function getOsProcesses(processName) {
371
371
  try {
372
- const raw = (0, import_node_child_process.execSync)(
373
- `ps -eo pid,pcpu,pmem,etime,lstart,args --no-headers`,
374
- { encoding: "utf8", timeout: 5e3 }
375
- );
372
+ const raw = (0, import_node_child_process.execSync)(`ps -eo pid,pcpu,pmem,etime,lstart,args --no-headers`, {
373
+ encoding: "utf8",
374
+ timeout: 5e3
375
+ });
376
376
  const results = [];
377
377
  for (const line of raw.split("\n")) {
378
378
  if (!line.includes(processName)) continue;
@@ -380,7 +380,7 @@ function getOsProcesses(processName) {
380
380
  const trimmed = line.trim();
381
381
  const parts = trimmed.split(/\s+/);
382
382
  const pid = parseInt(parts[0] ?? "0", 10);
383
- if (isNaN(pid) || pid <= 0) continue;
383
+ if (Number.isNaN(pid) || pid <= 0) continue;
384
384
  const cpu = parts[1] ?? "0";
385
385
  const mem = parts[2] ?? "0";
386
386
  const elapsed = parts[3] ?? "";
@@ -457,16 +457,45 @@ function auditProcesses(config) {
457
457
  }
458
458
  }
459
459
  if (systemd?.mainPid) knownPids.add(systemd.mainPid);
460
+ const childPids = /* @__PURE__ */ new Set();
461
+ for (const knownPid of knownPids) {
462
+ try {
463
+ const childrenRaw = (0, import_node_fs.readFileSync)(
464
+ `/proc/${knownPid}/task/${knownPid}/children`,
465
+ "utf8"
466
+ ).trim();
467
+ if (childrenRaw) {
468
+ for (const c of childrenRaw.split(/\s+/)) {
469
+ const cp = parseInt(c, 10);
470
+ if (!Number.isNaN(cp)) childPids.add(cp);
471
+ }
472
+ }
473
+ } catch {
474
+ }
475
+ }
476
+ for (const p of osProcesses) {
477
+ if (knownPids.has(p.pid)) continue;
478
+ try {
479
+ const statusContent = (0, import_node_fs.readFileSync)(`/proc/${p.pid}/status`, "utf8");
480
+ const ppidMatch = statusContent.match(/^PPid:\s+(\d+)/m);
481
+ if (ppidMatch) {
482
+ const ppid = parseInt(ppidMatch[1] ?? "0", 10);
483
+ if (knownPids.has(ppid)) childPids.add(p.pid);
484
+ }
485
+ } catch {
486
+ }
487
+ }
460
488
  const selfPid = process.pid;
461
489
  const selfPpid = process.ppid;
462
490
  const orphans = osProcesses.filter(
463
- (p) => !knownPids.has(p.pid) && p.pid !== selfPid && p.pid !== selfPpid
491
+ (p) => !knownPids.has(p.pid) && !childPids.has(p.pid) && p.pid !== selfPid && p.pid !== selfPpid
464
492
  );
465
493
  const problems = [];
466
494
  if (pidFile?.stale) problems.push(`Stale PID file: ${pidFile.reason}`);
467
495
  if (systemd?.crashLooping) problems.push("Systemd unit is crash-looping (auto-restart)");
468
496
  if (systemd?.failed) problems.push("Systemd unit has failed");
469
- if (systemd && systemd.restarts > 10) problems.push(`High systemd restart count: ${systemd.restarts}`);
497
+ if (systemd && systemd.restarts > 10)
498
+ problems.push(`High systemd restart count: ${systemd.restarts}`);
470
499
  if (pidFile?.pid && systemd?.mainPid && pidFile.pid !== systemd.mainPid) {
471
500
  problems.push(`PID mismatch: file says ${pidFile.pid}, systemd says ${systemd.mainPid}`);
472
501
  }
@@ -475,15 +504,24 @@ function auditProcesses(config) {
475
504
  if (w.stale) problems.push(`Worker "${w.name}" (pid ${w.pid}) declares running but is dead`);
476
505
  }
477
506
  }
478
- if (orphans.length > 0) problems.push(`${orphans.length} orphan process(es) not tracked by PID file or workers registry`);
507
+ if (orphans.length > 0)
508
+ problems.push(
509
+ `${orphans.length} orphan process(es) not tracked by PID file or workers registry`
510
+ );
479
511
  return { pidFile, systemd, workers, osProcesses, orphans, problems };
480
512
  }
481
513
  function formatAuditReport(result) {
482
514
  const lines = [];
483
515
  lines.push("");
484
- lines.push("\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");
485
- lines.push("\u2551 \u{1F50D} P R O C E S S A U D I T \u2551");
486
- lines.push("\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");
516
+ lines.push(
517
+ "\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"
518
+ );
519
+ lines.push(
520
+ "\u2551 \u{1F50D} P R O C E S S A U D I T \u2551"
521
+ );
522
+ lines.push(
523
+ "\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"
524
+ );
487
525
  if (result.pidFile) {
488
526
  const pf = result.pidFile;
489
527
  const icon = pf.pid && pf.alive && pf.matchesProcess ? "\u2705" : pf.stale ? "\u26A0\uFE0F " : "\u2139\uFE0F ";
@@ -501,25 +539,33 @@ function formatAuditReport(result) {
501
539
  }
502
540
  if (result.workers) {
503
541
  const w = result.workers;
504
- lines.push(`
505
- Workers (orchestrator pid ${w.orchestratorPid ?? "unknown"} ${w.orchestratorAlive ? "\u2705" : "\u274C"})`);
542
+ lines.push(
543
+ `
544
+ Workers (orchestrator pid ${w.orchestratorPid ?? "unknown"} ${w.orchestratorAlive ? "\u2705" : "\u274C"})`
545
+ );
506
546
  for (const worker of w.workers) {
507
547
  const icon = worker.declaredStatus === "running" && worker.alive ? "\u{1F7E2}" : worker.stale ? "\u{1F534} STALE" : "\u26AA";
508
- lines.push(` ${icon} ${worker.name.padEnd(14)} pid=${String(worker.pid ?? "-").padEnd(8)} status=${worker.declaredStatus}`);
548
+ lines.push(
549
+ ` ${icon} ${worker.name.padEnd(14)} pid=${String(worker.pid ?? "-").padEnd(8)} status=${worker.declaredStatus}`
550
+ );
509
551
  }
510
552
  }
511
553
  if (result.osProcesses.length > 0) {
512
554
  lines.push(`
513
555
  OS Processes (${result.osProcesses.length} total)`);
514
556
  for (const p of result.osProcesses) {
515
- lines.push(` 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)}`);
557
+ lines.push(
558
+ ` 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)}`
559
+ );
516
560
  }
517
561
  }
518
562
  if (result.orphans.length > 0) {
519
563
  lines.push(`
520
564
  \u26A0\uFE0F ${result.orphans.length} ORPHAN PROCESS(ES):`);
521
565
  for (const p of result.orphans) {
522
- lines.push(` PID ${String(p.pid).padEnd(8)} CPU=${p.cpu.padEnd(6)} MEM=${p.mem.padEnd(6)} Up=${p.elapsed}`);
566
+ lines.push(
567
+ ` PID ${String(p.pid).padEnd(8)} CPU=${p.cpu.padEnd(6)} MEM=${p.mem.padEnd(6)} Up=${p.elapsed}`
568
+ );
523
569
  lines.push(` Started: ${p.started}`);
524
570
  lines.push(` Command: ${p.cmdline || p.command}`);
525
571
  }
@@ -564,7 +610,7 @@ function parseArgs(argv) {
564
610
  } else if (arg === "--refresh" || arg === "-r") {
565
611
  i++;
566
612
  const v = parseInt(args[i] ?? "", 10);
567
- if (!isNaN(v) && v > 0) config.refreshMs = v * 1e3;
613
+ if (!Number.isNaN(v) && v > 0) config.refreshMs = v * 1e3;
568
614
  i++;
569
615
  } else if (arg === "--recursive" || arg === "-R") {
570
616
  config.recursive = true;
@@ -645,12 +691,22 @@ function scanFiles(dirs, recursive) {
645
691
  if (!stat.isFile()) continue;
646
692
  if (f.endsWith(".json")) {
647
693
  seen.add(fp);
648
- const entry = { filename: f, path: fp, mtime: stat.mtime.getTime(), ext: ".json" };
694
+ const entry = {
695
+ filename: f,
696
+ path: fp,
697
+ mtime: stat.mtime.getTime(),
698
+ ext: ".json"
699
+ };
649
700
  results.push(entry);
650
701
  dirResults.push(entry);
651
702
  } else if (f.endsWith(".jsonl")) {
652
703
  seen.add(fp);
653
- const entry = { filename: f, path: fp, mtime: stat.mtime.getTime(), ext: ".jsonl" };
704
+ const entry = {
705
+ filename: f,
706
+ path: fp,
707
+ mtime: stat.mtime.getTime(),
708
+ ext: ".jsonl"
709
+ };
654
710
  results.push(entry);
655
711
  dirResults.push(entry);
656
712
  }
@@ -712,7 +768,7 @@ function findTimestamp(obj) {
712
768
  if (typeof val === "number") return val > 1e12 ? val : val * 1e3;
713
769
  if (typeof val === "string") {
714
770
  const d = Date.parse(val);
715
- if (!isNaN(d)) return d;
771
+ if (!Number.isNaN(d)) return d;
716
772
  }
717
773
  }
718
774
  return 0;
@@ -744,7 +800,7 @@ function extractDetail(obj) {
744
800
  }
745
801
  return parts.join(" | ") || "";
746
802
  }
747
- function tryLoadTrace(fp, raw) {
803
+ function tryLoadTrace(_fp, raw) {
748
804
  if (typeof raw !== "object" || raw === null) return null;
749
805
  const obj = raw;
750
806
  if (!("nodes" in obj)) return null;
@@ -995,13 +1051,14 @@ function writeLine(lines, text) {
995
1051
  }
996
1052
  function flushLines(lines) {
997
1053
  process.stdout.write("\x1B[H");
998
- process.stdout.write(lines.join("\n") + "\n");
1054
+ process.stdout.write(`${lines.join("\n")}
1055
+ `);
999
1056
  process.stdout.write("\x1B[J");
1000
1057
  }
1001
1058
  var prevFileCount = 0;
1002
1059
  var newExecCount = 0;
1003
1060
  var sessionStart = Date.now();
1004
- var firstRender = true;
1061
+ var liveRunning = false;
1005
1062
  var cachedAuditConfig = null;
1006
1063
  var cachedAuditResult = null;
1007
1064
  var lastAuditTime = 0;
@@ -1089,7 +1146,7 @@ function render(config) {
1089
1146
  const status = fail > 0 ? "error" : running > 0 ? "running" : ok > 0 ? "ok" : "unknown";
1090
1147
  groups.push({
1091
1148
  name: groupName,
1092
- source: records[0].source,
1149
+ source: records[0]?.source ?? "trace",
1093
1150
  status,
1094
1151
  lastTs,
1095
1152
  detail: `${records.length} agents`,
@@ -1135,8 +1192,10 @@ function render(config) {
1135
1192
  cachedAuditResult = auditResult;
1136
1193
  lastAuditTime = now;
1137
1194
  } catch (err) {
1138
- process.stderr.write(`[agentflow] process audit error: ${err instanceof Error ? err.message : err}
1139
- `);
1195
+ process.stderr.write(
1196
+ `[agentflow] process audit error: ${err instanceof Error ? err.message : err}
1197
+ `
1198
+ );
1140
1199
  }
1141
1200
  }
1142
1201
  } else {
@@ -1193,14 +1252,10 @@ function render(config) {
1193
1252
  return new Date(ts).toLocaleTimeString();
1194
1253
  }
1195
1254
  function truncate(s, max) {
1196
- return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
1255
+ return s.length > max ? `${s.slice(0, max - 1)}\u2026` : s;
1197
1256
  }
1198
1257
  const termWidth = process.stdout.columns || 120;
1199
1258
  const detailWidth = Math.max(20, termWidth - 60);
1200
- if (firstRender) {
1201
- process.stdout.write("\x1B[2J");
1202
- firstRender = false;
1203
- }
1204
1259
  const L = [];
1205
1260
  writeLine(L, `${C.bold}${C.cyan}\u2554${"\u2550".repeat(70)}\u2557${C.reset}`);
1206
1261
  writeLine(
@@ -1238,7 +1293,8 @@ function render(config) {
1238
1293
  if (ar.systemd) {
1239
1294
  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}`;
1240
1295
  sysdLabel = ` ${C.bold}Systemd${C.reset} ${si} ${ar.systemd.activeState}`;
1241
- if (ar.systemd.restarts > 0) sysdLabel += ` ${C.dim}(${ar.systemd.restarts} restarts)${C.reset}`;
1296
+ if (ar.systemd.restarts > 0)
1297
+ sysdLabel += ` ${C.dim}(${ar.systemd.restarts} restarts)${C.reset}`;
1242
1298
  }
1243
1299
  let pidLabel = "";
1244
1300
  if (ar.pidFile?.pid) {
@@ -1247,7 +1303,10 @@ function render(config) {
1247
1303
  }
1248
1304
  writeLine(L, "");
1249
1305
  writeLine(L, ` ${C.bold}${C.under}Process Health${C.reset}`);
1250
- writeLine(L, ` ${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}`}`);
1306
+ writeLine(
1307
+ L,
1308
+ ` ${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}`}`
1309
+ );
1251
1310
  if (workerParts.length > 0) {
1252
1311
  writeLine(L, ` ${C.dim}Workers${C.reset} ${workerParts.join(" ")}`);
1253
1312
  }
@@ -1259,7 +1318,10 @@ function render(config) {
1259
1318
  if (ar.orphans.length > 0) {
1260
1319
  for (const o of ar.orphans.slice(0, 5)) {
1261
1320
  const cmd = (o.cmdline || o.command).substring(0, detailWidth);
1262
- writeLine(L, ` ${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}`);
1321
+ writeLine(
1322
+ L,
1323
+ ` ${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}`
1324
+ );
1263
1325
  }
1264
1326
  if (ar.orphans.length > 5) {
1265
1327
  writeLine(L, ` ${C.dim}... +${ar.orphans.length - 5} more orphans${C.reset}`);
@@ -1333,7 +1395,7 @@ function render(config) {
1333
1395
  for (let i = 0; i < Math.min(tree.length, 6); i++) {
1334
1396
  const tg = tree[i];
1335
1397
  const depth = getDistDepth(dt, tg.spanId);
1336
- const indent = " " + "\u2502 ".repeat(Math.max(0, depth - 1));
1398
+ const indent = ` ${"\u2502 ".repeat(Math.max(0, depth - 1))}`;
1337
1399
  const isLast = i === tree.length - 1 || getDistDepth(dt, tree[i + 1]?.spanId) <= depth;
1338
1400
  const conn = depth === 0 ? " " : isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
1339
1401
  const gs = tg.status === "completed" ? `${C.green}\u2713${C.reset}` : tg.status === "failed" ? `${C.red}\u2717${C.reset}` : `${C.yellow}\u23F3${C.reset}`;
@@ -1354,7 +1416,7 @@ function render(config) {
1354
1416
  const t = new Date(r.lastActive).toLocaleTimeString();
1355
1417
  const agent = truncate(r.id, 26).padEnd(26);
1356
1418
  const age = Math.floor((Date.now() - r.lastActive) / 1e3);
1357
- const ageStr = age < 60 ? age + "s ago" : age < 3600 ? Math.floor(age / 60) + "m ago" : Math.floor(age / 3600) + "h ago";
1419
+ const ageStr = age < 60 ? `${age}s ago` : age < 3600 ? `${Math.floor(age / 60)}m ago` : `${Math.floor(age / 3600)}h ago`;
1358
1420
  const det = truncate(r.detail, detailWidth);
1359
1421
  writeLine(
1360
1422
  L,
@@ -1395,6 +1457,9 @@ function startLive(argv) {
1395
1457
  console.warn(`Skipping non-existent: ${invalid.join(", ")}`);
1396
1458
  }
1397
1459
  config.dirs = valid;
1460
+ process.stdout.write("\x1B[?1049h");
1461
+ process.stdout.write("\x1B[?25l");
1462
+ liveRunning = true;
1398
1463
  render(config);
1399
1464
  let debounce = null;
1400
1465
  for (const dir of config.dirs) {
@@ -1407,8 +1472,20 @@ function startLive(argv) {
1407
1472
  }
1408
1473
  }
1409
1474
  setInterval(() => render(config), config.refreshMs);
1475
+ const cleanup = () => {
1476
+ if (liveRunning) {
1477
+ liveRunning = false;
1478
+ process.stdout.write("\x1B[?25h");
1479
+ process.stdout.write("\x1B[?1049l");
1480
+ }
1481
+ };
1410
1482
  process.on("SIGINT", () => {
1411
- console.log("\n" + C.dim + "Monitor stopped." + C.reset);
1483
+ cleanup();
1484
+ console.log(`${C.dim}Monitor stopped.${C.reset}`);
1485
+ process.exit(0);
1486
+ });
1487
+ process.on("SIGTERM", () => {
1488
+ cleanup();
1412
1489
  process.exit(0);
1413
1490
  });
1414
1491
  }
@@ -1419,7 +1496,7 @@ var import_node_fs3 = require("fs");
1419
1496
  var import_node_path3 = require("path");
1420
1497
 
1421
1498
  // src/graph-builder.ts
1422
- var import_crypto = require("crypto");
1499
+ var import_node_crypto = require("crypto");
1423
1500
  function deepFreeze(obj) {
1424
1501
  if (obj === null || typeof obj !== "object") return obj;
1425
1502
  if (obj instanceof Map) {
@@ -1450,8 +1527,8 @@ function createGraphBuilder(config) {
1450
1527
  const generateId = config?.idGenerator ?? createCounterIdGenerator();
1451
1528
  const agentId = config?.agentId ?? "unknown";
1452
1529
  const trigger = config?.trigger ?? "manual";
1453
- const spanId = (0, import_crypto.randomUUID)();
1454
- const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? (0, import_crypto.randomUUID)();
1530
+ const spanId = (0, import_node_crypto.randomUUID)();
1531
+ const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? (0, import_node_crypto.randomUUID)();
1455
1532
  const parentSpanId = config?.parentSpanId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_PARENT_SPAN_ID : void 0) ?? null;
1456
1533
  const graphId = generateId();
1457
1534
  const startTime = Date.now();
@@ -1671,7 +1748,7 @@ function agentIdFromFilename(filePath) {
1671
1748
  const cleaned = base.replace(/-state$/, "");
1672
1749
  return `alfred-${cleaned}`;
1673
1750
  }
1674
- function deriveAgentId(command) {
1751
+ function deriveAgentId(_command) {
1675
1752
  return "orchestrator";
1676
1753
  }
1677
1754
  function fileTimestamp() {
@@ -1781,14 +1858,18 @@ async function runTraced(config) {
1781
1858
  const filename = `${graph.agentId}-${ts}.json`;
1782
1859
  const outPath = (0, import_node_path3.join)(resolvedTracesDir, filename);
1783
1860
  const resolvedOut = (0, import_node_path3.resolve)(outPath);
1784
- if (!resolvedOut.startsWith(resolvedTracesDir + "/") && resolvedOut !== resolvedTracesDir) {
1785
- throw new Error(`Path traversal detected: agentId "${graph.agentId}" escapes traces directory`);
1861
+ if (!resolvedOut.startsWith(`${resolvedTracesDir}/`) && resolvedOut !== resolvedTracesDir) {
1862
+ throw new Error(
1863
+ `Path traversal detected: agentId "${graph.agentId}" escapes traces directory`
1864
+ );
1786
1865
  }
1787
1866
  (0, import_node_fs3.writeFileSync)(outPath, JSON.stringify(graphToJson(graph), null, 2), "utf-8");
1788
1867
  tracePaths.push(outPath);
1789
1868
  }
1790
1869
  if (tracePaths.length > 0) {
1791
- console.log(`\u{1F50D} Run "agentflow trace show ${orchestratorGraph.id} --traces-dir ${resolvedTracesDir}" to inspect`);
1870
+ console.log(
1871
+ `\u{1F50D} Run "agentflow trace show ${orchestratorGraph.id} --traces-dir ${resolvedTracesDir}" to inspect`
1872
+ );
1792
1873
  }
1793
1874
  return {
1794
1875
  exitCode,
@@ -1801,11 +1882,11 @@ async function runTraced(config) {
1801
1882
  }
1802
1883
 
1803
1884
  // src/trace-cli.ts
1804
- var import_path2 = require("path");
1885
+ var import_node_path5 = require("path");
1805
1886
 
1806
1887
  // src/trace-store.ts
1807
1888
  var import_promises = require("fs/promises");
1808
- var import_path = require("path");
1889
+ var import_node_path4 = require("path");
1809
1890
  init_loader();
1810
1891
  function createTraceStore(dir) {
1811
1892
  async function ensureDir() {
@@ -1823,7 +1904,7 @@ function createTraceStore(dir) {
1823
1904
  for (const file of files) {
1824
1905
  if (!file.endsWith(".json")) continue;
1825
1906
  try {
1826
- const content = await (0, import_promises.readFile)((0, import_path.join)(dir, file), "utf-8");
1907
+ const content = await (0, import_promises.readFile)((0, import_node_path4.join)(dir, file), "utf-8");
1827
1908
  const graph = loadGraph(content);
1828
1909
  graphs.push(graph);
1829
1910
  } catch {
@@ -1835,10 +1916,10 @@ function createTraceStore(dir) {
1835
1916
  async save(graph) {
1836
1917
  await ensureDir();
1837
1918
  const json = graphToJson(graph);
1838
- const filePath = (0, import_path.join)(dir, `${graph.id}.json`);
1839
- const resolvedBase = (0, import_path.resolve)(dir);
1840
- const resolvedPath = (0, import_path.resolve)(filePath);
1841
- if (!resolvedPath.startsWith(resolvedBase + "/") && resolvedPath !== resolvedBase) {
1919
+ const filePath = (0, import_node_path4.join)(dir, `${graph.id}.json`);
1920
+ const resolvedBase = (0, import_node_path4.resolve)(dir);
1921
+ const resolvedPath = (0, import_node_path4.resolve)(filePath);
1922
+ if (!resolvedPath.startsWith(`${resolvedBase}/`) && resolvedPath !== resolvedBase) {
1842
1923
  throw new Error(`Path traversal detected: "${graph.id}" escapes base directory`);
1843
1924
  }
1844
1925
  await (0, import_promises.writeFile)(filePath, JSON.stringify(json, null, 2), "utf-8");
@@ -1846,7 +1927,7 @@ function createTraceStore(dir) {
1846
1927
  },
1847
1928
  async get(graphId) {
1848
1929
  await ensureDir();
1849
- const filePath = (0, import_path.join)(dir, `${graphId}.json`);
1930
+ const filePath = (0, import_node_path4.join)(dir, `${graphId}.json`);
1850
1931
  try {
1851
1932
  const content = await (0, import_promises.readFile)(filePath, "utf-8");
1852
1933
  return loadGraph(content);
@@ -1968,7 +2049,8 @@ function toAsciiTree(graph) {
1968
2049
  const children = getChildren(graph, nodeId);
1969
2050
  const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
1970
2051
  for (let i = 0; i < children.length; i++) {
1971
- renderNode(children[i].id, childPrefix, i === children.length - 1, false);
2052
+ const childId = children[i]?.id;
2053
+ if (childId) renderNode(childId, childPrefix, i === children.length - 1, false);
1972
2054
  }
1973
2055
  }
1974
2056
  renderNode(graph.rootNodeId, "", true, true);
@@ -2042,9 +2124,9 @@ function toTimeline(graph) {
2042
2124
  function getTracesDir(argv) {
2043
2125
  const idx = argv.indexOf("--traces-dir");
2044
2126
  if (idx !== -1 && argv[idx + 1]) {
2045
- return (0, import_path2.resolve)(argv[idx + 1]);
2127
+ return (0, import_node_path5.resolve)(argv[idx + 1]);
2046
2128
  }
2047
- return (0, import_path2.resolve)("./traces");
2129
+ return (0, import_node_path5.resolve)("./traces");
2048
2130
  }
2049
2131
  function getFlag(argv, name) {
2050
2132
  const idx = argv.indexOf(name);
@@ -2230,7 +2312,7 @@ async function handleTrace(argv) {
2230
2312
  // src/watch.ts
2231
2313
  var import_node_fs5 = require("fs");
2232
2314
  var import_node_os = require("os");
2233
- var import_node_path4 = require("path");
2315
+ var import_node_path6 = require("path");
2234
2316
 
2235
2317
  // src/watch-alerts.ts
2236
2318
  var import_node_child_process3 = require("child_process");
@@ -2356,10 +2438,10 @@ function parseDuration(input) {
2356
2438
  const match = input.match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d)$/i);
2357
2439
  if (!match) {
2358
2440
  const n = parseInt(input, 10);
2359
- return isNaN(n) ? 0 : n * 1e3;
2441
+ return Number.isNaN(n) ? 0 : n * 1e3;
2360
2442
  }
2361
2443
  const value = parseFloat(match[1]);
2362
- switch (match[2].toLowerCase()) {
2444
+ switch (match[2]?.toLowerCase()) {
2363
2445
  case "s":
2364
2446
  return value * 1e3;
2365
2447
  case "m":
@@ -2386,7 +2468,7 @@ function loadWatchState(filePath) {
2386
2468
  }
2387
2469
  }
2388
2470
  function saveWatchState(filePath, state) {
2389
- const tmp = filePath + ".tmp";
2471
+ const tmp = `${filePath}.tmp`;
2390
2472
  try {
2391
2473
  (0, import_node_fs4.writeFileSync)(tmp, JSON.stringify(state, null, 2), "utf8");
2392
2474
  (0, import_node_fs4.renameSync)(tmp, filePath);
@@ -2587,8 +2669,8 @@ function parseWatchArgs(argv) {
2587
2669
  i++;
2588
2670
  const val = args[i] ?? "";
2589
2671
  if (val === "telegram") {
2590
- const botToken = process.env["AGENTFLOW_TELEGRAM_BOT_TOKEN"] ?? "";
2591
- const chatId = process.env["AGENTFLOW_TELEGRAM_CHAT_ID"] ?? "";
2672
+ const botToken = process.env.AGENTFLOW_TELEGRAM_BOT_TOKEN ?? "";
2673
+ const chatId = process.env.AGENTFLOW_TELEGRAM_CHAT_ID ?? "";
2592
2674
  if (botToken && chatId) {
2593
2675
  notifyChannels.push({ type: "telegram", botToken, chatId });
2594
2676
  } else {
@@ -2605,7 +2687,7 @@ function parseWatchArgs(argv) {
2605
2687
  } else if (arg === "--poll") {
2606
2688
  i++;
2607
2689
  const v = parseInt(args[i] ?? "", 10);
2608
- if (!isNaN(v) && v > 0) pollIntervalMs = v * 1e3;
2690
+ if (!Number.isNaN(v) && v > 0) pollIntervalMs = v * 1e3;
2609
2691
  i++;
2610
2692
  } else if (arg === "--cooldown") {
2611
2693
  i++;
@@ -2620,20 +2702,20 @@ function parseWatchArgs(argv) {
2620
2702
  recursive = true;
2621
2703
  i++;
2622
2704
  } else if (!arg.startsWith("-")) {
2623
- dirs.push((0, import_node_path4.resolve)(arg));
2705
+ dirs.push((0, import_node_path6.resolve)(arg));
2624
2706
  i++;
2625
2707
  } else {
2626
2708
  i++;
2627
2709
  }
2628
2710
  }
2629
- if (dirs.length === 0) dirs.push((0, import_node_path4.resolve)("."));
2711
+ if (dirs.length === 0) dirs.push((0, import_node_path6.resolve)("."));
2630
2712
  if (alertConditions.length === 0) {
2631
2713
  alertConditions.push({ type: "error" });
2632
2714
  alertConditions.push({ type: "recovery" });
2633
2715
  }
2634
2716
  notifyChannels.unshift({ type: "stdout" });
2635
2717
  if (!stateFilePath) {
2636
- stateFilePath = (0, import_node_path4.join)(dirs[0], ".agentflow-watch-state.json");
2718
+ stateFilePath = (0, import_node_path6.join)(dirs[0], ".agentflow-watch-state.json");
2637
2719
  }
2638
2720
  return {
2639
2721
  dirs,
@@ -2641,7 +2723,7 @@ function parseWatchArgs(argv) {
2641
2723
  pollIntervalMs,
2642
2724
  alertConditions,
2643
2725
  notifyChannels,
2644
- stateFilePath: (0, import_node_path4.resolve)(stateFilePath),
2726
+ stateFilePath: (0, import_node_path6.resolve)(stateFilePath),
2645
2727
  cooldownMs
2646
2728
  };
2647
2729
  }
@@ -2721,7 +2803,7 @@ agentflow watch started`);
2721
2803
  console.log(` Poll: ${config.pollIntervalMs / 1e3}s`);
2722
2804
  console.log(` Alert on: ${condLabels.join(", ")}`);
2723
2805
  console.log(
2724
- ` Notify: stdout${channelLabels.length > 0 ? ", " + channelLabels.join(", ") : ""}`
2806
+ ` Notify: stdout${channelLabels.length > 0 ? `, ${channelLabels.join(", ")}` : ""}`
2725
2807
  );
2726
2808
  console.log(` Cooldown: ${Math.floor(config.cooldownMs / 6e4)}m`);
2727
2809
  console.log(` State: ${config.stateFilePath}`);
@@ -2925,11 +3007,11 @@ async function runCommand(argv) {
2925
3007
  if (result.tracePaths.length > 0) {
2926
3008
  console.log("\u{1F4DD} Traces saved:");
2927
3009
  const orchPath = result.tracePaths[0];
2928
- const orchName = (0, import_path3.basename)(orchPath, ".json").split("-")[0] ?? "orchestrator";
3010
+ const orchName = (0, import_node_path7.basename)(orchPath, ".json").split("-")[0] ?? "orchestrator";
2929
3011
  console.log(` ${orchName.padEnd(14)} \u2192 ${orchPath}`);
2930
3012
  for (let i = 1; i < result.tracePaths.length; i++) {
2931
3013
  const tPath = result.tracePaths[i];
2932
- const name = (0, import_path3.basename)(tPath, ".json").replace(/-\d{4}-.*$/, "");
3014
+ const name = (0, import_node_path7.basename)(tPath, ".json").replace(/-\d{4}-.*$/, "");
2933
3015
  const isLast = i === result.tracePaths.length - 1;
2934
3016
  const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
2935
3017
  console.log(` ${prefix} ${name.padEnd(12)} \u2192 ${tPath} (state changed)`);
@@ -2978,7 +3060,7 @@ function parseAuditArgs(argv) {
2978
3060
  systemdUnit = null;
2979
3061
  i++;
2980
3062
  } else if (!arg.startsWith("-")) {
2981
- discoverDirs.push((0, import_path3.resolve)(arg));
3063
+ discoverDirs.push((0, import_node_path7.resolve)(arg));
2982
3064
  i++;
2983
3065
  } else {
2984
3066
  i++;
@@ -2987,12 +3069,16 @@ function parseAuditArgs(argv) {
2987
3069
  if (!processName && !pidFile && !workersFile && discoverDirs.length > 0) {
2988
3070
  const discovered = discoverProcessConfig(discoverDirs);
2989
3071
  if (discovered) {
2990
- console.log(`Auto-discovered: process="${discovered.processName}"${discovered.pidFile ? ` pid-file=${discovered.pidFile}` : ""}${discovered.workersFile ? ` workers=${discovered.workersFile}` : ""}`);
3072
+ console.log(
3073
+ `Auto-discovered: process="${discovered.processName}"${discovered.pidFile ? ` pid-file=${discovered.pidFile}` : ""}${discovered.workersFile ? ` workers=${discovered.workersFile}` : ""}`
3074
+ );
2991
3075
  return { ...discovered, systemdUnit };
2992
3076
  }
2993
3077
  }
2994
3078
  if (!processName) {
2995
- console.error("Error: --process <name> is required, or provide directories for auto-discovery.");
3079
+ console.error(
3080
+ "Error: --process <name> is required, or provide directories for auto-discovery."
3081
+ );
2996
3082
  console.error("Examples:");
2997
3083
  console.error(" agentflow audit --process alfred --pid-file ./data/alfred.pid");
2998
3084
  console.error(" agentflow audit ./data # auto-discovers *.pid and workers.json");
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  startWatch,
10
10
  toAsciiTree,
11
11
  toTimeline
12
- } from "./chunk-R5SNE2HB.js";
12
+ } from "./chunk-6X5HU5LB.js";
13
13
  import "./chunk-DY7YHFIB.js";
14
14
 
15
15
  // src/cli.ts
@@ -414,12 +414,16 @@ function parseAuditArgs(argv) {
414
414
  if (!processName && !pidFile && !workersFile && discoverDirs.length > 0) {
415
415
  const discovered = discoverProcessConfig(discoverDirs);
416
416
  if (discovered) {
417
- console.log(`Auto-discovered: process="${discovered.processName}"${discovered.pidFile ? ` pid-file=${discovered.pidFile}` : ""}${discovered.workersFile ? ` workers=${discovered.workersFile}` : ""}`);
417
+ console.log(
418
+ `Auto-discovered: process="${discovered.processName}"${discovered.pidFile ? ` pid-file=${discovered.pidFile}` : ""}${discovered.workersFile ? ` workers=${discovered.workersFile}` : ""}`
419
+ );
418
420
  return { ...discovered, systemdUnit };
419
421
  }
420
422
  }
421
423
  if (!processName) {
422
- console.error("Error: --process <name> is required, or provide directories for auto-discovery.");
424
+ console.error(
425
+ "Error: --process <name> is required, or provide directories for auto-discovery."
426
+ );
423
427
  console.error("Examples:");
424
428
  console.error(" agentflow audit --process alfred --pid-file ./data/alfred.pid");
425
429
  console.error(" agentflow audit ./data # auto-discovers *.pid and workers.json");