@tangle-network/sandbox-ui 0.2.2 → 0.3.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.
Files changed (70) hide show
  1. package/README.md +201 -10
  2. package/dist/auth.js +2 -2
  3. package/dist/chat-container-C8eHLw8z.d.ts +67 -0
  4. package/dist/chat.d.ts +70 -78
  5. package/dist/chat.js +8 -8
  6. package/dist/chunk-4F2GJRGU.js +756 -0
  7. package/dist/{chunk-HYEAX3DC.js → chunk-5LV6DZZF.js} +445 -114
  8. package/dist/{chunk-QSQBDR3N.js → chunk-BX6AQMUS.js} +5 -2
  9. package/dist/chunk-CCKNIAS7.js +124 -0
  10. package/dist/chunk-CJ2RYVZH.js +128 -0
  11. package/dist/{chunk-KMXV7DDX.js → chunk-CNWVHQFY.js} +1 -1
  12. package/dist/{chunk-OU4TRNQZ.js → chunk-COCSO7FG.js} +3 -3
  13. package/dist/chunk-FJSVPBKY.js +85 -0
  14. package/dist/chunk-FRGMMANX.js +102 -0
  15. package/dist/{chunk-E6FS7R4X.js → chunk-HWLX5NME.js} +1 -1
  16. package/dist/chunk-HY5IBRCE.js +1171 -0
  17. package/dist/chunk-JF6E2DS5.js +610 -0
  18. package/dist/chunk-MUOL44AE.js +121 -0
  19. package/dist/chunk-MXCSSOGH.js +105 -0
  20. package/dist/{chunk-NI2EI43H.js → chunk-PDV7W4NY.js} +9 -124
  21. package/dist/chunk-QGI5E7JD.js +1106 -0
  22. package/dist/chunk-TQN3VR4F.js +92 -0
  23. package/dist/{chunk-SOT2V7TX.js → chunk-TXI4MZAZ.js} +62 -144
  24. package/dist/chunk-WUR652Y3.js +1140 -0
  25. package/dist/chunk-YDBXQQLC.js +336 -0
  26. package/dist/{chunk-4EIWPJMJ.js → chunk-ZP6GSX4D.js} +36 -27
  27. package/dist/dashboard.d.ts +4 -111
  28. package/dist/dashboard.js +17 -4
  29. package/dist/{expanded-tool-detail-OkXGqTHe.d.ts → expanded-tool-detail-BDi_h_dZ.d.ts} +11 -4
  30. package/dist/file-tabs-CmaoDVBI.d.ts +72 -0
  31. package/dist/files.d.ts +25 -44
  32. package/dist/files.js +8 -3
  33. package/{src/styles → dist}/globals.css +16 -67
  34. package/dist/hooks.d.ts +5 -4
  35. package/dist/hooks.js +14 -9
  36. package/dist/index-BOjBJwzD.d.ts +219 -0
  37. package/dist/index.d.ts +39 -10
  38. package/dist/index.js +190 -121
  39. package/dist/markdown.d.ts +1 -24
  40. package/dist/markdown.js +1 -7
  41. package/dist/openui.d.ts +115 -0
  42. package/dist/openui.js +11 -0
  43. package/dist/pages.d.ts +3 -2
  44. package/dist/pages.js +19 -16
  45. package/dist/primitives.js +25 -19
  46. package/dist/run.d.ts +2 -2
  47. package/dist/run.js +8 -7
  48. package/dist/{use-sidecar-auth-Bb0-w3lX.d.ts → sdk-hooks.d.ts} +61 -72
  49. package/dist/sdk-hooks.js +29 -0
  50. package/dist/styles.css +179 -0
  51. package/dist/tokens.css +275 -0
  52. package/dist/{tool-display-BvsVW_Ur.d.ts → tool-display-Ct9nFAzJ.d.ts} +1 -1
  53. package/dist/types.d.ts +1 -1
  54. package/dist/{usage-chart-DINgSVL5.d.ts → usage-chart-CY9xo3KX.d.ts} +8 -3
  55. package/dist/use-pty-session-DeZSxOCN.d.ts +69 -0
  56. package/dist/utils.d.ts +1 -1
  57. package/dist/utils.js +1 -1
  58. package/dist/workspace.d.ts +171 -33
  59. package/dist/workspace.js +25 -1
  60. package/package.json +10 -3
  61. package/tailwind.config.cjs +39 -0
  62. package/dist/chunk-2UHPE5T7.js +0 -201
  63. package/dist/chunk-6MQIDUPA.js +0 -502
  64. package/dist/chunk-J4OADEUK.js +0 -814
  65. package/dist/chunk-KYY2X6LY.js +0 -318
  66. package/dist/chunk-L6ZDH5F4.js +0 -334
  67. package/dist/chunk-M34OA6PQ.js +0 -233
  68. package/dist/chunk-M6VLC32S.js +0 -219
  69. package/dist/chunk-U62G5TS7.js +0 -472
  70. package/src/styles/tokens.css +0 -73
@@ -1,814 +0,0 @@
1
- import {
2
- Logo
3
- } from "./chunk-OKCIKTXQ.js";
4
- import {
5
- DropdownMenu,
6
- DropdownMenuContent,
7
- DropdownMenuItem,
8
- DropdownMenuLabel,
9
- DropdownMenuSeparator,
10
- DropdownMenuTrigger
11
- } from "./chunk-MCGKDCOR.js";
12
- import {
13
- Badge,
14
- Skeleton
15
- } from "./chunk-2UHPE5T7.js";
16
- import {
17
- Button
18
- } from "./chunk-E6FS7R4X.js";
19
- import {
20
- cn
21
- } from "./chunk-RQHJBTEU.js";
22
-
23
- // src/primitives/theme-toggle.tsx
24
- import { useCallback, useEffect, useState } from "react";
25
- import { jsx, jsxs } from "react/jsx-runtime";
26
- function getSystemTheme() {
27
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
28
- }
29
- function applyTheme(theme) {
30
- const resolved = theme === "system" ? getSystemTheme() : theme;
31
- document.documentElement.classList.toggle("dark", resolved === "dark");
32
- }
33
- function useTheme() {
34
- const [theme, setThemeState] = useState(() => {
35
- if (typeof window === "undefined") return "system";
36
- return localStorage.getItem("theme") ?? "system";
37
- });
38
- const setTheme = useCallback((next) => {
39
- setThemeState(next);
40
- if (next === "system") {
41
- localStorage.removeItem("theme");
42
- } else {
43
- localStorage.setItem("theme", next);
44
- }
45
- applyTheme(next);
46
- }, []);
47
- useEffect(() => {
48
- applyTheme(theme);
49
- if (theme !== "system") return;
50
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
51
- const handler = () => applyTheme("system");
52
- mq.addEventListener("change", handler);
53
- return () => mq.removeEventListener("change", handler);
54
- }, [theme]);
55
- return { theme, setTheme };
56
- }
57
- var iconClass = "h-4 w-4";
58
- function SunIcon() {
59
- return /* @__PURE__ */ jsxs(
60
- "svg",
61
- {
62
- xmlns: "http://www.w3.org/2000/svg",
63
- viewBox: "0 0 24 24",
64
- fill: "none",
65
- stroke: "currentColor",
66
- strokeWidth: 2,
67
- strokeLinecap: "round",
68
- strokeLinejoin: "round",
69
- className: iconClass,
70
- children: [
71
- /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 5 }),
72
- /* @__PURE__ */ jsx("path", { d: "M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" })
73
- ]
74
- }
75
- );
76
- }
77
- function MoonIcon() {
78
- return /* @__PURE__ */ jsx(
79
- "svg",
80
- {
81
- xmlns: "http://www.w3.org/2000/svg",
82
- viewBox: "0 0 24 24",
83
- fill: "none",
84
- stroke: "currentColor",
85
- strokeWidth: 2,
86
- strokeLinecap: "round",
87
- strokeLinejoin: "round",
88
- className: iconClass,
89
- children: /* @__PURE__ */ jsx("path", { d: "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" })
90
- }
91
- );
92
- }
93
- function ThemeToggle() {
94
- const { theme, setTheme } = useTheme();
95
- const resolved = theme === "system" ? getSystemTheme() : theme;
96
- return /* @__PURE__ */ jsx(
97
- "button",
98
- {
99
- type: "button",
100
- onClick: () => setTheme(resolved === "dark" ? "light" : "dark"),
101
- className: "inline-flex items-center justify-center rounded-md p-2 text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors",
102
- "aria-label": `Switch to ${resolved === "dark" ? "light" : "dark"} mode`,
103
- children: resolved === "dark" ? /* @__PURE__ */ jsx(SunIcon, {}) : /* @__PURE__ */ jsx(MoonIcon, {})
104
- }
105
- );
106
- }
107
-
108
- // src/dashboard/dashboard-layout.tsx
109
- import * as React from "react";
110
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
111
- var variantStyles = {
112
- sandbox: {
113
- activeNav: "bg-purple-500/10 text-purple-400",
114
- userGradient: "from-purple-500 to-violet-500"
115
- }
116
- };
117
- function DefaultLink({
118
- href,
119
- to,
120
- className,
121
- children,
122
- ...rest
123
- }) {
124
- return /* @__PURE__ */ jsx2("a", { href: href ?? to, className, ...rest, children });
125
- }
126
- function UserIcon({ className }) {
127
- return /* @__PURE__ */ jsxs2(
128
- "svg",
129
- {
130
- xmlns: "http://www.w3.org/2000/svg",
131
- viewBox: "0 0 24 24",
132
- fill: "none",
133
- stroke: "currentColor",
134
- strokeWidth: "2",
135
- strokeLinecap: "round",
136
- strokeLinejoin: "round",
137
- className,
138
- children: [
139
- /* @__PURE__ */ jsx2("title", { children: "User icon" }),
140
- /* @__PURE__ */ jsx2("path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" }),
141
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "7", r: "4" })
142
- ]
143
- }
144
- );
145
- }
146
- function SettingsIcon({ className }) {
147
- return /* @__PURE__ */ jsxs2(
148
- "svg",
149
- {
150
- xmlns: "http://www.w3.org/2000/svg",
151
- viewBox: "0 0 24 24",
152
- fill: "none",
153
- stroke: "currentColor",
154
- strokeWidth: "2",
155
- strokeLinecap: "round",
156
- strokeLinejoin: "round",
157
- className,
158
- children: [
159
- /* @__PURE__ */ jsx2("title", { children: "Settings icon" }),
160
- /* @__PURE__ */ jsx2("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
161
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "3" })
162
- ]
163
- }
164
- );
165
- }
166
- function LogOutIcon({ className }) {
167
- return /* @__PURE__ */ jsxs2(
168
- "svg",
169
- {
170
- xmlns: "http://www.w3.org/2000/svg",
171
- viewBox: "0 0 24 24",
172
- fill: "none",
173
- stroke: "currentColor",
174
- strokeWidth: "2",
175
- strokeLinecap: "round",
176
- strokeLinejoin: "round",
177
- className,
178
- children: [
179
- /* @__PURE__ */ jsx2("title", { children: "Log out icon" }),
180
- /* @__PURE__ */ jsx2("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
181
- /* @__PURE__ */ jsx2("polyline", { points: "16,17 21,12 16,7" }),
182
- /* @__PURE__ */ jsx2("line", { x1: "21", x2: "9", y1: "12", y2: "12" })
183
- ]
184
- }
185
- );
186
- }
187
- function ChevronRightIcon({ className }) {
188
- return /* @__PURE__ */ jsxs2(
189
- "svg",
190
- {
191
- xmlns: "http://www.w3.org/2000/svg",
192
- viewBox: "0 0 24 24",
193
- fill: "none",
194
- stroke: "currentColor",
195
- strokeWidth: "2",
196
- strokeLinecap: "round",
197
- strokeLinejoin: "round",
198
- className,
199
- children: [
200
- /* @__PURE__ */ jsx2("title", { children: "Chevron right icon" }),
201
- /* @__PURE__ */ jsx2("path", { d: "m9 18 6-6-6-6" })
202
- ]
203
- }
204
- );
205
- }
206
- function MenuIcon({ className }) {
207
- return /* @__PURE__ */ jsxs2(
208
- "svg",
209
- {
210
- xmlns: "http://www.w3.org/2000/svg",
211
- viewBox: "0 0 24 24",
212
- fill: "none",
213
- stroke: "currentColor",
214
- strokeWidth: "2",
215
- strokeLinecap: "round",
216
- strokeLinejoin: "round",
217
- className,
218
- children: [
219
- /* @__PURE__ */ jsx2("title", { children: "Menu icon" }),
220
- /* @__PURE__ */ jsx2("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
221
- /* @__PURE__ */ jsx2("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
222
- /* @__PURE__ */ jsx2("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
223
- ]
224
- }
225
- );
226
- }
227
- function XIcon({ className }) {
228
- return /* @__PURE__ */ jsxs2(
229
- "svg",
230
- {
231
- xmlns: "http://www.w3.org/2000/svg",
232
- viewBox: "0 0 24 24",
233
- fill: "none",
234
- stroke: "currentColor",
235
- strokeWidth: "2",
236
- strokeLinecap: "round",
237
- strokeLinejoin: "round",
238
- className,
239
- children: [
240
- /* @__PURE__ */ jsx2("title", { children: "Close icon" }),
241
- /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18" }),
242
- /* @__PURE__ */ jsx2("path", { d: "m6 6 12 12" })
243
- ]
244
- }
245
- );
246
- }
247
- function DashboardLayout({
248
- children,
249
- variant = "sandbox",
250
- navItems,
251
- activeNavId,
252
- user,
253
- isLoading = false,
254
- onLogout,
255
- onSettingsClick,
256
- settingsHref = "/dashboard/settings",
257
- LinkComponent = DefaultLink
258
- }) {
259
- const styles = variantStyles[variant];
260
- const Link = LinkComponent;
261
- const [mobileMenuOpen, setMobileMenuOpen] = React.useState(false);
262
- const handleNavClick = () => {
263
- setMobileMenuOpen(false);
264
- };
265
- const SidebarContent = () => /* @__PURE__ */ jsxs2(Fragment, { children: [
266
- /* @__PURE__ */ jsx2("div", { className: "border-border border-b p-6", children: /* @__PURE__ */ jsx2(Logo, { variant, size: "md" }) }),
267
- /* @__PURE__ */ jsx2("nav", { className: "flex-1 space-y-1 p-4", "aria-label": "Main navigation", children: navItems.map((item) => {
268
- const Icon = item.icon;
269
- const isActive = activeNavId === item.id;
270
- return /* @__PURE__ */ jsxs2(
271
- Link,
272
- {
273
- href: item.href,
274
- to: item.href,
275
- onClick: handleNavClick,
276
- "aria-current": isActive ? "page" : void 0,
277
- className: cn(
278
- "flex items-center gap-3 rounded-lg px-4 py-2.5 transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-background",
279
- isActive ? styles.activeNav : "text-muted-foreground hover:bg-accent hover:text-foreground"
280
- ),
281
- children: [
282
- /* @__PURE__ */ jsx2(Icon, { className: "h-5 w-5", "aria-hidden": "true" }),
283
- /* @__PURE__ */ jsx2("span", { className: "font-medium", children: item.label })
284
- ]
285
- },
286
- item.id
287
- );
288
- }) }),
289
- /* @__PURE__ */ jsxs2("div", { className: "border-border border-t p-4", children: [
290
- /* @__PURE__ */ jsx2("div", { className: "mb-2 flex justify-end", children: /* @__PURE__ */ jsx2(ThemeToggle, {}) }),
291
- /* @__PURE__ */ jsxs2(DropdownMenu, { children: [
292
- /* @__PURE__ */ jsx2(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
293
- "button",
294
- {
295
- type: "button",
296
- className: "flex w-full items-center gap-3 rounded-lg p-3 transition-colors hover:bg-accent focus:outline-none focus:ring-2 focus:ring-offset-2",
297
- "aria-label": "User menu",
298
- children: [
299
- /* @__PURE__ */ jsx2(
300
- "div",
301
- {
302
- className: cn(
303
- "flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-r",
304
- styles.userGradient
305
- ),
306
- children: /* @__PURE__ */ jsx2(UserIcon, { className: "h-4 w-4 text-white", "aria-hidden": "true" })
307
- }
308
- ),
309
- /* @__PURE__ */ jsx2("div", { className: "flex-1 text-left", children: isLoading ? /* @__PURE__ */ jsxs2(Fragment, { children: [
310
- /* @__PURE__ */ jsx2(Skeleton, { className: "mb-1 h-4 w-24" }),
311
- /* @__PURE__ */ jsx2(Skeleton, { className: "h-3 w-16" })
312
- ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
313
- /* @__PURE__ */ jsx2("p", { className: "truncate font-medium text-sm", children: user?.email ?? "Not logged in" }),
314
- /* @__PURE__ */ jsxs2("p", { className: "text-muted-foreground text-xs capitalize", children: [
315
- user?.tier ?? "Free",
316
- " Plan"
317
- ] })
318
- ] }) }),
319
- /* @__PURE__ */ jsx2(
320
- ChevronRightIcon,
321
- {
322
- className: "h-4 w-4 text-muted-foreground",
323
- "aria-hidden": "true"
324
- }
325
- )
326
- ]
327
- }
328
- ) }),
329
- /* @__PURE__ */ jsxs2(DropdownMenuContent, { align: "end", className: "w-56", children: [
330
- /* @__PURE__ */ jsx2(DropdownMenuLabel, { children: "My Account" }),
331
- /* @__PURE__ */ jsx2(DropdownMenuSeparator, {}),
332
- onSettingsClick ? /* @__PURE__ */ jsxs2(DropdownMenuItem, { onClick: onSettingsClick, children: [
333
- /* @__PURE__ */ jsx2(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
334
- "Settings"
335
- ] }) : /* @__PURE__ */ jsx2(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs2(Link, { href: settingsHref, to: settingsHref, className: "flex items-center", children: [
336
- /* @__PURE__ */ jsx2(SettingsIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
337
- "Settings"
338
- ] }) }),
339
- onLogout && /* @__PURE__ */ jsxs2(DropdownMenuItem, { className: "text-red-400", onClick: onLogout, children: [
340
- /* @__PURE__ */ jsx2(LogOutIcon, { className: "mr-2 h-4 w-4", "aria-hidden": "true" }),
341
- "Sign Out"
342
- ] })
343
- ] })
344
- ] })
345
- ] })
346
- ] });
347
- return /* @__PURE__ */ jsxs2("div", { className: "flex min-h-screen bg-background", children: [
348
- /* @__PURE__ */ jsxs2("header", { className: "fixed top-0 right-0 left-0 z-40 flex h-16 items-center justify-between border-border border-b bg-card/95 px-4 backdrop-blur-xl md:hidden", children: [
349
- /* @__PURE__ */ jsx2(Logo, { variant, size: "sm" }),
350
- /* @__PURE__ */ jsx2(
351
- "button",
352
- {
353
- type: "button",
354
- onClick: () => setMobileMenuOpen(!mobileMenuOpen),
355
- className: "rounded-md p-2 hover:bg-accent focus:outline-none focus:ring-2 focus:ring-offset-2",
356
- "aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
357
- "aria-expanded": mobileMenuOpen,
358
- children: mobileMenuOpen ? /* @__PURE__ */ jsx2(XIcon, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx2(MenuIcon, { className: "h-6 w-6" })
359
- }
360
- )
361
- ] }),
362
- mobileMenuOpen && /* @__PURE__ */ jsx2(
363
- "div",
364
- {
365
- className: "fixed inset-0 z-30 bg-black/50 md:hidden",
366
- onClick: () => setMobileMenuOpen(false),
367
- "aria-hidden": "true"
368
- }
369
- ),
370
- /* @__PURE__ */ jsx2(
371
- "aside",
372
- {
373
- className: cn(
374
- "fixed top-16 bottom-0 left-0 z-30 flex w-64 flex-col border-border border-r bg-card/95 backdrop-blur-xl transition-transform duration-200 md:hidden",
375
- mobileMenuOpen ? "translate-x-0" : "-translate-x-full"
376
- ),
377
- children: /* @__PURE__ */ jsx2(SidebarContent, {})
378
- }
379
- ),
380
- /* @__PURE__ */ jsx2("aside", { className: "fixed top-0 bottom-0 left-0 hidden w-64 flex-col border-border border-r bg-card/50 backdrop-blur-xl md:flex", children: /* @__PURE__ */ jsx2(SidebarContent, {}) }),
381
- /* @__PURE__ */ jsx2("main", { className: "flex-1 pt-16 md:ml-64 md:pt-0", children: /* @__PURE__ */ jsx2("div", { className: "p-4 md:p-8", children: /* @__PURE__ */ jsx2("div", { className: "mx-auto max-w-6xl", children }) }) })
382
- ] });
383
- }
384
-
385
- // src/dashboard/backend-selector.tsx
386
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
387
- function BackendSelector({
388
- backends,
389
- selected,
390
- onChange,
391
- label = "Models",
392
- hint,
393
- multiSelect = true,
394
- className
395
- }) {
396
- const toggle = (type) => {
397
- if (multiSelect) {
398
- onChange(
399
- selected.includes(type) ? selected.filter((b) => b !== type) : [...selected, type]
400
- );
401
- } else {
402
- onChange([type]);
403
- }
404
- };
405
- return /* @__PURE__ */ jsxs3("div", { className, children: [
406
- /* @__PURE__ */ jsxs3("label", { className: "mb-2 block font-medium text-sm", children: [
407
- label,
408
- multiSelect && /* @__PURE__ */ jsx3("span", { className: "ml-2 font-normal text-muted-foreground", children: "(select multiple to compare)" })
409
- ] }),
410
- /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-2", children: backends.map((backend) => {
411
- const isSelected = selected.includes(backend.type);
412
- return /* @__PURE__ */ jsx3(
413
- "button",
414
- {
415
- type: "button",
416
- onClick: () => toggle(backend.type),
417
- className: `rounded-lg border px-3 py-2 text-sm transition-colors ${isSelected ? "border-blue-500 bg-blue-500/10 text-blue-400" : "border-border bg-background text-muted-foreground hover:border-muted-foreground/50"}`,
418
- title: backend.description,
419
- children: backend.label
420
- },
421
- backend.type
422
- );
423
- }) }),
424
- multiSelect && selected.length > 1 && /* @__PURE__ */ jsx3("p", { className: "mt-2 text-muted-foreground text-xs", children: hint || `Will run on ${selected.length} variants in parallel for comparison` })
425
- ] });
426
- }
427
-
428
- // src/dashboard/profile-selector.tsx
429
- import { Check, ChevronDown, Plus, Settings } from "lucide-react";
430
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
431
- function ProfileSelector({
432
- profiles,
433
- selectedId,
434
- onSelect,
435
- onCreateClick,
436
- onManageClick,
437
- label = "Profile",
438
- placeholder = "Default (no custom profile)",
439
- showMetrics = true,
440
- className
441
- }) {
442
- const selected = profiles.find((p) => p.id === selectedId);
443
- const builtinProfiles = profiles.filter((p) => p.is_builtin);
444
- const customProfiles = profiles.filter((p) => !p.is_builtin);
445
- return /* @__PURE__ */ jsxs4("div", { className, children: [
446
- label && /* @__PURE__ */ jsx4("label", { className: "mb-2 block font-medium text-sm", children: label }),
447
- /* @__PURE__ */ jsxs4(DropdownMenu, { children: [
448
- /* @__PURE__ */ jsx4(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button, { variant: "outline", className: "w-full justify-between", children: [
449
- /* @__PURE__ */ jsx4("span", { className: "truncate", children: selected ? selected.name : placeholder }),
450
- /* @__PURE__ */ jsx4(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
451
- ] }) }),
452
- /* @__PURE__ */ jsxs4(DropdownMenuContent, { className: "w-[300px]", align: "start", children: [
453
- /* @__PURE__ */ jsxs4(
454
- DropdownMenuItem,
455
- {
456
- onClick: () => onSelect(null),
457
- className: "flex items-center justify-between",
458
- children: [
459
- /* @__PURE__ */ jsx4("span", { children: placeholder }),
460
- !selectedId && /* @__PURE__ */ jsx4(Check, { className: "h-4 w-4 text-green-400" })
461
- ]
462
- }
463
- ),
464
- builtinProfiles.length > 0 && /* @__PURE__ */ jsxs4(Fragment2, { children: [
465
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
466
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: "Built-in Profiles" }),
467
- builtinProfiles.map((profile) => /* @__PURE__ */ jsxs4(
468
- DropdownMenuItem,
469
- {
470
- onClick: () => onSelect(profile),
471
- className: "flex flex-col items-start gap-1",
472
- children: [
473
- /* @__PURE__ */ jsxs4("div", { className: "flex w-full items-center justify-between", children: [
474
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
475
- /* @__PURE__ */ jsx4("span", { className: "font-medium", children: profile.name }),
476
- profile.extends && /* @__PURE__ */ jsxs4(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
477
- "extends ",
478
- profile.extends
479
- ] })
480
- ] }),
481
- selectedId === profile.id && /* @__PURE__ */ jsx4(Check, { className: "h-4 w-4 text-green-400" })
482
- ] }),
483
- profile.description && /* @__PURE__ */ jsx4("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
484
- ]
485
- },
486
- profile.id
487
- ))
488
- ] }),
489
- customProfiles.length > 0 && /* @__PURE__ */ jsxs4(Fragment2, { children: [
490
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
491
- /* @__PURE__ */ jsx4(DropdownMenuLabel, { children: "Custom Profiles" }),
492
- customProfiles.map((profile) => /* @__PURE__ */ jsxs4(
493
- DropdownMenuItem,
494
- {
495
- onClick: () => onSelect(profile),
496
- className: "flex flex-col items-start gap-1",
497
- children: [
498
- /* @__PURE__ */ jsxs4("div", { className: "flex w-full items-center justify-between", children: [
499
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
500
- /* @__PURE__ */ jsx4("span", { className: "font-medium", children: profile.name }),
501
- profile.model && /* @__PURE__ */ jsx4(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
502
- ] }),
503
- selectedId === profile.id && /* @__PURE__ */ jsx4(Check, { className: "h-4 w-4 text-green-400" })
504
- ] }),
505
- profile.description && /* @__PURE__ */ jsx4("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
506
- showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs4("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
507
- /* @__PURE__ */ jsxs4("span", { children: [
508
- profile.metrics.total_runs,
509
- " runs"
510
- ] }),
511
- /* @__PURE__ */ jsxs4("span", { children: [
512
- profile.metrics.success_rate.toFixed(0),
513
- "% success"
514
- ] }),
515
- /* @__PURE__ */ jsxs4("span", { children: [
516
- "~",
517
- (profile.metrics.avg_duration_ms / 1e3).toFixed(1),
518
- "s avg"
519
- ] })
520
- ] })
521
- ]
522
- },
523
- profile.id
524
- ))
525
- ] }),
526
- (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs4(Fragment2, { children: [
527
- /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
528
- onCreateClick && /* @__PURE__ */ jsxs4(
529
- DropdownMenuItem,
530
- {
531
- onClick: onCreateClick,
532
- className: "text-blue-400",
533
- children: [
534
- /* @__PURE__ */ jsx4(Plus, { className: "mr-2 h-4 w-4" }),
535
- "Create New Profile"
536
- ]
537
- }
538
- ),
539
- onManageClick && /* @__PURE__ */ jsxs4(
540
- DropdownMenuItem,
541
- {
542
- onClick: onManageClick,
543
- className: "text-muted-foreground",
544
- children: [
545
- /* @__PURE__ */ jsx4(Settings, { className: "mr-2 h-4 w-4" }),
546
- "Manage Profiles"
547
- ]
548
- }
549
- )
550
- ] })
551
- ] })
552
- ] })
553
- ] });
554
- }
555
- function ProfileComparison({
556
- profiles,
557
- className
558
- }) {
559
- const profilesWithMetrics = profiles.filter(
560
- (p) => p.metrics && p.metrics.total_runs > 0
561
- );
562
- if (profilesWithMetrics.length === 0) {
563
- return null;
564
- }
565
- const bestSuccess = profilesWithMetrics.reduce(
566
- (best, p) => (p.metrics?.success_rate ?? 0) > (best.metrics?.success_rate ?? 0) ? p : best
567
- );
568
- const fastestProfile = profilesWithMetrics.reduce(
569
- (best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
570
- );
571
- return /* @__PURE__ */ jsxs4("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
572
- /* @__PURE__ */ jsx4("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
573
- /* @__PURE__ */ jsx4("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
574
- const isBestSuccess = profile.id === bestSuccess.id;
575
- const isFastest = profile.id === fastestProfile.id;
576
- return /* @__PURE__ */ jsxs4(
577
- "div",
578
- {
579
- className: "flex items-center justify-between gap-4",
580
- children: [
581
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
582
- /* @__PURE__ */ jsx4("span", { className: "font-medium", children: profile.name }),
583
- isBestSuccess && /* @__PURE__ */ jsx4(Badge, { className: "border-0 bg-green-500/10 text-green-400 text-xs", children: "Best Success" }),
584
- isFastest && !isBestSuccess && /* @__PURE__ */ jsx4(Badge, { className: "border-0 bg-blue-500/10 text-blue-400 text-xs", children: "Fastest" })
585
- ] }),
586
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-4 text-sm", children: [
587
- /* @__PURE__ */ jsxs4("span", { children: [
588
- /* @__PURE__ */ jsx4("span", { className: "text-muted-foreground", children: "Success:" }),
589
- " ",
590
- /* @__PURE__ */ jsxs4(
591
- "span",
592
- {
593
- className: (profile.metrics?.success_rate ?? 0) >= 80 ? "text-green-400" : (profile.metrics?.success_rate ?? 0) >= 50 ? "text-yellow-400" : "text-red-400",
594
- children: [
595
- profile.metrics?.success_rate.toFixed(0),
596
- "%"
597
- ]
598
- }
599
- )
600
- ] }),
601
- /* @__PURE__ */ jsxs4("span", { children: [
602
- /* @__PURE__ */ jsx4("span", { className: "text-muted-foreground", children: "Avg:" }),
603
- " ",
604
- ((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
605
- "s"
606
- ] }),
607
- /* @__PURE__ */ jsxs4("span", { className: "text-muted-foreground", children: [
608
- profile.metrics?.total_runs,
609
- " runs"
610
- ] })
611
- ] })
612
- ]
613
- },
614
- profile.id
615
- );
616
- }) })
617
- ] });
618
- }
619
-
620
- // src/dashboard/variant-list.tsx
621
- import {
622
- Check as Check2,
623
- CheckCircle2,
624
- Clock,
625
- ExternalLink,
626
- Loader2,
627
- Timer,
628
- X,
629
- XCircle
630
- } from "lucide-react";
631
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
632
- var statusConfig = {
633
- pending: {
634
- icon: Clock,
635
- color: "text-yellow-400",
636
- bg: "bg-yellow-500/10",
637
- label: "Pending",
638
- animate: false
639
- },
640
- running: {
641
- icon: Loader2,
642
- color: "text-blue-400",
643
- bg: "bg-blue-500/10",
644
- label: "Running",
645
- animate: true
646
- },
647
- completed: {
648
- icon: CheckCircle2,
649
- color: "text-green-400",
650
- bg: "bg-green-500/10",
651
- label: "Completed",
652
- animate: false
653
- },
654
- failed: {
655
- icon: XCircle,
656
- color: "text-red-400",
657
- bg: "bg-red-500/10",
658
- label: "Failed",
659
- animate: false
660
- },
661
- cancelled: {
662
- icon: XCircle,
663
- color: "text-gray-400",
664
- bg: "bg-gray-500/10",
665
- label: "Cancelled",
666
- animate: false
667
- }
668
- };
669
- var outcomeConfig = {
670
- pending_review: {
671
- color: "text-amber-400",
672
- bg: "bg-amber-500/10",
673
- label: "Pending Review"
674
- },
675
- accepted: {
676
- color: "text-green-400",
677
- bg: "bg-green-500/10",
678
- label: "Accepted"
679
- },
680
- rejected: {
681
- color: "text-red-400",
682
- bg: "bg-red-500/10",
683
- label: "Rejected"
684
- },
685
- merged_with_conflicts: {
686
- color: "text-orange-400",
687
- bg: "bg-orange-500/10",
688
- label: "Merged (conflicts)"
689
- },
690
- expired: {
691
- color: "text-gray-400",
692
- bg: "bg-gray-500/10",
693
- label: "Expired"
694
- }
695
- };
696
- function VariantList({
697
- variants,
698
- selectedId,
699
- onSelect,
700
- onAccept,
701
- onReject,
702
- isActioning,
703
- className
704
- }) {
705
- return /* @__PURE__ */ jsx5("div", { className: `space-y-3 ${className || ""}`, children: variants.map((variant) => {
706
- const status = statusConfig[variant.status];
707
- const StatusIcon = status.icon;
708
- const isSelected = variant.id === selectedId;
709
- return /* @__PURE__ */ jsxs5(
710
- "div",
711
- {
712
- className: `cursor-pointer rounded-lg border p-4 transition-colors ${isSelected ? "border-blue-500 bg-blue-500/5" : "border-border hover:border-muted-foreground/50"}`,
713
- onClick: () => onSelect?.(variant.id),
714
- children: [
715
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
716
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
717
- /* @__PURE__ */ jsxs5(Badge, { className: `${status.bg} ${status.color} border-0`, children: [
718
- /* @__PURE__ */ jsx5(
719
- StatusIcon,
720
- {
721
- className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
722
- }
723
- ),
724
- status.label
725
- ] }),
726
- /* @__PURE__ */ jsx5("span", { className: "font-medium", children: variant.label }),
727
- variant.sublabel && /* @__PURE__ */ jsxs5("span", { className: "text-muted-foreground text-sm", children: [
728
- "(",
729
- variant.sublabel,
730
- ")"
731
- ] }),
732
- variant.durationMs && /* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-1 text-muted-foreground text-sm", children: [
733
- /* @__PURE__ */ jsx5(Timer, { className: "h-3 w-3" }),
734
- (variant.durationMs / 1e3).toFixed(2),
735
- "s"
736
- ] })
737
- ] }),
738
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
739
- variant.outcome && /* @__PURE__ */ jsx5(
740
- Badge,
741
- {
742
- className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].color} border-0`,
743
- children: outcomeConfig[variant.outcome].label
744
- }
745
- ),
746
- variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
747
- /* @__PURE__ */ jsxs5(
748
- Button,
749
- {
750
- variant: "outline",
751
- size: "sm",
752
- className: "text-green-400 hover:bg-green-500/10",
753
- onClick: (e) => {
754
- e.stopPropagation();
755
- onAccept(variant.id);
756
- },
757
- disabled: isActioning === variant.id,
758
- children: [
759
- /* @__PURE__ */ jsx5(Check2, { className: "mr-1 h-4 w-4" }),
760
- "Accept"
761
- ]
762
- }
763
- ),
764
- /* @__PURE__ */ jsxs5(
765
- Button,
766
- {
767
- variant: "outline",
768
- size: "sm",
769
- className: "text-red-400 hover:bg-red-500/10",
770
- onClick: (e) => {
771
- e.stopPropagation();
772
- onReject(variant.id);
773
- },
774
- disabled: isActioning === variant.id,
775
- children: [
776
- /* @__PURE__ */ jsx5(X, { className: "mr-1 h-4 w-4" }),
777
- "Reject"
778
- ]
779
- }
780
- )
781
- ] }),
782
- variant.detailsUrl && /* @__PURE__ */ jsx5(
783
- Button,
784
- {
785
- variant: "ghost",
786
- size: "sm",
787
- className: "text-muted-foreground",
788
- onClick: (e) => {
789
- e.stopPropagation();
790
- window.open(variant.detailsUrl, "_blank");
791
- },
792
- children: /* @__PURE__ */ jsx5(ExternalLink, { className: "h-4 w-4" })
793
- }
794
- )
795
- ] })
796
- ] }),
797
- variant.error && /* @__PURE__ */ jsx5("p", { className: "mt-2 text-red-400 text-sm", children: variant.error }),
798
- variant.summary && /* @__PURE__ */ jsx5("p", { className: "mt-2 line-clamp-2 text-muted-foreground text-sm", children: variant.summary })
799
- ]
800
- },
801
- variant.id
802
- );
803
- }) });
804
- }
805
-
806
- export {
807
- useTheme,
808
- ThemeToggle,
809
- DashboardLayout,
810
- BackendSelector,
811
- ProfileSelector,
812
- ProfileComparison,
813
- VariantList
814
- };