agentflow-dashboard 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +17 -91
- package/dist/index.js +14 -88
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ var import_chokidar = __toESM(require("chokidar"), 1);
|
|
|
49
49
|
var fs = __toESM(require("fs"), 1);
|
|
50
50
|
var path = __toESM(require("path"), 1);
|
|
51
51
|
var import_events = require("events");
|
|
52
|
+
var import_agentflow_core = require("agentflow-core");
|
|
52
53
|
var TraceWatcher = class extends import_events.EventEmitter {
|
|
53
54
|
watcher;
|
|
54
55
|
traces = /* @__PURE__ */ new Map();
|
|
@@ -81,16 +82,12 @@ var TraceWatcher = class extends import_events.EventEmitter {
|
|
|
81
82
|
loadTraceFile(filePath) {
|
|
82
83
|
try {
|
|
83
84
|
const content = fs.readFileSync(filePath, "utf8");
|
|
84
|
-
const
|
|
85
|
+
const graph = (0, import_agentflow_core.loadGraph)(content);
|
|
85
86
|
const filename = path.basename(filePath);
|
|
86
87
|
const stats = fs.statSync(filePath);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const nodesMap = new Map(trace.nodes);
|
|
91
|
-
trace.nodes = nodesMap;
|
|
92
|
-
}
|
|
93
|
-
this.traces.set(filename, trace);
|
|
88
|
+
graph.filename = filename;
|
|
89
|
+
graph.lastModified = stats.mtime.getTime();
|
|
90
|
+
this.traces.set(filename, graph);
|
|
94
91
|
return true;
|
|
95
92
|
} catch (error) {
|
|
96
93
|
console.error(`Error loading trace file ${filePath}:`, error);
|
|
@@ -99,7 +96,7 @@ var TraceWatcher = class extends import_events.EventEmitter {
|
|
|
99
96
|
}
|
|
100
97
|
startWatching() {
|
|
101
98
|
this.watcher = import_chokidar.default.watch(this.tracesDir, {
|
|
102
|
-
ignored:
|
|
99
|
+
ignored: /^\./,
|
|
103
100
|
persistent: true,
|
|
104
101
|
ignoreInitial: true
|
|
105
102
|
});
|
|
@@ -142,7 +139,7 @@ var TraceWatcher = class extends import_events.EventEmitter {
|
|
|
142
139
|
}
|
|
143
140
|
getAllTraces() {
|
|
144
141
|
return Array.from(this.traces.values()).sort((a, b) => {
|
|
145
|
-
return (b.lastModified || b.
|
|
142
|
+
return (b.lastModified || b.startTime) - (a.lastModified || a.startTime);
|
|
146
143
|
});
|
|
147
144
|
}
|
|
148
145
|
getTrace(filename) {
|
|
@@ -171,7 +168,6 @@ var TraceWatcher = class extends import_events.EventEmitter {
|
|
|
171
168
|
console.log("Stopped watching traces directory");
|
|
172
169
|
}
|
|
173
170
|
}
|
|
174
|
-
// Utility method to get trace statistics
|
|
175
171
|
getTraceStats() {
|
|
176
172
|
const total = this.traces.size;
|
|
177
173
|
const agentCount = this.getAgentIds().length;
|
|
@@ -190,81 +186,13 @@ var TraceWatcher = class extends import_events.EventEmitter {
|
|
|
190
186
|
}
|
|
191
187
|
};
|
|
192
188
|
|
|
193
|
-
// ../core/dist/index.js
|
|
194
|
-
function getFailures(graph) {
|
|
195
|
-
const failureStatuses = /* @__PURE__ */ new Set(["failed", "hung", "timeout"]);
|
|
196
|
-
return [...graph.nodes.values()].filter((node) => failureStatuses.has(node.status));
|
|
197
|
-
}
|
|
198
|
-
function getHungNodes(graph) {
|
|
199
|
-
return [...graph.nodes.values()].filter(
|
|
200
|
-
(node) => node.status === "running" && node.endTime === null
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
function getDuration(graph) {
|
|
204
|
-
const end = graph.endTime ?? Date.now();
|
|
205
|
-
return end - graph.startTime;
|
|
206
|
-
}
|
|
207
|
-
function getDepth(graph) {
|
|
208
|
-
const root = graph.nodes.get(graph.rootNodeId);
|
|
209
|
-
if (!root) return -1;
|
|
210
|
-
function dfs(node, depth) {
|
|
211
|
-
if (node.children.length === 0) return depth;
|
|
212
|
-
let maxDepth = depth;
|
|
213
|
-
for (const childId of node.children) {
|
|
214
|
-
const child = graph.nodes.get(childId);
|
|
215
|
-
if (!child) continue;
|
|
216
|
-
const childDepth = dfs(child, depth + 1);
|
|
217
|
-
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
218
|
-
}
|
|
219
|
-
return maxDepth;
|
|
220
|
-
}
|
|
221
|
-
return dfs(root, 0);
|
|
222
|
-
}
|
|
223
|
-
function getStats(graph) {
|
|
224
|
-
const byStatus = {
|
|
225
|
-
running: 0,
|
|
226
|
-
completed: 0,
|
|
227
|
-
failed: 0,
|
|
228
|
-
hung: 0,
|
|
229
|
-
timeout: 0
|
|
230
|
-
};
|
|
231
|
-
const byType = {
|
|
232
|
-
agent: 0,
|
|
233
|
-
tool: 0,
|
|
234
|
-
subagent: 0,
|
|
235
|
-
wait: 0,
|
|
236
|
-
decision: 0,
|
|
237
|
-
custom: 0
|
|
238
|
-
};
|
|
239
|
-
let failureCount = 0;
|
|
240
|
-
let hungCount = 0;
|
|
241
|
-
for (const node of graph.nodes.values()) {
|
|
242
|
-
byStatus[node.status]++;
|
|
243
|
-
byType[node.type]++;
|
|
244
|
-
if (node.status === "failed" || node.status === "timeout" || node.status === "hung") {
|
|
245
|
-
failureCount++;
|
|
246
|
-
}
|
|
247
|
-
if (node.status === "running" && node.endTime === null) {
|
|
248
|
-
hungCount++;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return {
|
|
252
|
-
totalNodes: graph.nodes.size,
|
|
253
|
-
byStatus,
|
|
254
|
-
byType,
|
|
255
|
-
depth: getDepth(graph),
|
|
256
|
-
duration: getDuration(graph),
|
|
257
|
-
failureCount,
|
|
258
|
-
hungCount
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
|
|
262
189
|
// src/stats.ts
|
|
190
|
+
var import_agentflow_core2 = require("agentflow-core");
|
|
263
191
|
var AgentStats = class {
|
|
264
192
|
agentMetrics = /* @__PURE__ */ new Map();
|
|
265
193
|
processedTraces = /* @__PURE__ */ new Set();
|
|
266
194
|
processTrace(trace) {
|
|
267
|
-
const traceKey = `${trace.filename || trace.agentId}-${trace.
|
|
195
|
+
const traceKey = `${trace.filename || trace.agentId}-${trace.startTime}`;
|
|
268
196
|
if (this.processedTraces.has(traceKey)) {
|
|
269
197
|
return;
|
|
270
198
|
}
|
|
@@ -287,7 +215,7 @@ var AgentStats = class {
|
|
|
287
215
|
}
|
|
288
216
|
const analysis = this.analyzeExecution(trace);
|
|
289
217
|
metrics.totalExecutions++;
|
|
290
|
-
metrics.lastExecution = Math.max(metrics.lastExecution, trace.
|
|
218
|
+
metrics.lastExecution = Math.max(metrics.lastExecution, trace.startTime);
|
|
291
219
|
const trigger = trace.trigger || "unknown";
|
|
292
220
|
metrics.triggers[trigger] = (metrics.triggers[trigger] || 0) + 1;
|
|
293
221
|
if (analysis.success) {
|
|
@@ -302,7 +230,7 @@ var AgentStats = class {
|
|
|
302
230
|
metrics.avgExecutionTime = (currentAvg * (count - 1) + analysis.executionTime) / count;
|
|
303
231
|
}
|
|
304
232
|
metrics.recentActivity.push({
|
|
305
|
-
timestamp: trace.
|
|
233
|
+
timestamp: trace.startTime,
|
|
306
234
|
success: analysis.success,
|
|
307
235
|
executionTime: analysis.executionTime,
|
|
308
236
|
trigger
|
|
@@ -314,23 +242,22 @@ var AgentStats = class {
|
|
|
314
242
|
}
|
|
315
243
|
analyzeExecution(trace) {
|
|
316
244
|
try {
|
|
317
|
-
const stats = getStats(trace);
|
|
318
|
-
const failures = getFailures(trace);
|
|
319
|
-
const hungNodes = getHungNodes(trace);
|
|
245
|
+
const stats = (0, import_agentflow_core2.getStats)(trace);
|
|
246
|
+
const failures = (0, import_agentflow_core2.getFailures)(trace);
|
|
247
|
+
const hungNodes = (0, import_agentflow_core2.getHungNodes)(trace);
|
|
320
248
|
return {
|
|
321
249
|
success: failures.length === 0 && hungNodes.length === 0,
|
|
322
|
-
executionTime: stats.
|
|
250
|
+
executionTime: stats.duration || 0,
|
|
323
251
|
nodeCount: stats.totalNodes || 0,
|
|
324
252
|
failureCount: failures.length,
|
|
325
253
|
hungCount: hungNodes.length
|
|
326
254
|
};
|
|
327
255
|
} catch (error) {
|
|
328
256
|
console.warn("Error analyzing trace with AgentFlow:", error);
|
|
329
|
-
const nodes = trace.nodes instanceof Map ? Array.from(trace.nodes.values()) :
|
|
257
|
+
const nodes = trace.nodes instanceof Map ? Array.from(trace.nodes.values()) : [];
|
|
330
258
|
const failedNodes = nodes.filter((node) => node.status === "failed").length;
|
|
331
|
-
const success = failedNodes === 0;
|
|
332
259
|
return {
|
|
333
|
-
success,
|
|
260
|
+
success: failedNodes === 0,
|
|
334
261
|
executionTime: 0,
|
|
335
262
|
nodeCount: nodes.length,
|
|
336
263
|
failureCount: failedNodes,
|
|
@@ -420,7 +347,6 @@ var AgentStats = class {
|
|
|
420
347
|
hourlySuccessRate: recentExecutions > 0 ? Math.round((recentExecutions - recentFailures) / recentExecutions * 1e4) / 100 : 0
|
|
421
348
|
};
|
|
422
349
|
}
|
|
423
|
-
// Clear old data (useful for long-running dashboard instances)
|
|
424
350
|
cleanup() {
|
|
425
351
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
426
352
|
for (const [agentId, metrics] of this.agentMetrics.entries()) {
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import chokidar from "chokidar";
|
|
|
13
13
|
import * as fs from "fs";
|
|
14
14
|
import * as path from "path";
|
|
15
15
|
import { EventEmitter } from "events";
|
|
16
|
+
import { loadGraph } from "agentflow-core";
|
|
16
17
|
var TraceWatcher = class extends EventEmitter {
|
|
17
18
|
watcher;
|
|
18
19
|
traces = /* @__PURE__ */ new Map();
|
|
@@ -45,16 +46,12 @@ var TraceWatcher = class extends EventEmitter {
|
|
|
45
46
|
loadTraceFile(filePath) {
|
|
46
47
|
try {
|
|
47
48
|
const content = fs.readFileSync(filePath, "utf8");
|
|
48
|
-
const
|
|
49
|
+
const graph = loadGraph(content);
|
|
49
50
|
const filename = path.basename(filePath);
|
|
50
51
|
const stats = fs.statSync(filePath);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const nodesMap = new Map(trace.nodes);
|
|
55
|
-
trace.nodes = nodesMap;
|
|
56
|
-
}
|
|
57
|
-
this.traces.set(filename, trace);
|
|
52
|
+
graph.filename = filename;
|
|
53
|
+
graph.lastModified = stats.mtime.getTime();
|
|
54
|
+
this.traces.set(filename, graph);
|
|
58
55
|
return true;
|
|
59
56
|
} catch (error) {
|
|
60
57
|
console.error(`Error loading trace file ${filePath}:`, error);
|
|
@@ -63,7 +60,7 @@ var TraceWatcher = class extends EventEmitter {
|
|
|
63
60
|
}
|
|
64
61
|
startWatching() {
|
|
65
62
|
this.watcher = chokidar.watch(this.tracesDir, {
|
|
66
|
-
ignored:
|
|
63
|
+
ignored: /^\./,
|
|
67
64
|
persistent: true,
|
|
68
65
|
ignoreInitial: true
|
|
69
66
|
});
|
|
@@ -106,7 +103,7 @@ var TraceWatcher = class extends EventEmitter {
|
|
|
106
103
|
}
|
|
107
104
|
getAllTraces() {
|
|
108
105
|
return Array.from(this.traces.values()).sort((a, b) => {
|
|
109
|
-
return (b.lastModified || b.
|
|
106
|
+
return (b.lastModified || b.startTime) - (a.lastModified || a.startTime);
|
|
110
107
|
});
|
|
111
108
|
}
|
|
112
109
|
getTrace(filename) {
|
|
@@ -135,7 +132,6 @@ var TraceWatcher = class extends EventEmitter {
|
|
|
135
132
|
console.log("Stopped watching traces directory");
|
|
136
133
|
}
|
|
137
134
|
}
|
|
138
|
-
// Utility method to get trace statistics
|
|
139
135
|
getTraceStats() {
|
|
140
136
|
const total = this.traces.size;
|
|
141
137
|
const agentCount = this.getAgentIds().length;
|
|
@@ -154,81 +150,13 @@ var TraceWatcher = class extends EventEmitter {
|
|
|
154
150
|
}
|
|
155
151
|
};
|
|
156
152
|
|
|
157
|
-
// ../core/dist/index.js
|
|
158
|
-
function getFailures(graph) {
|
|
159
|
-
const failureStatuses = /* @__PURE__ */ new Set(["failed", "hung", "timeout"]);
|
|
160
|
-
return [...graph.nodes.values()].filter((node) => failureStatuses.has(node.status));
|
|
161
|
-
}
|
|
162
|
-
function getHungNodes(graph) {
|
|
163
|
-
return [...graph.nodes.values()].filter(
|
|
164
|
-
(node) => node.status === "running" && node.endTime === null
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
function getDuration(graph) {
|
|
168
|
-
const end = graph.endTime ?? Date.now();
|
|
169
|
-
return end - graph.startTime;
|
|
170
|
-
}
|
|
171
|
-
function getDepth(graph) {
|
|
172
|
-
const root = graph.nodes.get(graph.rootNodeId);
|
|
173
|
-
if (!root) return -1;
|
|
174
|
-
function dfs(node, depth) {
|
|
175
|
-
if (node.children.length === 0) return depth;
|
|
176
|
-
let maxDepth = depth;
|
|
177
|
-
for (const childId of node.children) {
|
|
178
|
-
const child = graph.nodes.get(childId);
|
|
179
|
-
if (!child) continue;
|
|
180
|
-
const childDepth = dfs(child, depth + 1);
|
|
181
|
-
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
182
|
-
}
|
|
183
|
-
return maxDepth;
|
|
184
|
-
}
|
|
185
|
-
return dfs(root, 0);
|
|
186
|
-
}
|
|
187
|
-
function getStats(graph) {
|
|
188
|
-
const byStatus = {
|
|
189
|
-
running: 0,
|
|
190
|
-
completed: 0,
|
|
191
|
-
failed: 0,
|
|
192
|
-
hung: 0,
|
|
193
|
-
timeout: 0
|
|
194
|
-
};
|
|
195
|
-
const byType = {
|
|
196
|
-
agent: 0,
|
|
197
|
-
tool: 0,
|
|
198
|
-
subagent: 0,
|
|
199
|
-
wait: 0,
|
|
200
|
-
decision: 0,
|
|
201
|
-
custom: 0
|
|
202
|
-
};
|
|
203
|
-
let failureCount = 0;
|
|
204
|
-
let hungCount = 0;
|
|
205
|
-
for (const node of graph.nodes.values()) {
|
|
206
|
-
byStatus[node.status]++;
|
|
207
|
-
byType[node.type]++;
|
|
208
|
-
if (node.status === "failed" || node.status === "timeout" || node.status === "hung") {
|
|
209
|
-
failureCount++;
|
|
210
|
-
}
|
|
211
|
-
if (node.status === "running" && node.endTime === null) {
|
|
212
|
-
hungCount++;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
totalNodes: graph.nodes.size,
|
|
217
|
-
byStatus,
|
|
218
|
-
byType,
|
|
219
|
-
depth: getDepth(graph),
|
|
220
|
-
duration: getDuration(graph),
|
|
221
|
-
failureCount,
|
|
222
|
-
hungCount
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
|
|
226
153
|
// src/stats.ts
|
|
154
|
+
import { getStats, getFailures, getHungNodes } from "agentflow-core";
|
|
227
155
|
var AgentStats = class {
|
|
228
156
|
agentMetrics = /* @__PURE__ */ new Map();
|
|
229
157
|
processedTraces = /* @__PURE__ */ new Set();
|
|
230
158
|
processTrace(trace) {
|
|
231
|
-
const traceKey = `${trace.filename || trace.agentId}-${trace.
|
|
159
|
+
const traceKey = `${trace.filename || trace.agentId}-${trace.startTime}`;
|
|
232
160
|
if (this.processedTraces.has(traceKey)) {
|
|
233
161
|
return;
|
|
234
162
|
}
|
|
@@ -251,7 +179,7 @@ var AgentStats = class {
|
|
|
251
179
|
}
|
|
252
180
|
const analysis = this.analyzeExecution(trace);
|
|
253
181
|
metrics.totalExecutions++;
|
|
254
|
-
metrics.lastExecution = Math.max(metrics.lastExecution, trace.
|
|
182
|
+
metrics.lastExecution = Math.max(metrics.lastExecution, trace.startTime);
|
|
255
183
|
const trigger = trace.trigger || "unknown";
|
|
256
184
|
metrics.triggers[trigger] = (metrics.triggers[trigger] || 0) + 1;
|
|
257
185
|
if (analysis.success) {
|
|
@@ -266,7 +194,7 @@ var AgentStats = class {
|
|
|
266
194
|
metrics.avgExecutionTime = (currentAvg * (count - 1) + analysis.executionTime) / count;
|
|
267
195
|
}
|
|
268
196
|
metrics.recentActivity.push({
|
|
269
|
-
timestamp: trace.
|
|
197
|
+
timestamp: trace.startTime,
|
|
270
198
|
success: analysis.success,
|
|
271
199
|
executionTime: analysis.executionTime,
|
|
272
200
|
trigger
|
|
@@ -283,18 +211,17 @@ var AgentStats = class {
|
|
|
283
211
|
const hungNodes = getHungNodes(trace);
|
|
284
212
|
return {
|
|
285
213
|
success: failures.length === 0 && hungNodes.length === 0,
|
|
286
|
-
executionTime: stats.
|
|
214
|
+
executionTime: stats.duration || 0,
|
|
287
215
|
nodeCount: stats.totalNodes || 0,
|
|
288
216
|
failureCount: failures.length,
|
|
289
217
|
hungCount: hungNodes.length
|
|
290
218
|
};
|
|
291
219
|
} catch (error) {
|
|
292
220
|
console.warn("Error analyzing trace with AgentFlow:", error);
|
|
293
|
-
const nodes = trace.nodes instanceof Map ? Array.from(trace.nodes.values()) :
|
|
221
|
+
const nodes = trace.nodes instanceof Map ? Array.from(trace.nodes.values()) : [];
|
|
294
222
|
const failedNodes = nodes.filter((node) => node.status === "failed").length;
|
|
295
|
-
const success = failedNodes === 0;
|
|
296
223
|
return {
|
|
297
|
-
success,
|
|
224
|
+
success: failedNodes === 0,
|
|
298
225
|
executionTime: 0,
|
|
299
226
|
nodeCount: nodes.length,
|
|
300
227
|
failureCount: failedNodes,
|
|
@@ -384,7 +311,6 @@ var AgentStats = class {
|
|
|
384
311
|
hourlySuccessRate: recentExecutions > 0 ? Math.round((recentExecutions - recentFailures) / recentExecutions * 1e4) / 100 : 0
|
|
385
312
|
};
|
|
386
313
|
}
|
|
387
|
-
// Clear old data (useful for long-running dashboard instances)
|
|
388
314
|
cleanup() {
|
|
389
315
|
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
390
316
|
for (const [agentId, metrics] of this.agentMetrics.entries()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentflow-dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Real-time monitoring dashboard for AgentFlow - Visualize agent execution graphs and performance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"start": "node dist/server.js"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"agentflow-core": "^0.1.4",
|
|
30
31
|
"express": "^4.18.2",
|
|
31
32
|
"ws": "^8.16.0",
|
|
32
33
|
"chokidar": "^3.5.3"
|