ai-design-system 0.1.69 → 0.1.70
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/components/composites/DashboardChart/DashboardChart.tsx +107 -31
- package/components/features/EvalDashboardFeature/EvalDashboardFeature.tsx +16 -14
- package/components/features/EvalDashboardFeature/useEvalDashboardFeature.d.ts +7 -0
- package/components/features/NodeEditor/NodeEditor.tsx +25 -1
- package/dist/index.cjs +138 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +33 -23
- package/dist/index.js +139 -48
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import { Area,
|
|
2
|
+
import { Area, Line, ComposedChart, CartesianGrid, XAxis } from "recharts"
|
|
3
|
+
import type { TooltipContentProps } from "recharts"
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
ChartContainer,
|
|
@@ -70,21 +71,29 @@ export const DashboardChart = React.memo<DashboardChartProps>(({
|
|
|
70
71
|
)
|
|
71
72
|
|
|
72
73
|
const filteredSeries = React.useMemo(() => {
|
|
73
|
-
|
|
74
|
+
// 1. Sort ascending chronologically (oldest to newest)
|
|
75
|
+
const sortedSeries = [...series].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime())
|
|
76
|
+
|
|
77
|
+
const referenceDate = sortedSeries.length > 0 ? sortedSeries[sortedSeries.length - 1].date : new Date().toISOString()
|
|
74
78
|
let daysToSubtract = 90
|
|
75
79
|
if (timeRange === "30d") {
|
|
76
80
|
daysToSubtract = 30
|
|
77
81
|
} else if (timeRange === "7d") {
|
|
78
82
|
daysToSubtract = 7
|
|
79
|
-
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let filtered = sortedSeries;
|
|
86
|
+
if (timeRange === "10" || timeRange === "20" || timeRange === "30") {
|
|
80
87
|
// Special logic for count-based limits if passed as timeRange
|
|
81
88
|
const limit = parseInt(timeRange, 10)
|
|
82
|
-
|
|
89
|
+
filtered = sortedSeries.slice(-limit)
|
|
90
|
+
} else {
|
|
91
|
+
const startDate = new Date(referenceDate)
|
|
92
|
+
startDate.setDate(startDate.getDate() - daysToSubtract)
|
|
93
|
+
filtered = sortedSeries.filter(item => new Date(item.date) >= startDate)
|
|
83
94
|
}
|
|
84
95
|
|
|
85
|
-
|
|
86
|
-
startDate.setDate(startDate.getDate() - daysToSubtract)
|
|
87
|
-
return series.filter(item => new Date(item.date) >= startDate)
|
|
96
|
+
return filtered.map(item => ({ ...item, timestamp: new Date(item.date).getTime() }))
|
|
88
97
|
}, [series, timeRange])
|
|
89
98
|
|
|
90
99
|
return (
|
|
@@ -137,7 +146,7 @@ export const DashboardChart = React.memo<DashboardChartProps>(({
|
|
|
137
146
|
}}
|
|
138
147
|
className={cn("aspect-auto w-full", chartClassName || "h-[250px]")}
|
|
139
148
|
>
|
|
140
|
-
<
|
|
149
|
+
<ComposedChart data={filteredSeries}>
|
|
141
150
|
<defs>
|
|
142
151
|
<linearGradient id="fillDesktop" x1="0" y1="0" x2="0" y2="1">
|
|
143
152
|
<stop offset="5%" stopColor="var(--color-desktop)" stopOpacity={1} />
|
|
@@ -152,50 +161,117 @@ export const DashboardChart = React.memo<DashboardChartProps>(({
|
|
|
152
161
|
</defs>
|
|
153
162
|
<CartesianGrid vertical={false} />
|
|
154
163
|
<XAxis
|
|
155
|
-
dataKey="
|
|
164
|
+
dataKey="timestamp"
|
|
165
|
+
type="number"
|
|
166
|
+
scale="time"
|
|
167
|
+
domain={['dataMin', 'dataMax']}
|
|
156
168
|
tickLine={false}
|
|
157
169
|
axisLine={false}
|
|
158
170
|
tickMargin={8}
|
|
159
171
|
minTickGap={32}
|
|
160
172
|
tickFormatter={(value) => {
|
|
161
173
|
const date = new Date(value)
|
|
162
|
-
return date.
|
|
174
|
+
return date.toLocaleString("en-US", {
|
|
163
175
|
month: "short",
|
|
164
176
|
day: "numeric",
|
|
177
|
+
hour: "numeric",
|
|
178
|
+
minute: "2-digit"
|
|
165
179
|
})
|
|
166
180
|
}}
|
|
167
181
|
/>
|
|
168
182
|
<ChartTooltip
|
|
169
183
|
cursor={false}
|
|
170
|
-
content={
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
184
|
+
content={(props: TooltipContentProps) => {
|
|
185
|
+
const { active, payload, content: _content, label: _label, ...rest } = props;
|
|
186
|
+
if (!active || !payload?.length) return null;
|
|
187
|
+
|
|
188
|
+
const uniquePayload = payload.filter(
|
|
189
|
+
(item, index, self) =>
|
|
190
|
+
index === self.findIndex((t) => String(t.dataKey) === String(item.dataKey)),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<ChartTooltipContent
|
|
195
|
+
{...rest}
|
|
196
|
+
payload={uniquePayload}
|
|
197
|
+
labelFormatter={(value, tooltipPayload) => {
|
|
198
|
+
const typedPayload = tooltipPayload as Array<{ payload: { timestamp?: number } }>;
|
|
199
|
+
const timestamp = typedPayload?.[0]?.payload?.timestamp;
|
|
200
|
+
if (!timestamp) return null;
|
|
201
|
+
const date = new Date(timestamp);
|
|
202
|
+
if (isNaN(date.getTime())) return ""
|
|
203
|
+
return date.toLocaleDateString("en-US", {
|
|
204
|
+
month: "short",
|
|
205
|
+
year: "numeric",
|
|
206
|
+
})
|
|
207
|
+
}}
|
|
208
|
+
formatter={(value, name, item, index, tooltipPayload) => {
|
|
209
|
+
const typedPayload = tooltipPayload as { timestamp?: number };
|
|
210
|
+
const typedItem = item as { color?: string };
|
|
211
|
+
const labelText = name === "desktop" ? desktopLabel : (name === "mobile" ? mobileLabel : name);
|
|
212
|
+
const timeStr = typedPayload?.timestamp ? new Date(typedPayload.timestamp).toLocaleTimeString("en-US", {
|
|
213
|
+
hour: "numeric",
|
|
214
|
+
minute: "2-digit"
|
|
215
|
+
}) : null;
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div className="flex flex-col w-full">
|
|
219
|
+
<div className="flex w-full items-center gap-2">
|
|
220
|
+
<div
|
|
221
|
+
className="h-2.5 w-2.5 shrink-0 rounded-[2px]"
|
|
222
|
+
style={{ backgroundColor: typedItem.color }}
|
|
223
|
+
/>
|
|
224
|
+
<div className="flex flex-1 justify-between items-center gap-4">
|
|
225
|
+
<span className="text-muted-foreground">{labelText as React.ReactNode}</span>
|
|
226
|
+
<span className="font-mono font-medium tabular-nums text-foreground">{value as React.ReactNode}</span>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
{timeStr && (
|
|
230
|
+
<div className="text-[10px] text-muted-foreground self-end mt-0.5">
|
|
231
|
+
{timeStr}
|
|
232
|
+
</div>
|
|
233
|
+
)}
|
|
234
|
+
</div>
|
|
235
|
+
)
|
|
236
|
+
}}
|
|
237
|
+
indicator="dot"
|
|
238
|
+
/>
|
|
239
|
+
);
|
|
240
|
+
}}
|
|
181
241
|
/>
|
|
182
242
|
{showMobile && (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
243
|
+
<>
|
|
244
|
+
<Area
|
|
245
|
+
dataKey="mobile"
|
|
246
|
+
type="monotone"
|
|
247
|
+
fill="url(#fillMobile)"
|
|
248
|
+
stroke="none"
|
|
249
|
+
/>
|
|
250
|
+
<Line
|
|
251
|
+
dataKey="mobile"
|
|
252
|
+
type="monotone"
|
|
253
|
+
stroke="var(--color-mobile)"
|
|
254
|
+
strokeWidth={2}
|
|
255
|
+
dot={false}
|
|
256
|
+
activeDot={{ r: 4 }}
|
|
257
|
+
/>
|
|
258
|
+
</>
|
|
190
259
|
)}
|
|
191
260
|
<Area
|
|
192
261
|
dataKey="desktop"
|
|
193
|
-
type="
|
|
262
|
+
type="monotone"
|
|
194
263
|
fill="url(#fillDesktop)"
|
|
264
|
+
stroke="none"
|
|
265
|
+
/>
|
|
266
|
+
<Line
|
|
267
|
+
dataKey="desktop"
|
|
268
|
+
type="monotone"
|
|
195
269
|
stroke="var(--color-desktop)"
|
|
196
|
-
|
|
270
|
+
strokeWidth={2}
|
|
271
|
+
dot={false}
|
|
272
|
+
activeDot={{ r: 4 }}
|
|
197
273
|
/>
|
|
198
|
-
</
|
|
274
|
+
</ComposedChart>
|
|
199
275
|
</ChartContainer>
|
|
200
276
|
</CardContent>
|
|
201
277
|
</Card>
|
|
@@ -29,12 +29,13 @@ export const EvalDashboardFeature = React.memo<EvalDashboardFeatureProps>(
|
|
|
29
29
|
inbox.items.find(s => s.id === inbox.selectedItemId) || null
|
|
30
30
|
, [inbox.items, inbox.selectedItemId])
|
|
31
31
|
|
|
32
|
-
// Calculate average score for the trend section
|
|
32
|
+
// Calculate average score for the trend section (project-wide from runsHistory)
|
|
33
33
|
const avgScore = React.useMemo(() => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
const runs = data?.runsHistory || [];
|
|
35
|
+
if (runs.length === 0) return "0.0";
|
|
36
|
+
const sum = runs.reduce((acc, curr) => acc + curr.score, 0);
|
|
37
|
+
return (sum / runs.length).toFixed(1);
|
|
38
|
+
}, [data?.runsHistory]);
|
|
38
39
|
|
|
39
40
|
const inboxItems = React.useMemo(() => {
|
|
40
41
|
return inbox.items.map(session => ({
|
|
@@ -46,18 +47,19 @@ export const EvalDashboardFeature = React.memo<EvalDashboardFeatureProps>(
|
|
|
46
47
|
}, [inbox.items]);
|
|
47
48
|
|
|
48
49
|
const mockChartData = React.useMemo(() => {
|
|
50
|
+
const runs = data?.runsHistory || [];
|
|
49
51
|
// Sort items chronologically for the chart
|
|
50
|
-
const sortedItems = [...
|
|
52
|
+
const sortedItems = [...runs].sort(
|
|
51
53
|
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
|
52
54
|
)
|
|
53
55
|
|
|
54
|
-
return sortedItems.map(
|
|
55
|
-
date:
|
|
56
|
+
return sortedItems.map(run => ({
|
|
57
|
+
date: run.date,
|
|
56
58
|
// We map score to 'desktop' since DashboardChart is hardcoded for now
|
|
57
|
-
desktop:
|
|
59
|
+
desktop: run.score,
|
|
58
60
|
mobile: 0
|
|
59
61
|
}))
|
|
60
|
-
}, [
|
|
62
|
+
}, [data?.runsHistory]);
|
|
61
63
|
|
|
62
64
|
const sessionDetails = selectedSession ? {
|
|
63
65
|
id: selectedSession.id,
|
|
@@ -87,12 +89,12 @@ export const EvalDashboardFeature = React.memo<EvalDashboardFeatureProps>(
|
|
|
87
89
|
<DashboardChart
|
|
88
90
|
series={mockChartData}
|
|
89
91
|
title="Experiments Analysis"
|
|
90
|
-
description={`Average Score: ${avgScore}
|
|
92
|
+
description={`Average Score: ${avgScore} (per run)`}
|
|
91
93
|
shortDescription={`Avg: ${avgScore}`}
|
|
92
94
|
timeRanges={[
|
|
93
|
-
{ value: "10", label: "Last 10
|
|
94
|
-
{ value: "20", label: "Last 20
|
|
95
|
-
{ value: "30", label: "Last 30
|
|
95
|
+
{ value: "10", label: "Last 10 Runs", shortLabel: "Last 10" },
|
|
96
|
+
{ value: "20", label: "Last 20 Runs", shortLabel: "Last 20" },
|
|
97
|
+
{ value: "30", label: "Last 30 Runs", shortLabel: "Last 30" }
|
|
96
98
|
]}
|
|
97
99
|
desktopLabel="Score"
|
|
98
100
|
mobileLabel=""
|
|
@@ -28,6 +28,13 @@ export interface EvalDashboardFeatureData {
|
|
|
28
28
|
goldenEvals: GoldenEvalResult[];
|
|
29
29
|
systemPrompt: string;
|
|
30
30
|
outputTranscript: string;
|
|
31
|
+
runsHistory?: Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
session_id: string;
|
|
34
|
+
date: string;
|
|
35
|
+
score: number;
|
|
36
|
+
total: number;
|
|
37
|
+
}>;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
export interface EvalDashboardFeatureActionHandlers {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import { useMemo } from "react";
|
|
3
4
|
import { WorkflowToolbar, WorkflowToolbarActions } from "@/components/composites/WorkflowToolbar";
|
|
4
5
|
import { WorkflowCanvas } from "@/components/blocks/WorkflowCanvas";
|
|
5
6
|
import type { WorkflowNode, WorkflowEdge } from "@/components/blocks/WorkflowCanvas";
|
|
@@ -7,6 +8,13 @@ import type { ToolbarAction, WorkflowVersion } from "@/components/composites/Wor
|
|
|
7
8
|
import type { Connection, NodeChange, EdgeChange } from "@xyflow/react";
|
|
8
9
|
import { cn } from "@/lib/utils";
|
|
9
10
|
|
|
11
|
+
const GLOW: Record<string, string> = {
|
|
12
|
+
active: "0 0 14px 5px rgba(99, 102, 241, 0.9)",
|
|
13
|
+
pending: "0 0 14px 5px rgba(251, 146, 60, 1)",
|
|
14
|
+
done: "0 0 10px 3px rgba(34, 197, 94, 0.75)",
|
|
15
|
+
error: "0 0 14px 5px rgba(239, 68, 68, 0.9)",
|
|
16
|
+
};
|
|
17
|
+
|
|
10
18
|
export interface NodeEditorProps {
|
|
11
19
|
// Toolbar — left
|
|
12
20
|
workflowName?: string;
|
|
@@ -39,6 +47,9 @@ export interface NodeEditorProps {
|
|
|
39
47
|
interactive?: boolean;
|
|
40
48
|
hideDefaultActions?: boolean;
|
|
41
49
|
className?: string;
|
|
50
|
+
|
|
51
|
+
/** Per-node highlight states: { [nodeId]: 'active' | 'pending' | 'done' | 'error' } */
|
|
52
|
+
nodeHighlights?: Record<string, string>;
|
|
42
53
|
}
|
|
43
54
|
|
|
44
55
|
export function NodeEditor({
|
|
@@ -65,7 +76,20 @@ export function NodeEditor({
|
|
|
65
76
|
interactive = false,
|
|
66
77
|
hideDefaultActions = false,
|
|
67
78
|
className,
|
|
79
|
+
nodeHighlights,
|
|
68
80
|
}: NodeEditorProps) {
|
|
81
|
+
const highlightedNodes = useMemo(
|
|
82
|
+
() =>
|
|
83
|
+
nodes.map((n: WorkflowNode) => {
|
|
84
|
+
const glow = nodeHighlights?.[n.id];
|
|
85
|
+
if (!glow) return n;
|
|
86
|
+
return {
|
|
87
|
+
...n,
|
|
88
|
+
style: { ...(n.style ?? {}), boxShadow: GLOW[glow] },
|
|
89
|
+
};
|
|
90
|
+
}),
|
|
91
|
+
[nodes, nodeHighlights],
|
|
92
|
+
);
|
|
69
93
|
const defaultActionGroups: ToolbarAction[][] = [
|
|
70
94
|
[
|
|
71
95
|
{ id: "undo", icon: "undo-2", title: "Undo", onClick: onUndo, disabled: !canUndo },
|
|
@@ -87,7 +111,7 @@ export function NodeEditor({
|
|
|
87
111
|
className="h-full w-full"
|
|
88
112
|
edges={edges}
|
|
89
113
|
interactive={interactive}
|
|
90
|
-
nodes={
|
|
114
|
+
nodes={highlightedNodes}
|
|
91
115
|
showMinimap={showMinimap}
|
|
92
116
|
topLeft={
|
|
93
117
|
<WorkflowToolbar
|
package/dist/index.cjs
CHANGED
|
@@ -10927,19 +10927,24 @@ var DashboardChart = React3__namespace.memo(({
|
|
|
10927
10927
|
[onTimeRangeChange]
|
|
10928
10928
|
);
|
|
10929
10929
|
const filteredSeries = React3__namespace.useMemo(() => {
|
|
10930
|
-
const
|
|
10930
|
+
const sortedSeries = [...series].sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
|
|
10931
|
+
const referenceDate = sortedSeries.length > 0 ? sortedSeries[sortedSeries.length - 1].date : (/* @__PURE__ */ new Date()).toISOString();
|
|
10931
10932
|
let daysToSubtract = 90;
|
|
10932
10933
|
if (timeRange === "30d") {
|
|
10933
10934
|
daysToSubtract = 30;
|
|
10934
10935
|
} else if (timeRange === "7d") {
|
|
10935
10936
|
daysToSubtract = 7;
|
|
10936
|
-
}
|
|
10937
|
+
}
|
|
10938
|
+
let filtered = sortedSeries;
|
|
10939
|
+
if (timeRange === "10" || timeRange === "20" || timeRange === "30") {
|
|
10937
10940
|
const limit = parseInt(timeRange, 10);
|
|
10938
|
-
|
|
10941
|
+
filtered = sortedSeries.slice(-limit);
|
|
10942
|
+
} else {
|
|
10943
|
+
const startDate = new Date(referenceDate);
|
|
10944
|
+
startDate.setDate(startDate.getDate() - daysToSubtract);
|
|
10945
|
+
filtered = sortedSeries.filter((item) => new Date(item.date) >= startDate);
|
|
10939
10946
|
}
|
|
10940
|
-
|
|
10941
|
-
startDate.setDate(startDate.getDate() - daysToSubtract);
|
|
10942
|
-
return series.filter((item) => new Date(item.date) >= startDate);
|
|
10947
|
+
return filtered.map((item) => __spreadProps(__spreadValues({}, item), { timestamp: new Date(item.date).getTime() }));
|
|
10943
10948
|
}, [series, timeRange]);
|
|
10944
10949
|
return /* @__PURE__ */ jsxRuntime.jsx("section", { className: cn("px-4 lg:px-6 flex flex-col h-full", className), children: /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "@container/card flex flex-col flex-1 min-h-0 border-0 shadow-none bg-transparent", children: [
|
|
10945
10950
|
/* @__PURE__ */ jsxRuntime.jsxs(CardHeader2, { className: "shrink-0", children: [
|
|
@@ -10984,7 +10989,7 @@ var DashboardChart = React3__namespace.memo(({
|
|
|
10984
10989
|
desktop: { label: desktopLabel, color: "var(--primary)" }
|
|
10985
10990
|
}, showMobile ? { mobile: { label: mobileLabel, color: "var(--primary)" } } : {}),
|
|
10986
10991
|
className: cn("aspect-auto w-full", chartClassName || "h-[250px]"),
|
|
10987
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive.
|
|
10992
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive.ComposedChart, { data: filteredSeries, children: [
|
|
10988
10993
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
10989
10994
|
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "fillDesktop", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
10990
10995
|
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: "var(--color-desktop)", stopOpacity: 1 }),
|
|
@@ -10999,16 +11004,21 @@ var DashboardChart = React3__namespace.memo(({
|
|
|
10999
11004
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11000
11005
|
RechartsPrimitive.XAxis,
|
|
11001
11006
|
{
|
|
11002
|
-
dataKey: "
|
|
11007
|
+
dataKey: "timestamp",
|
|
11008
|
+
type: "number",
|
|
11009
|
+
scale: "time",
|
|
11010
|
+
domain: ["dataMin", "dataMax"],
|
|
11003
11011
|
tickLine: false,
|
|
11004
11012
|
axisLine: false,
|
|
11005
11013
|
tickMargin: 8,
|
|
11006
11014
|
minTickGap: 32,
|
|
11007
11015
|
tickFormatter: (value) => {
|
|
11008
11016
|
const date = new Date(value);
|
|
11009
|
-
return date.
|
|
11017
|
+
return date.toLocaleString("en-US", {
|
|
11010
11018
|
month: "short",
|
|
11011
|
-
day: "numeric"
|
|
11019
|
+
day: "numeric",
|
|
11020
|
+
hour: "numeric",
|
|
11021
|
+
minute: "2-digit"
|
|
11012
11022
|
});
|
|
11013
11023
|
}
|
|
11014
11024
|
}
|
|
@@ -11017,38 +11027,99 @@ var DashboardChart = React3__namespace.memo(({
|
|
|
11017
11027
|
ChartTooltip2,
|
|
11018
11028
|
{
|
|
11019
11029
|
cursor: false,
|
|
11020
|
-
content:
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
},
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11030
|
+
content: (props) => {
|
|
11031
|
+
const _a2 = props, { active, payload, content: _content, label: _label } = _a2, rest = __objRest(_a2, ["active", "payload", "content", "label"]);
|
|
11032
|
+
if (!active || !(payload == null ? void 0 : payload.length)) return null;
|
|
11033
|
+
const uniquePayload = payload.filter(
|
|
11034
|
+
(item, index, self) => index === self.findIndex((t) => String(t.dataKey) === String(item.dataKey))
|
|
11035
|
+
);
|
|
11036
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
11037
|
+
ChartTooltipContent2,
|
|
11038
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
11039
|
+
payload: uniquePayload,
|
|
11040
|
+
labelFormatter: (value, tooltipPayload) => {
|
|
11041
|
+
var _a3, _b2;
|
|
11042
|
+
const typedPayload = tooltipPayload;
|
|
11043
|
+
const timestamp = (_b2 = (_a3 = typedPayload == null ? void 0 : typedPayload[0]) == null ? void 0 : _a3.payload) == null ? void 0 : _b2.timestamp;
|
|
11044
|
+
if (!timestamp) return null;
|
|
11045
|
+
const date = new Date(timestamp);
|
|
11046
|
+
if (isNaN(date.getTime())) return "";
|
|
11047
|
+
return date.toLocaleDateString("en-US", {
|
|
11048
|
+
month: "short",
|
|
11049
|
+
year: "numeric"
|
|
11050
|
+
});
|
|
11051
|
+
},
|
|
11052
|
+
formatter: (value, name, item, index, tooltipPayload) => {
|
|
11053
|
+
const typedPayload = tooltipPayload;
|
|
11054
|
+
const typedItem = item;
|
|
11055
|
+
const labelText = name === "desktop" ? desktopLabel : name === "mobile" ? mobileLabel : name;
|
|
11056
|
+
const timeStr = (typedPayload == null ? void 0 : typedPayload.timestamp) ? new Date(typedPayload.timestamp).toLocaleTimeString("en-US", {
|
|
11057
|
+
hour: "numeric",
|
|
11058
|
+
minute: "2-digit"
|
|
11059
|
+
}) : null;
|
|
11060
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col w-full", children: [
|
|
11061
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2", children: [
|
|
11062
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11063
|
+
"div",
|
|
11064
|
+
{
|
|
11065
|
+
className: "h-2.5 w-2.5 shrink-0 rounded-[2px]",
|
|
11066
|
+
style: { backgroundColor: typedItem.color }
|
|
11067
|
+
}
|
|
11068
|
+
),
|
|
11069
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 justify-between items-center gap-4", children: [
|
|
11070
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: labelText }),
|
|
11071
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono font-medium tabular-nums text-foreground", children: value })
|
|
11072
|
+
] })
|
|
11073
|
+
] }),
|
|
11074
|
+
timeStr && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-muted-foreground self-end mt-0.5", children: timeStr })
|
|
11075
|
+
] });
|
|
11076
|
+
},
|
|
11077
|
+
indicator: "dot"
|
|
11078
|
+
})
|
|
11079
|
+
);
|
|
11080
|
+
}
|
|
11032
11081
|
}
|
|
11033
11082
|
),
|
|
11034
|
-
showMobile && /* @__PURE__ */ jsxRuntime.
|
|
11083
|
+
showMobile && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11084
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11085
|
+
RechartsPrimitive.Area,
|
|
11086
|
+
{
|
|
11087
|
+
dataKey: "mobile",
|
|
11088
|
+
type: "monotone",
|
|
11089
|
+
fill: "url(#fillMobile)",
|
|
11090
|
+
stroke: "none"
|
|
11091
|
+
}
|
|
11092
|
+
),
|
|
11093
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11094
|
+
RechartsPrimitive.Line,
|
|
11095
|
+
{
|
|
11096
|
+
dataKey: "mobile",
|
|
11097
|
+
type: "monotone",
|
|
11098
|
+
stroke: "var(--color-mobile)",
|
|
11099
|
+
strokeWidth: 2,
|
|
11100
|
+
dot: false,
|
|
11101
|
+
activeDot: { r: 4 }
|
|
11102
|
+
}
|
|
11103
|
+
)
|
|
11104
|
+
] }),
|
|
11105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11035
11106
|
RechartsPrimitive.Area,
|
|
11036
11107
|
{
|
|
11037
|
-
dataKey: "
|
|
11038
|
-
type: "
|
|
11039
|
-
fill: "url(#
|
|
11040
|
-
stroke: "
|
|
11041
|
-
stackId: "a"
|
|
11108
|
+
dataKey: "desktop",
|
|
11109
|
+
type: "monotone",
|
|
11110
|
+
fill: "url(#fillDesktop)",
|
|
11111
|
+
stroke: "none"
|
|
11042
11112
|
}
|
|
11043
11113
|
),
|
|
11044
11114
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11045
|
-
RechartsPrimitive.
|
|
11115
|
+
RechartsPrimitive.Line,
|
|
11046
11116
|
{
|
|
11047
11117
|
dataKey: "desktop",
|
|
11048
|
-
type: "
|
|
11049
|
-
fill: "url(#fillDesktop)",
|
|
11118
|
+
type: "monotone",
|
|
11050
11119
|
stroke: "var(--color-desktop)",
|
|
11051
|
-
|
|
11120
|
+
strokeWidth: 2,
|
|
11121
|
+
dot: false,
|
|
11122
|
+
activeDot: { r: 4 }
|
|
11052
11123
|
}
|
|
11053
11124
|
)
|
|
11054
11125
|
] })
|
|
@@ -11420,6 +11491,12 @@ async function getLayoutedElements(nodes, edges) {
|
|
|
11420
11491
|
}));
|
|
11421
11492
|
return { nodes: layoutedNodes, edges: layoutedEdges };
|
|
11422
11493
|
}
|
|
11494
|
+
var GLOW = {
|
|
11495
|
+
active: "0 0 14px 5px rgba(99, 102, 241, 0.9)",
|
|
11496
|
+
pending: "0 0 14px 5px rgba(251, 146, 60, 1)",
|
|
11497
|
+
done: "0 0 10px 3px rgba(34, 197, 94, 0.75)",
|
|
11498
|
+
error: "0 0 14px 5px rgba(239, 68, 68, 0.9)"
|
|
11499
|
+
};
|
|
11423
11500
|
function NodeEditor({
|
|
11424
11501
|
workflowName,
|
|
11425
11502
|
versions,
|
|
@@ -11443,8 +11520,20 @@ function NodeEditor({
|
|
|
11443
11520
|
showMinimap,
|
|
11444
11521
|
interactive = false,
|
|
11445
11522
|
hideDefaultActions = false,
|
|
11446
|
-
className
|
|
11523
|
+
className,
|
|
11524
|
+
nodeHighlights
|
|
11447
11525
|
}) {
|
|
11526
|
+
const highlightedNodes = React3.useMemo(
|
|
11527
|
+
() => nodes.map((n) => {
|
|
11528
|
+
var _a;
|
|
11529
|
+
const glow = nodeHighlights == null ? void 0 : nodeHighlights[n.id];
|
|
11530
|
+
if (!glow) return n;
|
|
11531
|
+
return __spreadProps(__spreadValues({}, n), {
|
|
11532
|
+
style: __spreadProps(__spreadValues({}, (_a = n.style) != null ? _a : {}), { boxShadow: GLOW[glow] })
|
|
11533
|
+
});
|
|
11534
|
+
}),
|
|
11535
|
+
[nodes, nodeHighlights]
|
|
11536
|
+
);
|
|
11448
11537
|
const defaultActionGroups = [
|
|
11449
11538
|
[
|
|
11450
11539
|
{ id: "undo", icon: "undo-2", title: "Undo", onClick: onUndo, disabled: !canUndo },
|
|
@@ -11466,7 +11555,7 @@ function NodeEditor({
|
|
|
11466
11555
|
className: "h-full w-full",
|
|
11467
11556
|
edges,
|
|
11468
11557
|
interactive,
|
|
11469
|
-
nodes,
|
|
11558
|
+
nodes: highlightedNodes,
|
|
11470
11559
|
showMinimap,
|
|
11471
11560
|
topLeft: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11472
11561
|
WorkflowToolbar,
|
|
@@ -13069,10 +13158,11 @@ var EvalDashboardFeature = React3__namespace.memo(
|
|
|
13069
13158
|
[inbox.items, inbox.selectedItemId]
|
|
13070
13159
|
);
|
|
13071
13160
|
const avgScore = React3__namespace.useMemo(() => {
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13161
|
+
const runs = (data == null ? void 0 : data.runsHistory) || [];
|
|
13162
|
+
if (runs.length === 0) return "0.0";
|
|
13163
|
+
const sum = runs.reduce((acc, curr) => acc + curr.score, 0);
|
|
13164
|
+
return (sum / runs.length).toFixed(1);
|
|
13165
|
+
}, [data == null ? void 0 : data.runsHistory]);
|
|
13076
13166
|
const inboxItems = React3__namespace.useMemo(() => {
|
|
13077
13167
|
return inbox.items.map((session) => ({
|
|
13078
13168
|
id: session.id,
|
|
@@ -13082,16 +13172,17 @@ var EvalDashboardFeature = React3__namespace.memo(
|
|
|
13082
13172
|
}));
|
|
13083
13173
|
}, [inbox.items]);
|
|
13084
13174
|
const mockChartData = React3__namespace.useMemo(() => {
|
|
13085
|
-
const
|
|
13175
|
+
const runs = (data == null ? void 0 : data.runsHistory) || [];
|
|
13176
|
+
const sortedItems = [...runs].sort(
|
|
13086
13177
|
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
|
|
13087
13178
|
);
|
|
13088
|
-
return sortedItems.map((
|
|
13089
|
-
date:
|
|
13179
|
+
return sortedItems.map((run) => ({
|
|
13180
|
+
date: run.date,
|
|
13090
13181
|
// We map score to 'desktop' since DashboardChart is hardcoded for now
|
|
13091
|
-
desktop:
|
|
13182
|
+
desktop: run.score,
|
|
13092
13183
|
mobile: 0
|
|
13093
13184
|
}));
|
|
13094
|
-
}, [
|
|
13185
|
+
}, [data == null ? void 0 : data.runsHistory]);
|
|
13095
13186
|
const sessionDetails = selectedSession ? {
|
|
13096
13187
|
id: selectedSession.id,
|
|
13097
13188
|
date: selectedSession.date,
|
|
@@ -13119,12 +13210,12 @@ var EvalDashboardFeature = React3__namespace.memo(
|
|
|
13119
13210
|
{
|
|
13120
13211
|
series: mockChartData,
|
|
13121
13212
|
title: "Experiments Analysis",
|
|
13122
|
-
description: `Average Score: ${avgScore}
|
|
13213
|
+
description: `Average Score: ${avgScore} (per run)`,
|
|
13123
13214
|
shortDescription: `Avg: ${avgScore}`,
|
|
13124
13215
|
timeRanges: [
|
|
13125
|
-
{ value: "10", label: "Last 10
|
|
13126
|
-
{ value: "20", label: "Last 20
|
|
13127
|
-
{ value: "30", label: "Last 30
|
|
13216
|
+
{ value: "10", label: "Last 10 Runs", shortLabel: "Last 10" },
|
|
13217
|
+
{ value: "20", label: "Last 20 Runs", shortLabel: "Last 20" },
|
|
13218
|
+
{ value: "30", label: "Last 30 Runs", shortLabel: "Last 30" }
|
|
13128
13219
|
],
|
|
13129
13220
|
desktopLabel: "Score",
|
|
13130
13221
|
mobileLabel: "",
|