@railtownai/railtracks-visualizer 0.0.2 → 0.0.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/LICENSE +201 -201
- package/README.md +52 -23
- package/dist/cjs/AgenticFlowVisualizer.js +750 -0
- package/dist/cjs/App.js +94 -0
- package/dist/cjs/Visualizer.js +16 -0
- package/dist/cjs/components/Edge.js +75 -0
- package/dist/cjs/components/FileSelector.js +28 -0
- package/dist/cjs/components/Node.js +104 -0
- package/dist/cjs/components/Timeline.js +122 -0
- package/dist/cjs/components/VerticalTimeline.js +160 -0
- package/dist/cjs/hooks/index.js +7 -0
- package/dist/cjs/hooks/useApi.js +108 -0
- package/dist/cjs/hooks/useFlowData.js +53 -0
- package/dist/cjs/index.js +40 -0
- package/dist/cjs/test/Visualizer.test.js +257 -0
- package/dist/cjs/test/setup.js +24 -0
- package/dist/{AgenticFlowVisualizer.js → esm/AgenticFlowVisualizer.js} +286 -286
- package/dist/{App.js → esm/App.js} +76 -76
- package/dist/esm/Visualizer.js +11 -0
- package/dist/{components → esm/components}/Edge.js +10 -10
- package/dist/{components → esm/components}/Node.js +70 -70
- package/dist/{components → esm/components}/VerticalTimeline.js +12 -12
- package/dist/{index.js → esm/index.js} +1 -2
- package/dist/esm/test/Visualizer.test.js +243 -0
- package/dist/{test → esm/test}/setup.js +1 -1
- package/dist/{AgenticFlowVisualizer.d.ts → types/AgenticFlowVisualizer.d.ts} +2 -2
- package/dist/types/AgenticFlowVisualizer.d.ts.map +1 -0
- package/dist/types/App.d.ts.map +1 -0
- package/dist/types/Visualizer.d.ts +9 -0
- package/dist/types/Visualizer.d.ts.map +1 -0
- package/dist/types/components/Edge.d.ts.map +1 -0
- package/dist/types/components/FileSelector.d.ts.map +1 -0
- package/dist/types/components/Node.d.ts.map +1 -0
- package/dist/types/components/Timeline.d.ts.map +1 -0
- package/dist/types/components/VerticalTimeline.d.ts.map +1 -0
- package/dist/types/hooks/index.d.ts.map +1 -0
- package/dist/types/hooks/useApi.d.ts.map +1 -0
- package/dist/types/hooks/useFlowData.d.ts.map +1 -0
- package/dist/{index.d.ts → types/index.d.ts} +2 -1
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/test/Visualizer.test.d.ts +2 -0
- package/dist/types/test/Visualizer.test.d.ts.map +1 -0
- package/dist/types/test/setup.d.ts.map +1 -0
- package/package.json +82 -75
- package/dist/AgenticFlowVisualizer.d.ts.map +0 -1
- package/dist/App.d.ts.map +0 -1
- package/dist/components/Edge.d.ts.map +0 -1
- package/dist/components/FileSelector.d.ts.map +0 -1
- package/dist/components/Node.d.ts.map +0 -1
- package/dist/components/Timeline.d.ts.map +0 -1
- package/dist/components/VerticalTimeline.d.ts.map +0 -1
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/useApi.d.ts.map +0 -1
- package/dist/hooks/useFlowData.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/test/setup.d.ts.map +0 -1
- /package/dist/{components → esm/components}/FileSelector.js +0 -0
- /package/dist/{components → esm/components}/Timeline.js +0 -0
- /package/dist/{hooks → esm/hooks}/index.js +0 -0
- /package/dist/{hooks → esm/hooks}/useApi.js +0 -0
- /package/dist/{hooks → esm/hooks}/useFlowData.js +0 -0
- /package/dist/{App.d.ts → types/App.d.ts} +0 -0
- /package/dist/{components → types/components}/Edge.d.ts +0 -0
- /package/dist/{components → types/components}/FileSelector.d.ts +0 -0
- /package/dist/{components → types/components}/Node.d.ts +0 -0
- /package/dist/{components → types/components}/Timeline.d.ts +0 -0
- /package/dist/{components → types/components}/VerticalTimeline.d.ts +0 -0
- /package/dist/{hooks → types/hooks}/index.d.ts +0 -0
- /package/dist/{hooks → types/hooks}/useApi.d.ts +0 -0
- /package/dist/{hooks → types/hooks}/useFlowData.d.ts +0 -0
- /package/dist/{test → types/test}/setup.d.ts +0 -0
package/dist/cjs/App.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const reactflow_1 = require("reactflow");
|
|
8
|
+
const hooks_1 = require("./hooks");
|
|
9
|
+
const FileSelector_1 = require("./components/FileSelector");
|
|
10
|
+
const AgenticFlowVisualizer_1 = __importDefault(require("./AgenticFlowVisualizer"));
|
|
11
|
+
const App = () => {
|
|
12
|
+
const { availableFiles, currentFile, flowData, loading, error, loadFile, refreshFiles } = (0, hooks_1.useFlowData)();
|
|
13
|
+
const handleFileSelect = (filename) => {
|
|
14
|
+
loadFile(filename);
|
|
15
|
+
};
|
|
16
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "app", children: [(0, jsx_runtime_1.jsxs)("div", { className: "app-header", children: [(0, jsx_runtime_1.jsx)("h1", { children: "RailTracks Visualizer" }), (0, jsx_runtime_1.jsx)("div", { className: "file-selector-container", children: (0, jsx_runtime_1.jsx)(FileSelector_1.FileSelector, { files: availableFiles, currentFile: currentFile, onFileSelect: handleFileSelect, onRefresh: refreshFiles, loading: loading, disabled: loading }) })] }), error && ((0, jsx_runtime_1.jsx)("div", { className: "error-message", children: (0, jsx_runtime_1.jsxs)("p", { children: ["Error: ", error] }) })), (0, jsx_runtime_1.jsx)("div", { className: "visualizer-container", children: loading ? ((0, jsx_runtime_1.jsxs)("div", { className: "loading-state", children: [(0, jsx_runtime_1.jsx)("div", { className: "loading-spinner" }), (0, jsx_runtime_1.jsx)("p", { children: "Loading flow data..." })] })) : flowData ? ((0, jsx_runtime_1.jsx)(reactflow_1.ReactFlowProvider, { children: (0, jsx_runtime_1.jsx)(AgenticFlowVisualizer_1.default, { flowData: flowData }) })) : ((0, jsx_runtime_1.jsx)("div", { className: "no-data-state", children: (0, jsx_runtime_1.jsx)("p", { children: "Please select a file to visualize the flow data" }) })) }), (0, jsx_runtime_1.jsx)("style", { children: `
|
|
17
|
+
.app {
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
background: #f9fafb;
|
|
20
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.app-header {
|
|
24
|
+
background: white;
|
|
25
|
+
border-bottom: 1px solid #e5e7eb;
|
|
26
|
+
padding: 5px;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.app-header h1 {
|
|
34
|
+
margin: 0;
|
|
35
|
+
font-size: 18px;
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
color: #1f2937;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.file-selector-container {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.error-message {
|
|
46
|
+
background: #fee2e2;
|
|
47
|
+
border: 1px solid #fecaca;
|
|
48
|
+
color: #991b1b;
|
|
49
|
+
padding: 12px 20px;
|
|
50
|
+
margin: 20px;
|
|
51
|
+
border-radius: 6px;
|
|
52
|
+
font-size: 14px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.visualizer-container {
|
|
56
|
+
padding: 20px;
|
|
57
|
+
min-height: calc(100vh - 100px);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.loading-state {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
align-items: center;
|
|
64
|
+
justify-content: center;
|
|
65
|
+
height: 400px;
|
|
66
|
+
color: #6b7280;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.loading-spinner {
|
|
70
|
+
width: 40px;
|
|
71
|
+
height: 40px;
|
|
72
|
+
border: 4px solid #e5e7eb;
|
|
73
|
+
border-top: 4px solid #6366f1;
|
|
74
|
+
border-radius: 50%;
|
|
75
|
+
animation: spin 1s linear infinite;
|
|
76
|
+
margin-bottom: 16px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes spin {
|
|
80
|
+
0% { transform: rotate(0deg); }
|
|
81
|
+
100% { transform: rotate(360deg); }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.no-data-state {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
height: 400px;
|
|
89
|
+
color: #6b7280;
|
|
90
|
+
font-size: 16px;
|
|
91
|
+
}
|
|
92
|
+
` })] }));
|
|
93
|
+
};
|
|
94
|
+
exports.default = App;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
|
+
const reactflow_1 = require("reactflow");
|
|
8
|
+
const AgenticFlowVisualizer_1 = __importDefault(require("./AgenticFlowVisualizer"));
|
|
9
|
+
/**
|
|
10
|
+
* Visualizer component that wraps AgenticFlowVisualizer with ReactFlowProvider.
|
|
11
|
+
* This is the main component that should be imported from the npm package.
|
|
12
|
+
*/
|
|
13
|
+
const Visualizer = (props) => {
|
|
14
|
+
return ((0, jsx_runtime_1.jsx)(reactflow_1.ReactFlowProvider, { children: (0, jsx_runtime_1.jsx)(AgenticFlowVisualizer_1.default, Object.assign({}, props)) }));
|
|
15
|
+
};
|
|
16
|
+
exports.default = Visualizer;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Edge = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const Edge = ({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style = {}, markerEnd, bidirectional = false, data, clientToSvgCoords, svgRef, onInspect }) => {
|
|
7
|
+
var _a;
|
|
8
|
+
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
|
|
9
|
+
// Function to determine stroke color based on edge state
|
|
10
|
+
const getStrokeColor = () => {
|
|
11
|
+
var _a;
|
|
12
|
+
const state = (_a = data === null || data === void 0 ? void 0 : data.details) === null || _a === void 0 ? void 0 : _a.state;
|
|
13
|
+
switch (state) {
|
|
14
|
+
case "Open":
|
|
15
|
+
return "#000000"; // Black
|
|
16
|
+
case "Completed":
|
|
17
|
+
return "#15803d"; // Darker Green
|
|
18
|
+
case "Error":
|
|
19
|
+
return "#ef4444"; // Red
|
|
20
|
+
default:
|
|
21
|
+
return style.stroke || "#6366f1"; // Default color
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const [edgePath, arrowMarkers] = (0, react_1.useMemo)(() => {
|
|
25
|
+
// Always use curved paths for better visual appeal
|
|
26
|
+
const centerX = (sourceX + targetX) / 2;
|
|
27
|
+
const centerY = (sourceY + targetY) / 2;
|
|
28
|
+
const path = `M ${sourceX} ${sourceY} Q ${centerX} ${centerY} ${targetX} ${targetY}`;
|
|
29
|
+
// Create arrow markers for bidirectional edges
|
|
30
|
+
const markers = [];
|
|
31
|
+
if (bidirectional) {
|
|
32
|
+
const strokeColor = getStrokeColor();
|
|
33
|
+
// Forward arrow (source to target)
|
|
34
|
+
markers.push((0, jsx_runtime_1.jsxs)("defs", { children: [(0, jsx_runtime_1.jsx)("marker", { id: `${id}-arrowhead-forward`, markerWidth: "10", markerHeight: "7", refX: "9", refY: "3.5", orient: "auto", markerUnits: "strokeWidth", children: (0, jsx_runtime_1.jsx)("polygon", { points: "0 0, 10 3.5, 0 7", fill: strokeColor }) }), (0, jsx_runtime_1.jsx)("marker", { id: `${id}-arrowhead-backward`, markerWidth: "10", markerHeight: "7", refX: "1", refY: "3.5", orient: "auto", markerUnits: "strokeWidth", children: (0, jsx_runtime_1.jsx)("polygon", { points: "10 0, 0 3.5, 10 7", fill: strokeColor }) })] }, `${id}-markers`));
|
|
35
|
+
}
|
|
36
|
+
return [path, markers];
|
|
37
|
+
}, [sourceX, sourceY, targetX, targetY, id, bidirectional, (_a = data === null || data === void 0 ? void 0 : data.details) === null || _a === void 0 ? void 0 : _a.state]);
|
|
38
|
+
const hoverStyle = Object.assign(Object.assign({}, style), { stroke: getStrokeColor(), strokeWidth: style.strokeWidth || 4, cursor: "pointer" });
|
|
39
|
+
const handleInspectClick = (event) => {
|
|
40
|
+
event.stopPropagation();
|
|
41
|
+
if (onInspect && data) {
|
|
42
|
+
onInspect(data);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return ((0, jsx_runtime_1.jsxs)("g", { "data-edge-id": id, children: [arrowMarkers, (0, jsx_runtime_1.jsx)("path", { id: id, className: "react-flow__edge-path", d: edgePath, markerEnd: bidirectional ? `url(#${id}-arrowhead-forward)` : markerEnd, markerStart: bidirectional ? `url(#${id}-arrowhead-backward)` : undefined, style: hoverStyle }), (data === null || data === void 0 ? void 0 : data.label) && ((0, jsx_runtime_1.jsx)("foreignObject", { x: (sourceX + targetX) / 2 - 50, y: (sourceY + targetY) / 2 - 20, width: "100", height: "40", style: { overflow: "visible", pointerEvents: "none" }, children: (0, jsx_runtime_1.jsx)("div", { className: "edge-label-renderer", style: {
|
|
46
|
+
display: "flex",
|
|
47
|
+
alignItems: "center",
|
|
48
|
+
justifyContent: "center",
|
|
49
|
+
width: "100%",
|
|
50
|
+
height: "100%",
|
|
51
|
+
pointerEvents: "auto"
|
|
52
|
+
}, children: (0, jsx_runtime_1.jsx)("button", { className: "edge-label-button", onClick: handleInspectClick, style: {
|
|
53
|
+
background: "#6366f1",
|
|
54
|
+
color: "white",
|
|
55
|
+
border: "none",
|
|
56
|
+
borderRadius: 6,
|
|
57
|
+
padding: "4px 12px",
|
|
58
|
+
fontSize: 12,
|
|
59
|
+
fontWeight: 600,
|
|
60
|
+
cursor: "pointer",
|
|
61
|
+
boxShadow: "0 2px 8px rgba(99,102,241,0.10)",
|
|
62
|
+
transition: "background 0.2s"
|
|
63
|
+
}, children: "Inspect" }) }) })), (0, jsx_runtime_1.jsx)("style", { children: `
|
|
64
|
+
.edge-label-renderer {
|
|
65
|
+
z-index: 8001;
|
|
66
|
+
user-select: none;
|
|
67
|
+
pointer-events: auto;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.edge-label-button {
|
|
71
|
+
pointer-events: auto;
|
|
72
|
+
}
|
|
73
|
+
` })] }));
|
|
74
|
+
};
|
|
75
|
+
exports.Edge = Edge;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileSelector = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const lucide_react_1 = require("lucide-react");
|
|
6
|
+
const FileSelector = ({ files, currentFile, onFileSelect, onRefresh, loading = false, disabled = false }) => {
|
|
7
|
+
const handleRefresh = (e) => {
|
|
8
|
+
e.stopPropagation();
|
|
9
|
+
onRefresh();
|
|
10
|
+
};
|
|
11
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [(0, jsx_runtime_1.jsxs)("select", { value: currentFile || "", onChange: (e) => onFileSelect(e.target.value), disabled: disabled, style: {
|
|
12
|
+
cursor: "pointer",
|
|
13
|
+
padding: "8px 16px 8px 16px",
|
|
14
|
+
borderRadius: "4px",
|
|
15
|
+
fontSize: "14px",
|
|
16
|
+
border: "1px solid #ccc",
|
|
17
|
+
appearance: "none",
|
|
18
|
+
WebkitAppearance: "none",
|
|
19
|
+
MozAppearance: "none"
|
|
20
|
+
}, children: [(0, jsx_runtime_1.jsx)("option", { value: "", children: "Select a RailTracks Run..." }), files.map((file) => ((0, jsx_runtime_1.jsx)("option", { value: file.name, children: file.name }, file.name)))] }), (0, jsx_runtime_1.jsx)("button", { onClick: handleRefresh, disabled: loading || disabled, title: "Refresh files", style: {
|
|
21
|
+
background: "none",
|
|
22
|
+
border: "none",
|
|
23
|
+
cursor: "pointer",
|
|
24
|
+
padding: "4px",
|
|
25
|
+
borderRadius: "4px"
|
|
26
|
+
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCw, { size: 16, style: { animation: loading ? "spin 1s linear infinite" : "none" } }) })] }));
|
|
27
|
+
};
|
|
28
|
+
exports.FileSelector = FileSelector;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Node = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const reactflow_1 = require("reactflow");
|
|
6
|
+
const Node = ({ data, id }) => {
|
|
7
|
+
var _a;
|
|
8
|
+
const { fitView } = (0, reactflow_1.useReactFlow)();
|
|
9
|
+
// Check if this node has any outgoing edges (source edges)
|
|
10
|
+
const hasOutgoingEdges = ((_a = data.edges) === null || _a === void 0 ? void 0 : _a.some((edge) => edge.source === id)) || false;
|
|
11
|
+
const handleNodeClick = () => {
|
|
12
|
+
// Zoom to the node
|
|
13
|
+
fitView({
|
|
14
|
+
nodes: [{ id }],
|
|
15
|
+
duration: 800,
|
|
16
|
+
padding: 0.1,
|
|
17
|
+
minZoom: 0.5,
|
|
18
|
+
maxZoom: 1.5
|
|
19
|
+
});
|
|
20
|
+
// Open inspection drawer
|
|
21
|
+
if (data.onInspect) {
|
|
22
|
+
data.onInspect({
|
|
23
|
+
label: data.label,
|
|
24
|
+
description: data.description,
|
|
25
|
+
nodeType: data.nodeType,
|
|
26
|
+
step: data.step,
|
|
27
|
+
time: data.time,
|
|
28
|
+
icon: data.icon
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "agent-node", onClick: handleNodeClick, style: { cursor: "pointer" }, children: [(0, jsx_runtime_1.jsx)(reactflow_1.Handle, { type: "target", position: reactflow_1.Position.Top, style: { background: "#6366f1" } }), (0, jsx_runtime_1.jsxs)("div", { className: "agent-header", children: [(0, jsx_runtime_1.jsx)("div", { className: "agent-icon", children: data.icon || "📋" }), (0, jsx_runtime_1.jsx)("div", { className: "agent-label", children: data.label })] }), data.description && (0, jsx_runtime_1.jsx)("div", { className: "agent-description", children: data.description }), data.step && ((0, jsx_runtime_1.jsxs)("div", { className: "agent-meta", children: [(0, jsx_runtime_1.jsxs)("span", { className: "step", children: ["Step: ", data.step] }), data.time && (0, jsx_runtime_1.jsx)("span", { className: "time", children: new Date(data.time * 1000).toLocaleTimeString() })] })), hasOutgoingEdges && (0, jsx_runtime_1.jsx)(reactflow_1.Handle, { type: "source", position: reactflow_1.Position.Bottom, style: { background: "#6366f1" } })] }), (0, jsx_runtime_1.jsx)("style", { children: `
|
|
33
|
+
.agent-node {
|
|
34
|
+
padding: 12px;
|
|
35
|
+
border-radius: 8px;
|
|
36
|
+
background: white;
|
|
37
|
+
border: 2px solid #e5e7eb;
|
|
38
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
39
|
+
min-width: 200px;
|
|
40
|
+
max-width: 250px;
|
|
41
|
+
transition: all 0.2s ease;
|
|
42
|
+
position: relative;
|
|
43
|
+
z-index: -5;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.agent-node:hover {
|
|
47
|
+
border-color: #6366f1;
|
|
48
|
+
box-shadow: 0 4px 8px rgba(99, 102, 241, 0.2);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.agent-header {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: 8px;
|
|
55
|
+
margin-bottom: 8px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.agent-icon {
|
|
59
|
+
font-size: 20px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.agent-label {
|
|
63
|
+
font-weight: 600;
|
|
64
|
+
color: #1f2937;
|
|
65
|
+
font-size: 14px;
|
|
66
|
+
word-break: break-word;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.agent-description {
|
|
70
|
+
color: #6b7280;
|
|
71
|
+
font-size: 12px;
|
|
72
|
+
line-height: 1.4;
|
|
73
|
+
word-break: break-word;
|
|
74
|
+
white-space: pre-line;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.agent-meta {
|
|
78
|
+
margin-top: 8px;
|
|
79
|
+
padding-top: 8px;
|
|
80
|
+
border-top: 1px solid #e5e7eb;
|
|
81
|
+
display: flex;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
font-size: 10px;
|
|
84
|
+
color: #9ca3af;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.step {
|
|
88
|
+
background: #f3f4f6;
|
|
89
|
+
padding: 2px 6px;
|
|
90
|
+
border-radius: 4px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.time {
|
|
94
|
+
font-family: monospace;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.react-flow__handle {
|
|
98
|
+
width: 8px;
|
|
99
|
+
height: 8px;
|
|
100
|
+
border: 2px solid #6366f1;
|
|
101
|
+
}
|
|
102
|
+
` })] }));
|
|
103
|
+
};
|
|
104
|
+
exports.Node = Node;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timeline = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const Timeline = ({ stamps, currentStep, isPlaying, onStepChange, onPlayPause }) => {
|
|
7
|
+
const maxStep = stamps.length > 0 ? Math.max(...stamps.map((s) => s.step)) : 0;
|
|
8
|
+
const minStep = stamps.length > 0 ? Math.min(...stamps.map((s) => s.step)) : 0;
|
|
9
|
+
const totalSteps = maxStep - minStep + 1;
|
|
10
|
+
// Initialize Bootstrap tooltips
|
|
11
|
+
(0, react_1.useEffect)(() => {
|
|
12
|
+
// Initialize all tooltips
|
|
13
|
+
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
14
|
+
const tooltipList = Array.from(tooltipTriggerList).map((tooltipTriggerEl) => new window.bootstrap.Tooltip(tooltipTriggerEl));
|
|
15
|
+
// Cleanup function to dispose tooltips
|
|
16
|
+
return () => {
|
|
17
|
+
tooltipList.forEach((tooltip) => tooltip.dispose());
|
|
18
|
+
};
|
|
19
|
+
}, [stamps, currentStep]); // Re-initialize when stamps or currentStep changes
|
|
20
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
21
|
+
position: "absolute",
|
|
22
|
+
bottom: 0,
|
|
23
|
+
left: 0,
|
|
24
|
+
right: 0,
|
|
25
|
+
height: "60px",
|
|
26
|
+
backgroundColor: "white",
|
|
27
|
+
borderTop: "1px solid #e5e7eb",
|
|
28
|
+
display: "flex",
|
|
29
|
+
alignItems: "center",
|
|
30
|
+
padding: "0 16px",
|
|
31
|
+
gap: "12px",
|
|
32
|
+
zIndex: 10
|
|
33
|
+
}, children: [(0, jsx_runtime_1.jsx)("button", { onClick: onPlayPause, style: {
|
|
34
|
+
width: "32px",
|
|
35
|
+
height: "32px",
|
|
36
|
+
borderRadius: "50%",
|
|
37
|
+
border: "1px solid #d1d5db",
|
|
38
|
+
backgroundColor: "white",
|
|
39
|
+
display: "flex",
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
justifyContent: "center",
|
|
42
|
+
cursor: "pointer",
|
|
43
|
+
transition: "all 0.2s ease"
|
|
44
|
+
}, onMouseEnter: (e) => {
|
|
45
|
+
e.currentTarget.style.backgroundColor = "#f3f4f6";
|
|
46
|
+
}, onMouseLeave: (e) => {
|
|
47
|
+
e.currentTarget.style.backgroundColor = "white";
|
|
48
|
+
}, children: isPlaying ? ((0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", gap: "2px" }, children: [(0, jsx_runtime_1.jsx)("div", { style: {
|
|
49
|
+
width: "3px",
|
|
50
|
+
height: "12px",
|
|
51
|
+
backgroundColor: "#374151"
|
|
52
|
+
} }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
53
|
+
width: "3px",
|
|
54
|
+
height: "12px",
|
|
55
|
+
backgroundColor: "#374151"
|
|
56
|
+
} })] })) : ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
57
|
+
width: 0,
|
|
58
|
+
height: 0,
|
|
59
|
+
borderLeft: "8px solid #374151",
|
|
60
|
+
borderTop: "6px solid transparent",
|
|
61
|
+
borderBottom: "6px solid transparent",
|
|
62
|
+
marginLeft: "2px"
|
|
63
|
+
} })) }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
64
|
+
flex: 1,
|
|
65
|
+
display: "flex",
|
|
66
|
+
alignItems: "center",
|
|
67
|
+
gap: "8px",
|
|
68
|
+
padding: "0 8px"
|
|
69
|
+
}, children: Array.from({ length: totalSteps }, (_, index) => {
|
|
70
|
+
var _a;
|
|
71
|
+
const step = minStep + index;
|
|
72
|
+
const isActive = step === currentStep;
|
|
73
|
+
const isPast = step < currentStep;
|
|
74
|
+
const hasStep = stamps.some((s) => s.step === step);
|
|
75
|
+
// Determine background color based on step state
|
|
76
|
+
let backgroundColor = "white";
|
|
77
|
+
if (isActive) {
|
|
78
|
+
backgroundColor = "#6366f1";
|
|
79
|
+
}
|
|
80
|
+
else if (isPast) {
|
|
81
|
+
backgroundColor = hasStep ? "#fef3c7" : "#fef3c7"; // Light yellow for past steps
|
|
82
|
+
}
|
|
83
|
+
else if (hasStep) {
|
|
84
|
+
backgroundColor = "#e5e7eb";
|
|
85
|
+
}
|
|
86
|
+
const tooltipText = `Step ${step}${hasStep ? ` - ${((_a = stamps.find((s) => s.step === step)) === null || _a === void 0 ? void 0 : _a.identifier) || ""}` : " - No activity"}`;
|
|
87
|
+
return ((0, jsx_runtime_1.jsx)("button", { onClick: () => onStepChange(step), "data-bs-toggle": "tooltip", "data-bs-placement": "top", "data-bs-title": tooltipText, style: {
|
|
88
|
+
width: "16px",
|
|
89
|
+
height: "16px",
|
|
90
|
+
borderRadius: "50%",
|
|
91
|
+
border: isActive ? "2px solid #6366f1" : "1px solid #d1d5db",
|
|
92
|
+
backgroundColor: backgroundColor,
|
|
93
|
+
cursor: "pointer",
|
|
94
|
+
transition: "all 0.2s ease",
|
|
95
|
+
position: "relative"
|
|
96
|
+
}, onMouseEnter: (e) => {
|
|
97
|
+
if (!isActive) {
|
|
98
|
+
if (isPast) {
|
|
99
|
+
e.currentTarget.style.backgroundColor = hasStep ? "#fde68a" : "#fde68a"; // Darker yellow on hover for past steps
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
e.currentTarget.style.backgroundColor = hasStep ? "#d1d5db" : "#f3f4f6";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}, onMouseLeave: (e) => {
|
|
106
|
+
if (!isActive) {
|
|
107
|
+
if (isPast) {
|
|
108
|
+
e.currentTarget.style.backgroundColor = hasStep ? "#fef3c7" : "#fef3c7"; // Back to light yellow for past steps
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
e.currentTarget.style.backgroundColor = hasStep ? "#e5e7eb" : "white";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} }, step));
|
|
115
|
+
}) }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
116
|
+
fontSize: "12px",
|
|
117
|
+
color: "#6b7280",
|
|
118
|
+
minWidth: "60px",
|
|
119
|
+
textAlign: "right"
|
|
120
|
+
}, children: [currentStep, " / ", maxStep] })] }));
|
|
121
|
+
};
|
|
122
|
+
exports.Timeline = Timeline;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VerticalTimeline = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const lucide_react_1 = require("lucide-react");
|
|
6
|
+
const VerticalTimeline = ({ stamps, currentStep, onStepChange, onToggle }) => {
|
|
7
|
+
const maxStep = stamps.length > 0 ? Math.max(...stamps.map((s) => s.step)) : 0;
|
|
8
|
+
const minStep = stamps.length > 0 ? Math.min(...stamps.map((s) => s.step)) : 0;
|
|
9
|
+
const totalSteps = maxStep - minStep + 1;
|
|
10
|
+
// Calculate latency for each step
|
|
11
|
+
const getStepLatency = (step) => {
|
|
12
|
+
const stepStamps = stamps.filter((s) => s.step === step);
|
|
13
|
+
if (stepStamps.length === 0)
|
|
14
|
+
return null;
|
|
15
|
+
// Calculate time difference from previous step
|
|
16
|
+
const prevStep = step - 1;
|
|
17
|
+
const prevStepStamps = stamps.filter((s) => s.step === prevStep);
|
|
18
|
+
if (prevStepStamps.length === 0)
|
|
19
|
+
return null;
|
|
20
|
+
const currentTime = Math.min(...stepStamps.map((s) => s.time));
|
|
21
|
+
const prevTime = Math.max(...prevStepStamps.map((s) => s.time));
|
|
22
|
+
return currentTime - prevTime;
|
|
23
|
+
};
|
|
24
|
+
// Get step label
|
|
25
|
+
const getStepLabel = (step) => {
|
|
26
|
+
var _a;
|
|
27
|
+
const stepStamps = stamps.filter((s) => s.step === step);
|
|
28
|
+
if (stepStamps.length === 0)
|
|
29
|
+
return `Step ${step}`;
|
|
30
|
+
// Get the first identifier for this step
|
|
31
|
+
const identifier = ((_a = stepStamps[0]) === null || _a === void 0 ? void 0 : _a.identifier) || "";
|
|
32
|
+
return identifier || `Step ${step}`;
|
|
33
|
+
};
|
|
34
|
+
// Format latency
|
|
35
|
+
const formatLatency = (latency) => {
|
|
36
|
+
if (latency < 1000) {
|
|
37
|
+
return `${latency.toFixed(0)}ms`;
|
|
38
|
+
}
|
|
39
|
+
else if (latency < 60000) {
|
|
40
|
+
return `${(latency / 1000).toFixed(1)}s`;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return `${(latency / 60000).toFixed(1)}m`;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
47
|
+
width: "100%",
|
|
48
|
+
height: "100%",
|
|
49
|
+
backgroundColor: "white",
|
|
50
|
+
display: "flex",
|
|
51
|
+
flexDirection: "column",
|
|
52
|
+
overflow: "hidden"
|
|
53
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
|
|
54
|
+
padding: "16px",
|
|
55
|
+
borderBottom: "1px solid #e5e7eb",
|
|
56
|
+
backgroundColor: "#f9fafb",
|
|
57
|
+
display: "flex",
|
|
58
|
+
justifyContent: "space-between",
|
|
59
|
+
alignItems: "flex-start"
|
|
60
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: {
|
|
61
|
+
margin: 0,
|
|
62
|
+
fontSize: "16px",
|
|
63
|
+
fontWeight: 600,
|
|
64
|
+
color: "#1f2937"
|
|
65
|
+
}, children: "Timeline" }), (0, jsx_runtime_1.jsx)("p", { style: {
|
|
66
|
+
margin: "4px 0 0 0",
|
|
67
|
+
fontSize: "12px",
|
|
68
|
+
color: "#6b7280"
|
|
69
|
+
}, children: "Click to jump to step" })] }), onToggle && ((0, jsx_runtime_1.jsx)("button", { onClick: onToggle, style: {
|
|
70
|
+
border: "none",
|
|
71
|
+
background: "none",
|
|
72
|
+
cursor: "pointer",
|
|
73
|
+
color: "#6b7280",
|
|
74
|
+
padding: "4px",
|
|
75
|
+
display: "flex",
|
|
76
|
+
alignItems: "center",
|
|
77
|
+
justifyContent: "center",
|
|
78
|
+
transition: "color 0.2s ease"
|
|
79
|
+
}, title: "Collapse Panel", children: (0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeft, { size: 16 }) }))] }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
80
|
+
flex: 1,
|
|
81
|
+
overflowY: "auto",
|
|
82
|
+
padding: "8px 0 16px 0" // Add bottom padding
|
|
83
|
+
}, children: Array.from({ length: totalSteps }, (_, index) => {
|
|
84
|
+
const step = minStep + index;
|
|
85
|
+
const isActive = step === currentStep;
|
|
86
|
+
const isPast = step < currentStep;
|
|
87
|
+
const hasStep = stamps.some((s) => s.step === step);
|
|
88
|
+
const latency = getStepLatency(step);
|
|
89
|
+
const label = getStepLabel(step);
|
|
90
|
+
return ((0, jsx_runtime_1.jsxs)("div", { onClick: () => hasStep && onStepChange(step), style: {
|
|
91
|
+
padding: "12px 16px",
|
|
92
|
+
borderBottom: "1px solid #f3f4f6",
|
|
93
|
+
cursor: hasStep ? "pointer" : "default",
|
|
94
|
+
backgroundColor: isActive ? "#f0f9ff" : "transparent",
|
|
95
|
+
borderLeft: isActive ? "4px solid #6366f1" : "4px solid transparent",
|
|
96
|
+
transition: "all 0.2s ease",
|
|
97
|
+
position: "relative"
|
|
98
|
+
}, onMouseEnter: (e) => {
|
|
99
|
+
if (hasStep && !isActive) {
|
|
100
|
+
e.currentTarget.style.backgroundColor = "#f8fafc";
|
|
101
|
+
}
|
|
102
|
+
}, onMouseLeave: (e) => {
|
|
103
|
+
if (hasStep && !isActive) {
|
|
104
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
105
|
+
}
|
|
106
|
+
}, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
|
|
107
|
+
display: "flex",
|
|
108
|
+
alignItems: "center",
|
|
109
|
+
gap: "8px",
|
|
110
|
+
marginBottom: "4px"
|
|
111
|
+
}, children: [(0, jsx_runtime_1.jsx)("div", { style: {
|
|
112
|
+
width: "12px",
|
|
113
|
+
height: "12px",
|
|
114
|
+
borderRadius: "50%",
|
|
115
|
+
backgroundColor: isActive ? "#6366f1" : isPast ? "#fbbf24" : hasStep ? "#9ca3af" : "#e5e7eb",
|
|
116
|
+
border: isActive ? "2px solid #6366f1" : "1px solid #d1d5db",
|
|
117
|
+
flexShrink: 0
|
|
118
|
+
} }), (0, jsx_runtime_1.jsxs)("span", { style: {
|
|
119
|
+
fontSize: "14px",
|
|
120
|
+
fontWeight: isActive ? 600 : 500,
|
|
121
|
+
color: isActive ? "#1f2937" : "#6b7280"
|
|
122
|
+
}, children: ["Step ", step] }), latency && ((0, jsx_runtime_1.jsx)("span", { style: {
|
|
123
|
+
fontSize: "11px",
|
|
124
|
+
color: "#9ca3af",
|
|
125
|
+
backgroundColor: "#f3f4f6",
|
|
126
|
+
padding: "2px 6px",
|
|
127
|
+
borderRadius: "4px",
|
|
128
|
+
marginLeft: "auto"
|
|
129
|
+
}, children: formatLatency(latency) }))] }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
130
|
+
fontSize: "13px",
|
|
131
|
+
color: hasStep ? "#1f2937" : "#9ca3af",
|
|
132
|
+
lineHeight: "1.4",
|
|
133
|
+
wordBreak: "break-word",
|
|
134
|
+
fontStyle: hasStep ? "normal" : "italic"
|
|
135
|
+
}, children: hasStep ? label : "No activity" }), isActive && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
136
|
+
position: "absolute",
|
|
137
|
+
right: "8px",
|
|
138
|
+
top: "50%",
|
|
139
|
+
transform: "translateY(-50%)",
|
|
140
|
+
width: "6px",
|
|
141
|
+
height: "6px",
|
|
142
|
+
borderRadius: "50%",
|
|
143
|
+
backgroundColor: "#6366f1",
|
|
144
|
+
animation: "pulse 2s infinite"
|
|
145
|
+
} }))] }, step));
|
|
146
|
+
}) }), (0, jsx_runtime_1.jsx)("style", { children: `
|
|
147
|
+
@keyframes pulse {
|
|
148
|
+
0% {
|
|
149
|
+
opacity: 1;
|
|
150
|
+
}
|
|
151
|
+
50% {
|
|
152
|
+
opacity: 0.5;
|
|
153
|
+
}
|
|
154
|
+
100% {
|
|
155
|
+
opacity: 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
` })] }));
|
|
159
|
+
};
|
|
160
|
+
exports.VerticalTimeline = VerticalTimeline;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useFlowData = exports.useApi = void 0;
|
|
4
|
+
var useApi_1 = require("./useApi");
|
|
5
|
+
Object.defineProperty(exports, "useApi", { enumerable: true, get: function () { return useApi_1.useApi; } });
|
|
6
|
+
var useFlowData_1 = require("./useFlowData");
|
|
7
|
+
Object.defineProperty(exports, "useFlowData", { enumerable: true, get: function () { return useFlowData_1.useFlowData; } });
|