agentflow-dashboard 0.3.0 → 0.3.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 CHANGED
@@ -1,15 +1,32 @@
1
- # AgentFlow Dashboard
1
+ # AgentFlow Dashboard v0.3.0
2
2
 
3
- Real-time monitoring dashboard for AgentFlow - Visualize agent execution graphs and performance metrics in a beautiful web interface.
3
+ Real-time monitoring dashboard for AgentFlow - Visualize agent execution graphs and performance metrics with comprehensive agent infrastructure monitoring.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Real-time Monitoring** - Live updates via WebSocket connections
8
- - **Agent Performance Metrics** - Success rates, execution times, and activity tracking
9
- - **Execution Graph Visualization** - Interactive display of agent execution flows
10
- - **Multi-Agent System Overview** - Monitor entire agent ecosystems at once
7
+ ### **🎯 Universal Agent Monitoring**
8
+ - **Alfred Integration** - Full Alfred worker and conversation monitoring
9
+ - **OpenClaw Support** - OpenClaw gateway and agent trace ingestion
10
+ - **Multi-Framework** - Supports LangChain, CrewAI, AutoGen, Mastra, and more
11
+ - **Real-time Updates** - Live WebSocket connections with instant trace updates
12
+
13
+ ### **🛠️ Enhanced Process Health**
14
+ - **Process Tagging** - Smart categorization (`main`, `agents`, `browser`, `context`, `exec`, `read`, `tool`, `think`, `user`, `write`)
15
+ - **Tree View Structure** - Hierarchical process relationships with parent-child visualization
16
+ - **Infrastructure Detection** - Automatic detection of Milvus, Redis, PostgreSQL, and vector databases
17
+ - **Resource Monitoring** - CPU, memory, and uptime tracking for all processes
18
+
19
+ ### **💬 LLM Conversation Tracking**
20
+ - **Session Parsing** - Full Alfred and OpenClaw conversation logs
21
+ - **Token Usage** - OpenRouter, Claude, and other provider usage statistics
22
+ - **Model Interactions** - Complete LLM request/response chains with metadata
23
+ - **Activity Filtering** - Filter traces by agent activity type and behavior
24
+
25
+ ### **📊 Performance & Visualization**
26
+ - **Interactive Graphs** - Cytoscape.js execution flow visualization
27
+ - **Timeline View** - Waterfall execution timeline with duration metrics
28
+ - **Success Metrics** - Agent performance, failure rates, and health monitoring
11
29
  - **Responsive Design** - Works on desktop and mobile devices
12
- - **Zero Configuration** - Auto-discovers trace files and starts monitoring
13
30
 
14
31
  ## Quick Start
15
32
 
@@ -1,3 +1,12 @@
1
+ // src/server.ts
2
+ import express from "express";
3
+ import * as fs3 from "fs";
4
+ import { createServer } from "http";
5
+ import * as path3 from "path";
6
+ import { fileURLToPath } from "url";
7
+ import { WebSocketServer } from "ws";
8
+ import { discoverProcessConfig, auditProcesses } from "agentflow-core";
9
+
1
10
  // src/stats.ts
2
11
  import { getFailures, getHungNodes, getStats } from "agentflow-core";
3
12
  var AgentStats = class {
@@ -950,16 +959,154 @@ var TraceWatcher = class extends EventEmitter {
950
959
  }
951
960
  };
952
961
 
953
- // src/server.ts
954
- import express from "express";
962
+ // src/cli.ts
955
963
  import * as fs2 from "fs";
956
- import { createServer } from "http";
964
+ import * as os from "os";
957
965
  import * as path2 from "path";
958
- import { fileURLToPath } from "url";
959
- import { WebSocketServer } from "ws";
960
- import { discoverProcessConfig, auditProcesses } from "agentflow-core";
966
+ var VERSION = "0.3.1";
967
+ function getLanAddress() {
968
+ const interfaces = os.networkInterfaces();
969
+ for (const name of Object.keys(interfaces)) {
970
+ for (const iface of interfaces[name] || []) {
971
+ if (iface.family === "IPv4" && !iface.internal) {
972
+ return iface.address;
973
+ }
974
+ }
975
+ }
976
+ return null;
977
+ }
978
+ function printBanner(config, traceCount, stats) {
979
+ var _a;
980
+ const lan = getLanAddress();
981
+ const host = config.host || "localhost";
982
+ const port = config.port;
983
+ const isPublic = host === "0.0.0.0";
984
+ console.log(`
985
+ ___ _ _____ _
986
+ / _ \\ __ _ ___ _ __ | |_| ___| | _____ __
987
+ | |_| |/ _\` |/ _ \\ '_ \\| __| |_ | |/ _ \\ \\ /\\ / /
988
+ | _ | (_| | __/ | | | |_| _| | | (_) \\ V V /
989
+ |_| |_|\\__, |\\___|_| |_|\\__|_| |_|\\___/ \\_/\\_/
990
+ |___/ dashboard v${VERSION}
991
+
992
+ See your agents think.
993
+
994
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
995
+ \u2502 \u{1F916} Agents \u2502 TRACE FILES \u2502 \u{1F4CA} AgentFlow \u2502 SHOWS YOU \u2502 \u{1F310} Your browser \u2502
996
+ \u2502 Execute tasks, \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500> \u2502 Reads traces, \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500> \u2502 Interactive \u2502
997
+ \u2502 write JSON \u2502 \u2502 builds graphs, \u2502 \u2502 graph, timeline, \u2502
998
+ \u2502 trace files. \u2502 \u2502 serves dashboard.\u2502 \u2502 metrics, health. \u2502
999
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
1000
+
1001
+ Runs locally. Your data never leaves your machine.
1002
+
1003
+ Tabs: \u{1F3AF} Graph \xB7 \u23F1\uFE0F Timeline \xB7 \u{1F4CA} Metrics \xB7 \u{1F6E0}\uFE0F Process Health \xB7 \u26A0\uFE0F Errors
1004
+
1005
+ Traces: ${config.tracesDir}${((_a = config.dataDirs) == null ? void 0 : _a.length) ? "\n Data dirs: " + config.dataDirs.join("\n ") : ""}
1006
+ Loaded: ${traceCount} traces \xB7 ${stats.totalAgents} agents \xB7 ${stats.totalExecutions} executions
1007
+ Success: ${stats.globalSuccessRate.toFixed(1)}%${stats.activeAgents > 0 ? ` \xB7 ${stats.activeAgents} active now` : ""}
1008
+ CORS: ${config.enableCors ? "enabled" : "disabled"}
1009
+ WebSocket: live updates enabled
1010
+
1011
+ \u2192 http://localhost:${port}${isPublic && lan ? `
1012
+ \u2192 http://${lan}:${port} (LAN)` : ""}
1013
+ `);
1014
+ }
1015
+ async function startDashboard() {
1016
+ const args = process.argv.slice(2);
1017
+ const config = {
1018
+ port: 3e3,
1019
+ tracesDir: "./traces",
1020
+ host: "localhost",
1021
+ enableCors: false
1022
+ };
1023
+ for (let i = 0; i < args.length; i++) {
1024
+ switch (args[i]) {
1025
+ case "--port":
1026
+ case "-p":
1027
+ config.port = parseInt(args[++i]) || 3e3;
1028
+ break;
1029
+ case "--traces":
1030
+ case "-t":
1031
+ config.tracesDir = args[++i];
1032
+ break;
1033
+ case "--host":
1034
+ case "-h":
1035
+ config.host = args[++i];
1036
+ break;
1037
+ case "--data-dir":
1038
+ if (!config.dataDirs) config.dataDirs = [];
1039
+ config.dataDirs.push(args[++i]);
1040
+ break;
1041
+ case "--cors":
1042
+ config.enableCors = true;
1043
+ break;
1044
+ case "--help":
1045
+ printHelp();
1046
+ process.exit(0);
1047
+ }
1048
+ }
1049
+ const tracesPath = path2.resolve(config.tracesDir);
1050
+ if (!fs2.existsSync(tracesPath)) {
1051
+ fs2.mkdirSync(tracesPath, { recursive: true });
1052
+ }
1053
+ config.tracesDir = tracesPath;
1054
+ console.log("\nStarting AgentFlow Dashboard...\n");
1055
+ const dashboard = new DashboardServer(config);
1056
+ process.on("SIGINT", async () => {
1057
+ console.log("\n\u{1F6D1} Shutting down dashboard...");
1058
+ await dashboard.stop();
1059
+ process.exit(0);
1060
+ });
1061
+ process.on("SIGTERM", async () => {
1062
+ await dashboard.stop();
1063
+ process.exit(0);
1064
+ });
1065
+ try {
1066
+ await dashboard.start();
1067
+ setTimeout(() => {
1068
+ const stats = dashboard.getStats();
1069
+ const traces = dashboard.getTraces();
1070
+ printBanner(config, traces.length, stats);
1071
+ }, 1500);
1072
+ } catch (error) {
1073
+ console.error("\u274C Failed to start dashboard:", error);
1074
+ process.exit(1);
1075
+ }
1076
+ }
1077
+ function printHelp() {
1078
+ console.log(`
1079
+ \u{1F4CA} AgentFlow Dashboard v${VERSION} \u2014 See your agents think.
1080
+
1081
+ Usage:
1082
+ agentflow-dashboard [options]
1083
+ npx agentflow-dashboard [options]
1084
+
1085
+ Options:
1086
+ -p, --port <number> Server port (default: 3000)
1087
+ -t, --traces <path> Traces directory (default: ./traces)
1088
+ -h, --host <address> Host address (default: localhost)
1089
+ --data-dir <path> Extra data directory for process discovery (repeatable)
1090
+ --cors Enable CORS headers
1091
+ --help Show this help message
1092
+
1093
+ Examples:
1094
+ agentflow-dashboard --traces ./traces --host 0.0.0.0 --cors
1095
+ agentflow-dashboard -p 8080 -t /var/log/agentflow
1096
+ agentflow-dashboard --traces ./traces --data-dir ./workers --data-dir ./cron
1097
+
1098
+ Tabs:
1099
+ \u{1F3AF} Graph Interactive Cytoscape.js execution graph
1100
+ \u23F1\uFE0F Timeline Waterfall view of node durations
1101
+ \u{1F4CA} Metrics Success rates, durations, node breakdown
1102
+ \u{1F6E0}\uFE0F Process Health PID files, systemd, workers, orphans
1103
+ \u26A0\uFE0F Errors Failed and hung nodes with metadata
1104
+ `);
1105
+ }
1106
+
1107
+ // src/server.ts
961
1108
  var __filename = fileURLToPath(import.meta.url);
962
- var __dirname = path2.dirname(__filename);
1109
+ var __dirname = path3.dirname(__filename);
963
1110
  var DashboardServer = class {
964
1111
  constructor(config) {
965
1112
  this.config = config;
@@ -989,8 +1136,8 @@ var DashboardServer = class {
989
1136
  next();
990
1137
  });
991
1138
  }
992
- const publicDir = path2.join(__dirname, "../public");
993
- if (fs2.existsSync(publicDir)) {
1139
+ const publicDir = path3.join(__dirname, "../public");
1140
+ if (fs3.existsSync(publicDir)) {
994
1141
  this.app.use(express.static(publicDir));
995
1142
  }
996
1143
  this.app.get("/api/traces", (req, res) => {
@@ -1062,7 +1209,7 @@ var DashboardServer = class {
1062
1209
  }
1063
1210
  const discoveryDirs = [
1064
1211
  this.config.tracesDir,
1065
- path2.dirname(this.config.tracesDir),
1212
+ path3.dirname(this.config.tracesDir),
1066
1213
  ...this.config.dataDirs || []
1067
1214
  ];
1068
1215
  const processConfig = discoverProcessConfig(discoveryDirs);
@@ -1077,8 +1224,8 @@ var DashboardServer = class {
1077
1224
  }
1078
1225
  });
1079
1226
  this.app.get("*", (req, res) => {
1080
- const indexPath = path2.join(__dirname, "../public/index.html");
1081
- if (fs2.existsSync(indexPath)) {
1227
+ const indexPath = path3.join(__dirname, "../public/index.html");
1228
+ if (fs3.existsSync(indexPath)) {
1082
1229
  res.sendFile(indexPath);
1083
1230
  } else {
1084
1231
  res.status(404).send("Dashboard not found - public files may not be built");
@@ -1135,21 +1282,21 @@ var DashboardServer = class {
1135
1282
  });
1136
1283
  }
1137
1284
  async start() {
1138
- return new Promise((resolve2) => {
1285
+ return new Promise((resolve3) => {
1139
1286
  const host = this.config.host || "localhost";
1140
1287
  this.server.listen(this.config.port, host, () => {
1141
1288
  console.log(`AgentFlow Dashboard running at http://${host}:${this.config.port}`);
1142
1289
  console.log(`Watching traces in: ${this.config.tracesDir}`);
1143
- resolve2();
1290
+ resolve3();
1144
1291
  });
1145
1292
  });
1146
1293
  }
1147
1294
  async stop() {
1148
- return new Promise((resolve2) => {
1295
+ return new Promise((resolve3) => {
1149
1296
  this.watcher.stop();
1150
1297
  this.server.close(() => {
1151
1298
  console.log("Dashboard server stopped");
1152
- resolve2();
1299
+ resolve3();
1153
1300
  });
1154
1301
  });
1155
1302
  }
@@ -1160,9 +1307,13 @@ var DashboardServer = class {
1160
1307
  return this.watcher.getAllTraces();
1161
1308
  }
1162
1309
  };
1310
+ if (import.meta.url === `file://${process.argv[1]}`) {
1311
+ startDashboard().catch(console.error);
1312
+ }
1163
1313
 
1164
1314
  export {
1165
1315
  AgentStats,
1166
1316
  TraceWatcher,
1167
- DashboardServer
1317
+ DashboardServer,
1318
+ startDashboard
1168
1319
  };
package/dist/cli.cjs CHANGED
@@ -1201,9 +1201,12 @@ var DashboardServer = class {
1201
1201
  return this.watcher.getAllTraces();
1202
1202
  }
1203
1203
  };
1204
+ if (import_meta.url === `file://${process.argv[1]}`) {
1205
+ startDashboard().catch(console.error);
1206
+ }
1204
1207
 
1205
1208
  // src/cli.ts
1206
- var VERSION = "0.2.2";
1209
+ var VERSION = "0.3.1";
1207
1210
  function getLanAddress() {
1208
1211
  const interfaces = os.networkInterfaces();
1209
1212
  for (const name of Object.keys(interfaces)) {
package/dist/cli.js CHANGED
@@ -1,151 +1,6 @@
1
1
  import {
2
- DashboardServer
3
- } from "./chunk-2FTN742J.js";
4
-
5
- // src/cli.ts
6
- import * as fs from "fs";
7
- import * as os from "os";
8
- import * as path from "path";
9
- var VERSION = "0.2.2";
10
- function getLanAddress() {
11
- const interfaces = os.networkInterfaces();
12
- for (const name of Object.keys(interfaces)) {
13
- for (const iface of interfaces[name] || []) {
14
- if (iface.family === "IPv4" && !iface.internal) {
15
- return iface.address;
16
- }
17
- }
18
- }
19
- return null;
20
- }
21
- function printBanner(config, traceCount, stats) {
22
- var _a;
23
- const lan = getLanAddress();
24
- const host = config.host || "localhost";
25
- const port = config.port;
26
- const isPublic = host === "0.0.0.0";
27
- console.log(`
28
- ___ _ _____ _
29
- / _ \\ __ _ ___ _ __ | |_| ___| | _____ __
30
- | |_| |/ _\` |/ _ \\ '_ \\| __| |_ | |/ _ \\ \\ /\\ / /
31
- | _ | (_| | __/ | | | |_| _| | | (_) \\ V V /
32
- |_| |_|\\__, |\\___|_| |_|\\__|_| |_|\\___/ \\_/\\_/
33
- |___/ dashboard v${VERSION}
34
-
35
- See your agents think.
36
-
37
- \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510
38
- \u2502 \u{1F916} Agents \u2502 TRACE FILES \u2502 \u{1F4CA} AgentFlow \u2502 SHOWS YOU \u2502 \u{1F310} Your browser \u2502
39
- \u2502 Execute tasks, \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500> \u2502 Reads traces, \u2502 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500> \u2502 Interactive \u2502
40
- \u2502 write JSON \u2502 \u2502 builds graphs, \u2502 \u2502 graph, timeline, \u2502
41
- \u2502 trace files. \u2502 \u2502 serves dashboard.\u2502 \u2502 metrics, health. \u2502
42
- \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
43
-
44
- Runs locally. Your data never leaves your machine.
45
-
46
- Tabs: \u{1F3AF} Graph \xB7 \u23F1\uFE0F Timeline \xB7 \u{1F4CA} Metrics \xB7 \u{1F6E0}\uFE0F Process Health \xB7 \u26A0\uFE0F Errors
47
-
48
- Traces: ${config.tracesDir}${((_a = config.dataDirs) == null ? void 0 : _a.length) ? "\n Data dirs: " + config.dataDirs.join("\n ") : ""}
49
- Loaded: ${traceCount} traces \xB7 ${stats.totalAgents} agents \xB7 ${stats.totalExecutions} executions
50
- Success: ${stats.globalSuccessRate.toFixed(1)}%${stats.activeAgents > 0 ? ` \xB7 ${stats.activeAgents} active now` : ""}
51
- CORS: ${config.enableCors ? "enabled" : "disabled"}
52
- WebSocket: live updates enabled
53
-
54
- \u2192 http://localhost:${port}${isPublic && lan ? `
55
- \u2192 http://${lan}:${port} (LAN)` : ""}
56
- `);
57
- }
58
- async function startDashboard() {
59
- const args = process.argv.slice(2);
60
- const config = {
61
- port: 3e3,
62
- tracesDir: "./traces",
63
- host: "localhost",
64
- enableCors: false
65
- };
66
- for (let i = 0; i < args.length; i++) {
67
- switch (args[i]) {
68
- case "--port":
69
- case "-p":
70
- config.port = parseInt(args[++i]) || 3e3;
71
- break;
72
- case "--traces":
73
- case "-t":
74
- config.tracesDir = args[++i];
75
- break;
76
- case "--host":
77
- case "-h":
78
- config.host = args[++i];
79
- break;
80
- case "--data-dir":
81
- if (!config.dataDirs) config.dataDirs = [];
82
- config.dataDirs.push(args[++i]);
83
- break;
84
- case "--cors":
85
- config.enableCors = true;
86
- break;
87
- case "--help":
88
- printHelp();
89
- process.exit(0);
90
- }
91
- }
92
- const tracesPath = path.resolve(config.tracesDir);
93
- if (!fs.existsSync(tracesPath)) {
94
- fs.mkdirSync(tracesPath, { recursive: true });
95
- }
96
- config.tracesDir = tracesPath;
97
- console.log("\nStarting AgentFlow Dashboard...\n");
98
- const dashboard = new DashboardServer(config);
99
- process.on("SIGINT", async () => {
100
- console.log("\n\u{1F6D1} Shutting down dashboard...");
101
- await dashboard.stop();
102
- process.exit(0);
103
- });
104
- process.on("SIGTERM", async () => {
105
- await dashboard.stop();
106
- process.exit(0);
107
- });
108
- try {
109
- await dashboard.start();
110
- setTimeout(() => {
111
- const stats = dashboard.getStats();
112
- const traces = dashboard.getTraces();
113
- printBanner(config, traces.length, stats);
114
- }, 1500);
115
- } catch (error) {
116
- console.error("\u274C Failed to start dashboard:", error);
117
- process.exit(1);
118
- }
119
- }
120
- function printHelp() {
121
- console.log(`
122
- \u{1F4CA} AgentFlow Dashboard v${VERSION} \u2014 See your agents think.
123
-
124
- Usage:
125
- agentflow-dashboard [options]
126
- npx agentflow-dashboard [options]
127
-
128
- Options:
129
- -p, --port <number> Server port (default: 3000)
130
- -t, --traces <path> Traces directory (default: ./traces)
131
- -h, --host <address> Host address (default: localhost)
132
- --data-dir <path> Extra data directory for process discovery (repeatable)
133
- --cors Enable CORS headers
134
- --help Show this help message
135
-
136
- Examples:
137
- agentflow-dashboard --traces ./traces --host 0.0.0.0 --cors
138
- agentflow-dashboard -p 8080 -t /var/log/agentflow
139
- agentflow-dashboard --traces ./traces --data-dir ./workers --data-dir ./cron
140
-
141
- Tabs:
142
- \u{1F3AF} Graph Interactive Cytoscape.js execution graph
143
- \u23F1\uFE0F Timeline Waterfall view of node durations
144
- \u{1F4CA} Metrics Success rates, durations, node breakdown
145
- \u{1F6E0}\uFE0F Process Health PID files, systemd, workers, orphans
146
- \u26A0\uFE0F Errors Failed and hung nodes with metadata
147
- `);
148
- }
2
+ startDashboard
3
+ } from "./chunk-EDHK4NJD.js";
149
4
  export {
150
5
  startDashboard
151
6
  };