agentflow-core 0.2.1 → 0.2.3
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/{chunk-FJVQYJFB.js → chunk-5SPZPOFN.js} +188 -101
- package/dist/cli.cjs +192 -104
- package/dist/cli.js +5 -4
- package/dist/index.cjs +188 -101
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -587,7 +587,7 @@ var C = {
|
|
|
587
587
|
white: "\x1B[37m"
|
|
588
588
|
};
|
|
589
589
|
function parseArgs(argv) {
|
|
590
|
-
const config = {
|
|
590
|
+
const config = { dirs: [], refreshMs: 3e3, recursive: false };
|
|
591
591
|
const args = argv.slice(0);
|
|
592
592
|
if (args[0] === "live") args.shift();
|
|
593
593
|
let i = 0;
|
|
@@ -604,18 +604,14 @@ function parseArgs(argv) {
|
|
|
604
604
|
} else if (arg === "--recursive" || arg === "-R") {
|
|
605
605
|
config.recursive = true;
|
|
606
606
|
i++;
|
|
607
|
-
} else if (arg === "--traces-dir" || arg === "-t") {
|
|
608
|
-
i++;
|
|
609
|
-
config.tracesDir = args[i] ?? config.tracesDir;
|
|
610
|
-
i++;
|
|
611
607
|
} else if (!arg.startsWith("-")) {
|
|
612
|
-
config.
|
|
608
|
+
config.dirs.push((0, import_node_path2.resolve)(arg));
|
|
613
609
|
i++;
|
|
614
610
|
} else {
|
|
615
611
|
i++;
|
|
616
612
|
}
|
|
617
613
|
}
|
|
618
|
-
config.
|
|
614
|
+
if (config.dirs.length === 0) config.dirs.push((0, import_node_path2.resolve)("."));
|
|
619
615
|
return config;
|
|
620
616
|
}
|
|
621
617
|
function printUsage() {
|
|
@@ -623,13 +619,13 @@ function printUsage() {
|
|
|
623
619
|
AgentFlow Live Monitor \u2014 real-time terminal dashboard for agent systems.
|
|
624
620
|
|
|
625
621
|
Auto-detects agent traces, state files, job schedulers, and session logs
|
|
626
|
-
from any JSON/JSONL files in the watched
|
|
622
|
+
from any JSON/JSONL files in the watched directories.
|
|
627
623
|
|
|
628
624
|
Usage:
|
|
629
|
-
agentflow live [
|
|
625
|
+
agentflow live [dir...] [options]
|
|
630
626
|
|
|
631
627
|
Arguments:
|
|
632
|
-
|
|
628
|
+
dir One or more directories to watch (default: .)
|
|
633
629
|
|
|
634
630
|
Options:
|
|
635
631
|
-r, --refresh <secs> Refresh interval in seconds (default: 3)
|
|
@@ -638,38 +634,42 @@ Options:
|
|
|
638
634
|
|
|
639
635
|
Examples:
|
|
640
636
|
agentflow live ./data
|
|
641
|
-
agentflow live ./traces --refresh 5
|
|
637
|
+
agentflow live ./traces ./cron ./workers --refresh 5
|
|
642
638
|
agentflow live /var/lib/myagent -R
|
|
643
639
|
`.trim());
|
|
644
640
|
}
|
|
645
|
-
function scanFiles(
|
|
641
|
+
function scanFiles(dirs, recursive) {
|
|
646
642
|
const results = [];
|
|
647
|
-
|
|
643
|
+
const seen = /* @__PURE__ */ new Set();
|
|
644
|
+
function scanDir(d, topLevel) {
|
|
648
645
|
try {
|
|
649
646
|
for (const f of (0, import_node_fs2.readdirSync)(d)) {
|
|
650
647
|
if (f.startsWith(".")) continue;
|
|
651
648
|
const fp = (0, import_node_path2.join)(d, f);
|
|
649
|
+
if (seen.has(fp)) continue;
|
|
652
650
|
let stat;
|
|
653
651
|
try {
|
|
654
652
|
stat = (0, import_node_fs2.statSync)(fp);
|
|
655
653
|
} catch {
|
|
656
654
|
continue;
|
|
657
655
|
}
|
|
658
|
-
if (stat.isDirectory() && recursive &&
|
|
659
|
-
scanDir(fp);
|
|
656
|
+
if (stat.isDirectory() && recursive && topLevel) {
|
|
657
|
+
scanDir(fp, false);
|
|
660
658
|
continue;
|
|
661
659
|
}
|
|
662
660
|
if (!stat.isFile()) continue;
|
|
663
661
|
if (f.endsWith(".json")) {
|
|
662
|
+
seen.add(fp);
|
|
664
663
|
results.push({ filename: f, path: fp, mtime: stat.mtime.getTime(), ext: ".json" });
|
|
665
664
|
} else if (f.endsWith(".jsonl")) {
|
|
665
|
+
seen.add(fp);
|
|
666
666
|
results.push({ filename: f, path: fp, mtime: stat.mtime.getTime(), ext: ".jsonl" });
|
|
667
667
|
}
|
|
668
668
|
}
|
|
669
669
|
} catch {
|
|
670
670
|
}
|
|
671
671
|
}
|
|
672
|
-
scanDir(dir);
|
|
672
|
+
for (const dir of dirs) scanDir(dir, true);
|
|
673
673
|
results.sort((a, b) => b.mtime - a.mtime);
|
|
674
674
|
return results;
|
|
675
675
|
}
|
|
@@ -819,11 +819,21 @@ function processJsonlFile(file) {
|
|
|
819
819
|
return [];
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
|
+
var K = "\x1B[K";
|
|
823
|
+
function writeLine(lines, text) {
|
|
824
|
+
lines.push(text + K);
|
|
825
|
+
}
|
|
826
|
+
function flushLines(lines) {
|
|
827
|
+
process.stdout.write("\x1B[H");
|
|
828
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
829
|
+
process.stdout.write("\x1B[J");
|
|
830
|
+
}
|
|
822
831
|
var prevFileCount = 0;
|
|
823
832
|
var newExecCount = 0;
|
|
824
833
|
var sessionStart = Date.now();
|
|
834
|
+
var firstRender = true;
|
|
825
835
|
function render(config) {
|
|
826
|
-
const files = scanFiles(config.
|
|
836
|
+
const files = scanFiles(config.dirs, config.recursive);
|
|
827
837
|
if (files.length > prevFileCount && prevFileCount > 0) {
|
|
828
838
|
newExecCount += files.length - prevFileCount;
|
|
829
839
|
}
|
|
@@ -837,26 +847,58 @@ function render(config) {
|
|
|
837
847
|
if (r.traceData) allTraces.push(r.traceData);
|
|
838
848
|
}
|
|
839
849
|
}
|
|
840
|
-
const
|
|
850
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
841
851
|
for (const r of allRecords) {
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
852
|
+
const arr = byFile.get(r.file) ?? [];
|
|
853
|
+
arr.push(r);
|
|
854
|
+
byFile.set(r.file, arr);
|
|
855
|
+
}
|
|
856
|
+
const groups = [];
|
|
857
|
+
for (const [file, records] of byFile) {
|
|
858
|
+
if (records.length === 1) {
|
|
859
|
+
const r = records[0];
|
|
860
|
+
groups.push({
|
|
861
|
+
name: r.id,
|
|
862
|
+
source: r.source,
|
|
863
|
+
status: r.status,
|
|
864
|
+
lastTs: r.lastActive,
|
|
865
|
+
detail: r.detail,
|
|
866
|
+
children: [],
|
|
867
|
+
ok: r.status === "ok" ? 1 : 0,
|
|
868
|
+
fail: r.status === "error" ? 1 : 0,
|
|
869
|
+
running: r.status === "running" ? 1 : 0,
|
|
870
|
+
total: 1
|
|
871
|
+
});
|
|
872
|
+
} else {
|
|
873
|
+
const groupName = nameFromFile(file);
|
|
874
|
+
let lastTs = 0;
|
|
875
|
+
let ok = 0, fail = 0, running = 0;
|
|
876
|
+
for (const r of records) {
|
|
877
|
+
if (r.lastActive > lastTs) lastTs = r.lastActive;
|
|
878
|
+
if (r.status === "ok") ok++;
|
|
879
|
+
else if (r.status === "error") fail++;
|
|
880
|
+
else if (r.status === "running") running++;
|
|
881
|
+
}
|
|
882
|
+
const status = fail > 0 ? "error" : running > 0 ? "running" : ok > 0 ? "ok" : "unknown";
|
|
883
|
+
groups.push({
|
|
884
|
+
name: groupName,
|
|
885
|
+
source: records[0].source,
|
|
886
|
+
status,
|
|
887
|
+
lastTs,
|
|
888
|
+
detail: `${records.length} agents`,
|
|
889
|
+
children: records.sort((a, b) => b.lastActive - a.lastActive),
|
|
890
|
+
ok,
|
|
891
|
+
fail,
|
|
892
|
+
running,
|
|
893
|
+
total: records.length
|
|
894
|
+
});
|
|
854
895
|
}
|
|
855
896
|
}
|
|
856
|
-
|
|
857
|
-
const totExec =
|
|
858
|
-
const totFail =
|
|
859
|
-
const totRunning =
|
|
897
|
+
groups.sort((a, b) => b.lastTs - a.lastTs);
|
|
898
|
+
const totExec = allRecords.length;
|
|
899
|
+
const totFail = allRecords.filter((r) => r.status === "error").length;
|
|
900
|
+
const totRunning = allRecords.filter((r) => r.status === "running").length;
|
|
901
|
+
const uniqueAgents = new Set(allRecords.map((r) => r.id)).size;
|
|
860
902
|
const sysRate = totExec > 0 ? ((totExec - totFail) / totExec * 100).toFixed(1) : "100.0";
|
|
861
903
|
const now = Date.now();
|
|
862
904
|
const buckets = new Array(12).fill(0);
|
|
@@ -893,7 +935,21 @@ function render(config) {
|
|
|
893
935
|
const upMin = Math.floor(upSec / 60);
|
|
894
936
|
const upStr = upMin > 0 ? `${upMin}m ${upSec % 60}s` : `${upSec}s`;
|
|
895
937
|
const time = (/* @__PURE__ */ new Date()).toLocaleTimeString();
|
|
896
|
-
|
|
938
|
+
function statusIcon(s, recent) {
|
|
939
|
+
if (s === "error") return `${C.red}\u25CF${C.reset}`;
|
|
940
|
+
if (s === "running") return `${C.green}\u25CF${C.reset}`;
|
|
941
|
+
if (s === "ok" && recent) return `${C.green}\u25CF${C.reset}`;
|
|
942
|
+
if (s === "ok") return `${C.dim}\u25CB${C.reset}`;
|
|
943
|
+
return `${C.dim}\u25CB${C.reset}`;
|
|
944
|
+
}
|
|
945
|
+
function statusText(g) {
|
|
946
|
+
if (g.fail > 0 && g.ok === 0 && g.running === 0) return `${C.red}error${C.reset}`;
|
|
947
|
+
if (g.running > 0) return `${C.green}running${C.reset}`;
|
|
948
|
+
if (g.fail > 0) return `${C.yellow}${g.ok}ok/${g.fail}err${C.reset}`;
|
|
949
|
+
if (g.ok > 0) return g.total > 1 ? `${C.green}${g.ok}/${g.total} ok${C.reset}` : `${C.green}ok${C.reset}`;
|
|
950
|
+
return `${C.dim}idle${C.reset}`;
|
|
951
|
+
}
|
|
952
|
+
function sourceTag(s) {
|
|
897
953
|
switch (s) {
|
|
898
954
|
case "trace":
|
|
899
955
|
return `${C.cyan}trace${C.reset}`;
|
|
@@ -906,92 +962,115 @@ function render(config) {
|
|
|
906
962
|
case "state":
|
|
907
963
|
return `${C.dim}state${C.reset}`;
|
|
908
964
|
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
965
|
+
}
|
|
966
|
+
function timeStr(ts) {
|
|
967
|
+
if (ts <= 0) return "n/a";
|
|
968
|
+
return new Date(ts).toLocaleTimeString();
|
|
969
|
+
}
|
|
970
|
+
function truncate(s, max) {
|
|
971
|
+
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
972
|
+
}
|
|
973
|
+
if (firstRender) {
|
|
974
|
+
process.stdout.write("\x1B[2J");
|
|
975
|
+
firstRender = false;
|
|
976
|
+
}
|
|
977
|
+
const L = [];
|
|
978
|
+
writeLine(L, `${C.bold}${C.cyan}\u2554${"\u2550".repeat(70)}\u2557${C.reset}`);
|
|
979
|
+
writeLine(L, `${C.bold}${C.cyan}\u2551${C.reset} ${C.bold}${C.white}AGENTFLOW LIVE${C.reset} ${C.green}\u25CF LIVE${C.reset} ${C.dim}${time}${C.reset} ${C.bold}${C.cyan}\u2551${C.reset}`);
|
|
913
980
|
const metaLine = `Refresh: ${config.refreshMs / 1e3}s \xB7 Up: ${upStr} \xB7 Files: ${files.length}`;
|
|
914
981
|
const pad1 = Math.max(0, 64 - metaLine.length);
|
|
915
|
-
|
|
916
|
-
|
|
982
|
+
writeLine(L, `${C.bold}${C.cyan}\u2551${C.reset} ${C.dim}${metaLine}${C.reset}${" ".repeat(pad1)}${C.bold}${C.cyan}\u2551${C.reset}`);
|
|
983
|
+
writeLine(L, `${C.bold}${C.cyan}\u255A${"\u2550".repeat(70)}\u255D${C.reset}`);
|
|
917
984
|
const sc = totFail === 0 ? C.green : C.yellow;
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
statusIcon = `${C.yellow}\u25CF${C.reset}`;
|
|
937
|
-
statusText = `${C.yellow}${ag.ok}ok/${ag.fail}err${C.reset}`;
|
|
938
|
-
} else if (ag.ok > 0) {
|
|
939
|
-
statusIcon = isRecent ? `${C.green}\u25CF${C.reset}` : `${C.dim}\u25CB${C.reset}`;
|
|
940
|
-
statusText = ag.total > 1 ? `${C.green}${ag.ok}/${ag.total}${C.reset}` : `${C.green}ok${C.reset}`;
|
|
985
|
+
writeLine(L, "");
|
|
986
|
+
writeLine(L, ` ${C.bold}Agents${C.reset} ${sc}${uniqueAgents}${C.reset} ${C.bold}Records${C.reset} ${sc}${totExec}${C.reset} ${C.bold}Success${C.reset} ${sc}${sysRate}%${C.reset} ${C.bold}Running${C.reset} ${C.green}${totRunning}${C.reset} ${C.bold}Errors${C.reset} ${totFail > 0 ? C.red : C.dim}${totFail}${C.reset} ${C.bold}New${C.reset} ${C.yellow}+${newExecCount}${C.reset}`);
|
|
987
|
+
writeLine(L, "");
|
|
988
|
+
writeLine(L, ` ${C.bold}Activity (1h)${C.reset} ${spark} ${C.dim}\u2190 now${C.reset}`);
|
|
989
|
+
writeLine(L, "");
|
|
990
|
+
writeLine(L, ` ${C.bold}${C.under}Agent Status Last Active Detail${C.reset}`);
|
|
991
|
+
let lineCount = 0;
|
|
992
|
+
for (const g of groups) {
|
|
993
|
+
if (lineCount > 35) break;
|
|
994
|
+
const isRecent = Date.now() - g.lastTs < 3e5;
|
|
995
|
+
const icon = statusIcon(g.status, isRecent);
|
|
996
|
+
const active = isRecent ? `${C.green}${timeStr(g.lastTs)}${C.reset}` : `${C.dim}${timeStr(g.lastTs)}${C.reset}`;
|
|
997
|
+
if (g.children.length === 0) {
|
|
998
|
+
const name = truncate(g.name, 26).padEnd(26);
|
|
999
|
+
const st = statusText(g);
|
|
1000
|
+
const det = truncate(g.detail, 30);
|
|
1001
|
+
writeLine(L, ` ${icon} ${name} ${st.padEnd(20)} ${active.padEnd(20)} ${C.dim}${det}${C.reset}`);
|
|
1002
|
+
lineCount++;
|
|
941
1003
|
} else {
|
|
942
|
-
|
|
943
|
-
|
|
1004
|
+
const name = truncate(g.name, 24).padEnd(24);
|
|
1005
|
+
const st = statusText(g);
|
|
1006
|
+
const tag = sourceTag(g.source);
|
|
1007
|
+
writeLine(L, ` ${icon} ${C.bold}${name}${C.reset} ${st.padEnd(20)} ${active.padEnd(20)} ${tag} ${C.dim}(${g.children.length} agents)${C.reset}`);
|
|
1008
|
+
lineCount++;
|
|
1009
|
+
const kids = g.children.slice(0, 12);
|
|
1010
|
+
for (let i = 0; i < kids.length; i++) {
|
|
1011
|
+
if (lineCount > 35) break;
|
|
1012
|
+
const child = kids[i];
|
|
1013
|
+
const isLast = i === kids.length - 1;
|
|
1014
|
+
const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
1015
|
+
const cIcon = statusIcon(child.status, Date.now() - child.lastActive < 3e5);
|
|
1016
|
+
const cName = truncate(child.id, 22).padEnd(22);
|
|
1017
|
+
const cActive = `${C.dim}${timeStr(child.lastActive)}${C.reset}`;
|
|
1018
|
+
const cDet = truncate(child.detail, 25);
|
|
1019
|
+
writeLine(L, ` ${C.dim}${connector}${C.reset} ${cIcon} ${cName} ${cActive.padEnd(20)} ${C.dim}${cDet}${C.reset}`);
|
|
1020
|
+
lineCount++;
|
|
1021
|
+
}
|
|
1022
|
+
if (g.children.length > 12) {
|
|
1023
|
+
writeLine(L, ` ${C.dim} ... +${g.children.length - 12} more${C.reset}`);
|
|
1024
|
+
lineCount++;
|
|
1025
|
+
}
|
|
944
1026
|
}
|
|
945
|
-
const name = ag.name.length > 23 ? ag.name.slice(0, 22) + "\u2026" : ag.name.padEnd(23);
|
|
946
|
-
const src = sourceTag(ag.source).padEnd(16);
|
|
947
|
-
const active = isRecent ? `${C.green}${lastTime}${C.reset}` : `${C.dim}${lastTime}${C.reset}`;
|
|
948
|
-
const detail = ag.detail.length > 30 ? ag.detail.slice(0, 29) + "\u2026" : ag.detail;
|
|
949
|
-
console.log(` ${statusIcon} ${name} ${src} ${statusText.padEnd(18)} ${active.padEnd(20)} ${C.dim}${detail}${C.reset}`);
|
|
950
1027
|
}
|
|
951
1028
|
if (distributedTraces.length > 0) {
|
|
952
|
-
|
|
953
|
-
|
|
1029
|
+
writeLine(L, "");
|
|
1030
|
+
writeLine(L, ` ${C.bold}${C.under}Distributed Traces${C.reset}`);
|
|
954
1031
|
for (const dt of distributedTraces.slice(0, 3)) {
|
|
955
1032
|
const traceTime = new Date(dt.startTime).toLocaleTimeString();
|
|
956
|
-
const
|
|
1033
|
+
const si = dt.status === "completed" ? `${C.green}\u2713${C.reset}` : dt.status === "failed" ? `${C.red}\u2717${C.reset}` : `${C.yellow}\u23F3${C.reset}`;
|
|
957
1034
|
const dur = dt.endTime ? `${dt.endTime - dt.startTime}ms` : "running";
|
|
958
1035
|
const tid = dt.traceId.slice(0, 8);
|
|
959
|
-
|
|
1036
|
+
writeLine(L, ` ${si} ${C.magenta}trace:${tid}${C.reset} ${C.dim}${traceTime} ${dur} (${dt.graphs.size} agents)${C.reset}`);
|
|
960
1037
|
const tree = getTraceTree(dt);
|
|
961
1038
|
for (let i = 0; i < Math.min(tree.length, 6); i++) {
|
|
962
|
-
const
|
|
963
|
-
const depth = getDistDepth(dt,
|
|
1039
|
+
const tg = tree[i];
|
|
1040
|
+
const depth = getDistDepth(dt, tg.spanId);
|
|
964
1041
|
const indent = " " + "\u2502 ".repeat(Math.max(0, depth - 1));
|
|
965
1042
|
const isLast = i === tree.length - 1 || getDistDepth(dt, tree[i + 1]?.spanId) <= depth;
|
|
966
1043
|
const conn = depth === 0 ? " " : isLast ? "\u2514\u2500 " : "\u251C\u2500 ";
|
|
967
|
-
const gs =
|
|
968
|
-
const gd =
|
|
969
|
-
|
|
1044
|
+
const gs = tg.status === "completed" ? `${C.green}\u2713${C.reset}` : tg.status === "failed" ? `${C.red}\u2717${C.reset}` : `${C.yellow}\u23F3${C.reset}`;
|
|
1045
|
+
const gd = tg.endTime ? `${tg.endTime - tg.startTime}ms` : "running";
|
|
1046
|
+
writeLine(L, `${indent}${conn}${gs} ${C.bold}${tg.agentId}${C.reset} ${C.dim}[${tg.trigger}] ${gd}${C.reset}`);
|
|
970
1047
|
}
|
|
971
1048
|
}
|
|
972
1049
|
}
|
|
973
|
-
const recentRecords = allRecords.filter((r) => r.lastActive > 0).sort((a, b) => b.lastActive - a.lastActive).slice(0,
|
|
1050
|
+
const recentRecords = allRecords.filter((r) => r.lastActive > 0).sort((a, b) => b.lastActive - a.lastActive).slice(0, 6);
|
|
974
1051
|
if (recentRecords.length > 0) {
|
|
975
|
-
|
|
976
|
-
|
|
1052
|
+
writeLine(L, "");
|
|
1053
|
+
writeLine(L, ` ${C.bold}${C.under}Recent Activity${C.reset}`);
|
|
977
1054
|
for (const r of recentRecords) {
|
|
978
1055
|
const icon = r.status === "ok" ? `${C.green}\u2713${C.reset}` : r.status === "error" ? `${C.red}\u2717${C.reset}` : r.status === "running" ? `${C.green}\u25B6${C.reset}` : `${C.dim}\u25CB${C.reset}`;
|
|
979
1056
|
const t = new Date(r.lastActive).toLocaleTimeString();
|
|
980
|
-
const agent = r.id
|
|
1057
|
+
const agent = truncate(r.id, 26).padEnd(26);
|
|
981
1058
|
const age = Math.floor((Date.now() - r.lastActive) / 1e3);
|
|
982
1059
|
const ageStr = age < 60 ? age + "s ago" : age < 3600 ? Math.floor(age / 60) + "m ago" : Math.floor(age / 3600) + "h ago";
|
|
983
|
-
const
|
|
984
|
-
|
|
1060
|
+
const det = truncate(r.detail, 25);
|
|
1061
|
+
writeLine(L, ` ${icon} ${agent} ${C.dim}${t} ${ageStr.padStart(8)}${C.reset} ${C.dim}${det}${C.reset}`);
|
|
985
1062
|
}
|
|
986
1063
|
}
|
|
987
1064
|
if (files.length === 0) {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1065
|
+
writeLine(L, "");
|
|
1066
|
+
writeLine(L, ` ${C.dim}No JSON/JSONL files found. Waiting for data in:${C.reset}`);
|
|
1067
|
+
for (const d of config.dirs) writeLine(L, ` ${C.dim} ${d}${C.reset}`);
|
|
991
1068
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1069
|
+
writeLine(L, "");
|
|
1070
|
+
const dirLabel = config.dirs.length === 1 ? config.dirs[0] : `${config.dirs.length} directories`;
|
|
1071
|
+
writeLine(L, ` ${C.dim}Watching: ${dirLabel}${C.reset}`);
|
|
1072
|
+
writeLine(L, ` ${C.dim}Press Ctrl+C to exit${C.reset}`);
|
|
1073
|
+
flushLines(L);
|
|
995
1074
|
}
|
|
996
1075
|
function getDistDepth(dt, spanId) {
|
|
997
1076
|
if (!spanId) return 0;
|
|
@@ -1001,19 +1080,27 @@ function getDistDepth(dt, spanId) {
|
|
|
1001
1080
|
}
|
|
1002
1081
|
function startLive(argv) {
|
|
1003
1082
|
const config = parseArgs(argv);
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
console.error(
|
|
1083
|
+
const valid = config.dirs.filter((d) => (0, import_node_fs2.existsSync)(d));
|
|
1084
|
+
if (valid.length === 0) {
|
|
1085
|
+
console.error(`No valid directories found: ${config.dirs.join(", ")}`);
|
|
1086
|
+
console.error("Specify directories containing JSON/JSONL files: agentflow live <dir> [dir...]");
|
|
1007
1087
|
process.exit(1);
|
|
1008
1088
|
}
|
|
1089
|
+
const invalid = config.dirs.filter((d) => !(0, import_node_fs2.existsSync)(d));
|
|
1090
|
+
if (invalid.length > 0) {
|
|
1091
|
+
console.warn(`Skipping non-existent: ${invalid.join(", ")}`);
|
|
1092
|
+
}
|
|
1093
|
+
config.dirs = valid;
|
|
1009
1094
|
render(config);
|
|
1010
1095
|
let debounce = null;
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1096
|
+
for (const dir of config.dirs) {
|
|
1097
|
+
try {
|
|
1098
|
+
(0, import_node_fs2.watch)(dir, { recursive: config.recursive }, () => {
|
|
1099
|
+
if (debounce) clearTimeout(debounce);
|
|
1100
|
+
debounce = setTimeout(() => render(config), 500);
|
|
1101
|
+
});
|
|
1102
|
+
} catch {
|
|
1103
|
+
}
|
|
1017
1104
|
}
|
|
1018
1105
|
setInterval(() => render(config), config.refreshMs);
|
|
1019
1106
|
process.on("SIGINT", () => {
|
|
@@ -1031,15 +1118,16 @@ Usage:
|
|
|
1031
1118
|
agentflow <command> [options]
|
|
1032
1119
|
|
|
1033
1120
|
Commands:
|
|
1034
|
-
run [options] -- <cmd>
|
|
1035
|
-
live [dir] [options] Real-time terminal monitor (auto-detects any JSON/JSONL)
|
|
1121
|
+
run [options] -- <cmd> Wrap a command with automatic execution tracing
|
|
1122
|
+
live [dir...] [options] Real-time terminal monitor (auto-detects any JSON/JSONL)
|
|
1036
1123
|
|
|
1037
1124
|
Run \`agentflow <command> --help\` for command-specific options.
|
|
1038
1125
|
|
|
1039
1126
|
Examples:
|
|
1040
1127
|
agentflow run --traces-dir ./traces -- python -m myagent process
|
|
1041
1128
|
agentflow live ./data
|
|
1042
|
-
agentflow live ./
|
|
1129
|
+
agentflow live ./traces ./cron ./workers -R
|
|
1130
|
+
agentflow live ./data --refresh 5
|
|
1043
1131
|
`.trim());
|
|
1044
1132
|
}
|
|
1045
1133
|
function parseRunArgs(argv) {
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runTraced,
|
|
4
4
|
startLive
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5SPZPOFN.js";
|
|
6
6
|
|
|
7
7
|
// src/cli.ts
|
|
8
8
|
import { basename } from "path";
|
|
@@ -14,15 +14,16 @@ Usage:
|
|
|
14
14
|
agentflow <command> [options]
|
|
15
15
|
|
|
16
16
|
Commands:
|
|
17
|
-
run [options] -- <cmd>
|
|
18
|
-
live [dir] [options] Real-time terminal monitor (auto-detects any JSON/JSONL)
|
|
17
|
+
run [options] -- <cmd> Wrap a command with automatic execution tracing
|
|
18
|
+
live [dir...] [options] Real-time terminal monitor (auto-detects any JSON/JSONL)
|
|
19
19
|
|
|
20
20
|
Run \`agentflow <command> --help\` for command-specific options.
|
|
21
21
|
|
|
22
22
|
Examples:
|
|
23
23
|
agentflow run --traces-dir ./traces -- python -m myagent process
|
|
24
24
|
agentflow live ./data
|
|
25
|
-
agentflow live ./
|
|
25
|
+
agentflow live ./traces ./cron ./workers -R
|
|
26
|
+
agentflow live ./data --refresh 5
|
|
26
27
|
`.trim());
|
|
27
28
|
}
|
|
28
29
|
function parseRunArgs(argv) {
|