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.
@@ -1,5 +1,6 @@
1
1
  import * as React from "react"
2
- import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
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
- const referenceDate = series.length > 0 ? series[series.length - 1].date : new Date().toISOString()
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
- } else if (timeRange === "10" || timeRange === "20" || timeRange === "30") {
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
- return series.slice(-limit)
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
- const startDate = new Date(referenceDate)
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
- <AreaChart data={filteredSeries}>
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="date"
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.toLocaleDateString("en-US", {
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
- <ChartTooltipContent
172
- labelFormatter={(value) => {
173
- return new Date(String(value)).toLocaleDateString("en-US", {
174
- month: "short",
175
- day: "numeric",
176
- })
177
- }}
178
- indicator="dot"
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
- <Area
184
- dataKey="mobile"
185
- type="natural"
186
- fill="url(#fillMobile)"
187
- stroke="var(--color-mobile)"
188
- stackId="a"
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="natural"
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
- stackId="a"
270
+ strokeWidth={2}
271
+ dot={false}
272
+ activeDot={{ r: 4 }}
197
273
  />
198
- </AreaChart>
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
- if (inbox.items.length === 0) return "0.0";
35
- const sum = inbox.items.reduce((acc, curr) => acc + curr.score, 0);
36
- return (sum / inbox.items.length).toFixed(1);
37
- }, [inbox.items]);
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 = [...inbox.items].sort(
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(session => ({
55
- date: session.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: session.score,
59
+ desktop: run.score,
58
60
  mobile: 0
59
61
  }))
60
- }, [inbox.items]);
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} / 41`}
92
+ description={`Average Score: ${avgScore} (per run)`}
91
93
  shortDescription={`Avg: ${avgScore}`}
92
94
  timeRanges={[
93
- { value: "10", label: "Last 10 Sessions", shortLabel: "Last 10" },
94
- { value: "20", label: "Last 20 Sessions", shortLabel: "Last 20" },
95
- { value: "30", label: "Last 30 Sessions", shortLabel: "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={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 referenceDate = series.length > 0 ? series[series.length - 1].date : (/* @__PURE__ */ new Date()).toISOString();
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
- } else if (timeRange === "10" || timeRange === "20" || timeRange === "30") {
10937
+ }
10938
+ let filtered = sortedSeries;
10939
+ if (timeRange === "10" || timeRange === "20" || timeRange === "30") {
10937
10940
  const limit = parseInt(timeRange, 10);
10938
- return series.slice(-limit);
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
- const startDate = new Date(referenceDate);
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.AreaChart, { data: filteredSeries, children: [
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: "date",
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.toLocaleDateString("en-US", {
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: /* @__PURE__ */ jsxRuntime.jsx(
11021
- ChartTooltipContent2,
11022
- {
11023
- labelFormatter: (value) => {
11024
- return new Date(String(value)).toLocaleDateString("en-US", {
11025
- month: "short",
11026
- day: "numeric"
11027
- });
11028
- },
11029
- indicator: "dot"
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.jsx(
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: "mobile",
11038
- type: "natural",
11039
- fill: "url(#fillMobile)",
11040
- stroke: "var(--color-mobile)",
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.Area,
11115
+ RechartsPrimitive.Line,
11046
11116
  {
11047
11117
  dataKey: "desktop",
11048
- type: "natural",
11049
- fill: "url(#fillDesktop)",
11118
+ type: "monotone",
11050
11119
  stroke: "var(--color-desktop)",
11051
- stackId: "a"
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
- if (inbox.items.length === 0) return "0.0";
13073
- const sum = inbox.items.reduce((acc, curr) => acc + curr.score, 0);
13074
- return (sum / inbox.items.length).toFixed(1);
13075
- }, [inbox.items]);
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 sortedItems = [...inbox.items].sort(
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((session) => ({
13089
- date: session.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: session.score,
13182
+ desktop: run.score,
13092
13183
  mobile: 0
13093
13184
  }));
13094
- }, [inbox.items]);
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} / 41`,
13213
+ description: `Average Score: ${avgScore} (per run)`,
13123
13214
  shortDescription: `Avg: ${avgScore}`,
13124
13215
  timeRanges: [
13125
- { value: "10", label: "Last 10 Sessions", shortLabel: "Last 10" },
13126
- { value: "20", label: "Last 20 Sessions", shortLabel: "Last 20" },
13127
- { value: "30", label: "Last 30 Sessions", shortLabel: "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: "",