@tangle-network/sandbox-ui 0.125.3 → 0.126.0

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,15 +1,15 @@
1
- import { Zt as Logo, o as Button$1 } from "./primitives-DLE_MCwZ.js";
1
+ import { Zt as Logo, o as Button$1 } from "./primitives-WP3v1yf0.js";
2
2
  import { t as cn$1 } from "./utils-DzWbktWG.js";
3
3
  import { n as MOTION_SURFACE, r as MOTION_TRAVEL, t as MOTION_CONTROL } from "./motion-DkyBRJb9.js";
4
4
  import { i as moonshot_default } from "./model-brand-hMyDTUqB.js";
5
- import "./page-layout-DJV7cbxx.js";
6
- import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Dialog, DialogClose, DialogContent, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Skeleton, StatCard, StatusPill, useTheme } from "@tangle-network/ui/primitives";
5
+ import "./page-layout-2IRtfx51.js";
6
+ import { Avatar, AvatarFallback, AvatarImage, Dialog, DialogClose, DialogContent, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Skeleton, StatCard, StatusPill } from "@tangle-network/ui/primitives";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  import * as React$1 from "react";
9
9
  import { useEffect, useRef, useState } from "react";
10
10
  import { createPortal } from "react-dom";
11
- import { Activity, BarChart2, Bell, Bot, Box, Camera, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Clock, Code2, Copy, Cpu, DollarSign, Download, ExternalLink, File, FileEdit, FilePlus, FileText, GitBranch, GitCommit, Globe, HardDrive, Key, Layers, Loader2, MemoryStick, MessageSquare, Monitor, MoreHorizontal, MoreVertical, Network, PanelLeft, Play, Plug, Plus, Power, PowerOff, RotateCcw, Server, Settings, ShieldAlert, Skull, Terminal, Timer, Trash2, User, Users, Wrench, X, XCircle } from "lucide-react";
12
- import { focusField, focusFieldWithin, focusRing, focusRingInset, timeAgo } from "@tangle-network/ui/utils";
11
+ import { Activity, ArrowRight, BarChart2, Bell, Bot, Box, Camera, Check, ChevronDown, ChevronLeft, ChevronRight, Clock, Code2, Copy, Cpu, DollarSign, ExternalLink, File, FileEdit, FilePlus, GitBranch, GitCommit, Globe, HardDrive, Key, Layers, MemoryStick, MessageSquare, Monitor, MoreHorizontal, MoreVertical, Network, PanelLeft, Play, Plug, Plus, Power, PowerOff, RotateCcw, Skull, Terminal, Trash2, User, Users } from "lucide-react";
12
+ import { focusField, focusRing, focusRingInset, timeAgo } from "@tangle-network/ui/utils";
13
13
  import * as Select$1 from "@radix-ui/react-select";
14
14
  //#region src/dashboard/sidebar-context.tsx
15
15
  const PANEL_OPEN_KEY = "sandbox-sidebar-panel-open";
@@ -302,74 +302,6 @@ function MoonIcon({ className }) {
302
302
  children: [/* @__PURE__ */ jsx("title", { children: "Dark mode icon" }), /* @__PURE__ */ jsx("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })]
303
303
  });
304
304
  }
305
- /**
306
- * Compact light/dark switch driven by the shared `useTheme` hook.
307
- *
308
- * @deprecated The redesigned rail no longer renders a standalone theme toggle —
309
- * theme lives in the account menu as a Light/Dark/System control via the
310
- * `appearance` controller on {@link ProfileAvatar} (and both layouts). Kept for
311
- * backward compatibility; not used by `SidebarLayout`/`DashboardLayout`.
312
- */
313
- function RailThemeToggle({ className }) {
314
- const { theme, setTheme } = useTheme();
315
- const [mounted, setMounted] = React$1.useState(false);
316
- React$1.useEffect(() => setMounted(true), []);
317
- const isDark = mounted && (theme === "dark" || theme === "system" && typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches);
318
- return /* @__PURE__ */ jsx("button", {
319
- type: "button",
320
- onClick: () => setTheme(isDark ? "light" : "dark"),
321
- "aria-label": "Toggle theme",
322
- title: isDark ? "Switch to light mode" : "Switch to dark mode",
323
- className: cn$1("flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors", MOTION_CONTROL, "hover:bg-[var(--accent-surface-soft)] hover:text-foreground", focusRing, className),
324
- children: isDark ? /* @__PURE__ */ jsx(SunIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(MoonIcon, { className: "h-4 w-4" })
325
- });
326
- }
327
- function ChevronsLeftIcon({ className }) {
328
- return /* @__PURE__ */ jsxs("svg", {
329
- xmlns: "http://www.w3.org/2000/svg",
330
- viewBox: "0 0 24 24",
331
- fill: "none",
332
- stroke: "currentColor",
333
- strokeWidth: "2",
334
- strokeLinecap: "round",
335
- strokeLinejoin: "round",
336
- className,
337
- children: [/* @__PURE__ */ jsx("title", { children: "Collapse sidebar" }), /* @__PURE__ */ jsx("path", { d: "m11 17-5-5 5-5M18 17l-5-5 5-5" })]
338
- });
339
- }
340
- function ChevronsRightIcon({ className }) {
341
- return /* @__PURE__ */ jsxs("svg", {
342
- xmlns: "http://www.w3.org/2000/svg",
343
- viewBox: "0 0 24 24",
344
- fill: "none",
345
- stroke: "currentColor",
346
- strokeWidth: "2",
347
- strokeLinecap: "round",
348
- strokeLinejoin: "round",
349
- className,
350
- children: [/* @__PURE__ */ jsx("title", { children: "Expand sidebar" }), /* @__PURE__ */ jsx("path", { d: "m6 17 5-5-5-5M13 17l5-5-5-5" })]
351
- });
352
- }
353
- function RailCollapseToggle({ collapsed, showLabel, onToggle, className }) {
354
- const label = collapsed ? "Expand sidebar" : "Collapse sidebar";
355
- const Icon = collapsed ? ChevronsRightIcon : ChevronsLeftIcon;
356
- return /* @__PURE__ */ jsx(RailTooltip, {
357
- label,
358
- disabled: showLabel,
359
- className: showLabel ? "w-full" : void 0,
360
- children: /* @__PURE__ */ jsxs("button", {
361
- type: "button",
362
- onClick: onToggle,
363
- "aria-label": label,
364
- "aria-pressed": collapsed,
365
- className: cn$1("flex shrink-0 items-center rounded-md text-muted-foreground transition-colors", MOTION_CONTROL, showLabel ? "h-9 w-full justify-start gap-2.5 px-2.5" : "h-9 w-9 justify-center", "hover:bg-[var(--accent-surface-soft)] hover:text-foreground", focusRing, className),
366
- children: [/* @__PURE__ */ jsx(Icon, { className: "h-[17px] w-[17px] shrink-0" }), showLabel && /* @__PURE__ */ jsx("span", {
367
- className: "text-[13.5px] font-medium",
368
- children: label
369
- })]
370
- })
371
- });
372
- }
373
305
  function PanelToggleButton({ collapsed, onToggle, className }) {
374
306
  const label = collapsed ? "Expand sidebar" : "Collapse sidebar";
375
307
  return /* @__PURE__ */ jsx("button", {
@@ -477,17 +409,6 @@ function SidebarRail({ children, className, wide = false }) {
477
409
  children
478
410
  });
479
411
  }
480
- /**
481
- * @deprecated Superseded by {@link RailHeader}, the three-slot header
482
- * (brand · middle · panel toggle) used by both shells. Kept for backward
483
- * compatibility; no longer rendered by `SidebarLayout`/`DashboardLayout`.
484
- */
485
- function SidebarRailHeader({ children, className }) {
486
- return /* @__PURE__ */ jsx("div", {
487
- className: cn$1("flex h-14 shrink-0 items-center justify-center border-b border-[var(--md3-outline-variant)]", className),
488
- children
489
- });
490
- }
491
412
  function SidebarRailNav({ children, className, onClick }) {
492
413
  return /* @__PURE__ */ jsx("nav", {
493
414
  onClick,
@@ -1109,78 +1030,6 @@ function ProfileAvatar({ user, isLoading = false, onLogout, onSettingsClick, set
1109
1030
  })] });
1110
1031
  }
1111
1032
  //#endregion
1112
- //#region src/dashboard/credit-balance.tsx
1113
- function CreditBalance({ amount, description = "Credits are automatically deducted based on hourly Sandbox usage and Agent operations.", onTopUp, quickAmounts = [
1114
- 10,
1115
- 25,
1116
- 100
1117
- ], className }) {
1118
- const [topUpValue, setTopUpValue] = React$1.useState("50.00");
1119
- const topUpId = React$1.useId();
1120
- return /* @__PURE__ */ jsxs("div", {
1121
- className: cn$1("bg-surface-container p-5 rounded-xl flex flex-col justify-between border border-[var(--md3-outline-variant)]", className),
1122
- children: [/* @__PURE__ */ jsxs("div", { children: [
1123
- /* @__PURE__ */ jsx("h3", {
1124
- className: "text-sm font-semibold text-muted-foreground uppercase tracking-widest mb-2",
1125
- children: "Available Credits"
1126
- }),
1127
- /* @__PURE__ */ jsxs("div", {
1128
- className: "text-4xl font-extrabold text-primary tracking-tighter mb-2",
1129
- children: ["$", amount.toFixed(2)]
1130
- }),
1131
- /* @__PURE__ */ jsx("p", {
1132
- className: "text-sm text-muted-foreground leading-relaxed",
1133
- children: description
1134
- })
1135
- ] }), onTopUp && /* @__PURE__ */ jsxs("div", {
1136
- className: "space-y-2.5 mt-5",
1137
- children: [
1138
- /* @__PURE__ */ jsx("label", {
1139
- htmlFor: topUpId,
1140
- className: "block text-xs font-medium text-muted-foreground",
1141
- children: "Top-up amount (USD)"
1142
- }),
1143
- /* @__PURE__ */ jsxs("div", {
1144
- className: `bg-surface-container-low border p-1 rounded-lg flex items-center ${focusFieldWithin}`,
1145
- children: [/* @__PURE__ */ jsx("input", {
1146
- id: topUpId,
1147
- type: "text",
1148
- inputMode: "decimal",
1149
- value: `$${topUpValue}`,
1150
- onChange: (e) => {
1151
- const raw = e.target.value.replace(/[^0-9.]/g, "");
1152
- setTopUpValue(raw.match(/^(\d*\.?\d{0,2})/)?.[1] ?? "");
1153
- },
1154
- className: "bg-transparent border-none text-foreground font-mono text-lg min-w-0 flex-1 focus:ring-0 px-4 outline-none"
1155
- }), /* @__PURE__ */ jsx("button", {
1156
- type: "button",
1157
- onClick: () => {
1158
- const parsed = Number.parseFloat(topUpValue);
1159
- if (!Number.isFinite(parsed) || parsed <= 0) return;
1160
- onTopUp(parsed);
1161
- },
1162
- className: "shrink-0 whitespace-nowrap bg-[var(--accent-surface-soft)] border border-[var(--md3-outline-variant)] text-[var(--accent-text)] px-5 py-3 rounded-md font-bold text-xs uppercase tracking-widest active:scale-95 transition-transform hover:bg-[var(--accent-surface-strong)]",
1163
- children: "Top Up"
1164
- })]
1165
- }),
1166
- /* @__PURE__ */ jsx("div", {
1167
- className: "flex justify-between gap-2",
1168
- children: quickAmounts.filter((qa) => Number.isFinite(qa) && qa > 0).map((qa) => /* @__PURE__ */ jsxs("button", {
1169
- type: "button",
1170
- onClick: () => {
1171
- const rounded = parseFloat(qa.toFixed(2));
1172
- setTopUpValue(qa.toFixed(2));
1173
- onTopUp(rounded);
1174
- },
1175
- className: "flex-1 py-2 text-center text-xs font-mono tabular-nums text-muted-foreground border border-[var(--md3-outline-variant)] rounded-md hover:bg-surface-container-high hover:text-foreground transition-colors uppercase",
1176
- children: ["+$", qa.toLocaleString("en-US")]
1177
- }, qa))
1178
- })
1179
- ]
1180
- })]
1181
- });
1182
- }
1183
- //#endregion
1184
1033
  //#region src/dashboard/out-of-credits.tsx
1185
1034
  /**
1186
1035
  * Canonical "out of credits" UX, shared across every Tangle product.
@@ -1267,51 +1116,6 @@ function OutOfCreditsModal({ balance, onClose, ctaLabel = "Add credits", classNa
1267
1116
  });
1268
1117
  }
1269
1118
  //#endregion
1270
- //#region src/dashboard/cluster-status-bar.tsx
1271
- function ClusterStatusBar({ items, latency, className }) {
1272
- if (!items?.length) return null;
1273
- return /* @__PURE__ */ jsx("div", {
1274
- className: cn$1("fixed bottom-6 left-1/2 -translate-x-1/2 z-40 w-max max-w-[90vw] animate-in slide-in-from-bottom flex justify-center", className),
1275
- children: /* @__PURE__ */ jsxs("div", {
1276
- className: "flex items-center gap-4 overflow-x-auto rounded-full border border-[var(--md3-outline-variant)] bg-surface-container px-5 py-2.5 shadow-sm",
1277
- children: [items.map((item, i) => /* @__PURE__ */ jsxs(React$1.Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", {
1278
- "aria-hidden": true,
1279
- className: "h-5 w-px shrink-0 bg-border"
1280
- }), /* @__PURE__ */ jsxs("div", {
1281
- className: "flex shrink-0 items-center gap-2",
1282
- children: [item.icon ? /* @__PURE__ */ jsx("span", {
1283
- className: "flex shrink-0 items-center text-[var(--md3-primary)] [&_svg]:h-[18px] [&_svg]:w-[18px]",
1284
- children: item.icon
1285
- }) : null, /* @__PURE__ */ jsxs("div", {
1286
- className: "flex flex-col leading-tight",
1287
- children: [/* @__PURE__ */ jsx("span", {
1288
- className: "text-[10px] font-bold uppercase tracking-wider text-[var(--md3-on-surface-variant)]",
1289
- children: item.label
1290
- }), /* @__PURE__ */ jsx("span", {
1291
- className: cn$1("text-sm font-bold tabular-nums text-foreground", item.valueClass),
1292
- children: item.value
1293
- })]
1294
- })]
1295
- })] }, i)), latency && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
1296
- "aria-hidden": true,
1297
- className: "h-5 w-px shrink-0 bg-border"
1298
- }), /* @__PURE__ */ jsxs("div", {
1299
- className: "flex shrink-0 items-center gap-2",
1300
- children: [/* @__PURE__ */ jsxs("span", {
1301
- className: "relative flex h-2.5 w-2.5 items-center justify-center",
1302
- children: [/* @__PURE__ */ jsx("span", {
1303
- className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75",
1304
- "data-motion": "essential"
1305
- }), /* @__PURE__ */ jsx("span", { className: "relative inline-flex h-2 w-2 rounded-full bg-green-500" })]
1306
- }), /* @__PURE__ */ jsx("span", {
1307
- className: "font-mono text-xs font-bold text-green-400",
1308
- children: latency
1309
- })]
1310
- })] })]
1311
- })
1312
- });
1313
- }
1314
- //#endregion
1315
1119
  //#region src/dashboard/resource-meter.tsx
1316
1120
  function getBarColor(percent) {
1317
1121
  if (percent >= 90) return "bg-[var(--code-error)]";
@@ -2152,159 +1956,6 @@ function SandboxTable({ sandboxes, page = 1, pageSize = 10, total, onPageChange,
2152
1956
  });
2153
1957
  }
2154
1958
  //#endregion
2155
- //#region src/dashboard/invoice-table.tsx
2156
- const statusStyle = {
2157
- paid: "bg-[var(--accent-surface-soft)] text-primary border border-[var(--md3-outline-variant)]",
2158
- pending: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border border-[var(--surface-warning-border)]",
2159
- failed: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border border-[var(--surface-danger-border)]"
2160
- };
2161
- function InvoiceTable({ invoices, onExportAll, onLoadMore, onViewInvoice, hasMore, className }) {
2162
- return /* @__PURE__ */ jsxs("section", {
2163
- className,
2164
- children: [
2165
- /* @__PURE__ */ jsxs("div", {
2166
- className: "flex justify-between items-center mb-6 px-2",
2167
- children: [/* @__PURE__ */ jsx("h2", {
2168
- className: "text-2xl font-bold text-foreground tracking-tight",
2169
- children: "Invoice History"
2170
- }), onExportAll && /* @__PURE__ */ jsxs("button", {
2171
- type: "button",
2172
- onClick: onExportAll,
2173
- className: "text-[10px] font-mono text-primary uppercase tracking-widest flex items-center gap-2 hover:underline",
2174
- children: [/* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5" }), "Export All"]
2175
- })]
2176
- }),
2177
- /* @__PURE__ */ jsx("div", {
2178
- className: "bg-surface-container rounded-xl overflow-hidden border border-[var(--md3-outline-variant)]",
2179
- children: /* @__PURE__ */ jsxs("table", {
2180
- className: "w-full text-left border-collapse",
2181
- children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
2182
- className: "bg-surface-container-high border-b border-[var(--md3-outline-variant)]",
2183
- children: [
2184
- /* @__PURE__ */ jsx("th", {
2185
- className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest",
2186
- children: "Invoice ID"
2187
- }),
2188
- /* @__PURE__ */ jsx("th", {
2189
- className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest",
2190
- children: "Date"
2191
- }),
2192
- /* @__PURE__ */ jsx("th", {
2193
- className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest",
2194
- children: "Amount"
2195
- }),
2196
- /* @__PURE__ */ jsx("th", {
2197
- className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest",
2198
- children: "Status"
2199
- }),
2200
- /* @__PURE__ */ jsx("th", {
2201
- className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest text-right",
2202
- children: "Action"
2203
- })
2204
- ]
2205
- }) }), /* @__PURE__ */ jsx("tbody", {
2206
- className: "divide-y divide-border",
2207
- children: invoices.map((inv) => /* @__PURE__ */ jsxs("tr", {
2208
- className: "hover:bg-surface-container-high transition-colors",
2209
- children: [
2210
- /* @__PURE__ */ jsx("td", {
2211
- className: "px-6 py-5 font-mono text-xs text-foreground",
2212
- children: inv.id
2213
- }),
2214
- /* @__PURE__ */ jsx("td", {
2215
- className: "px-6 py-5 text-sm text-foreground",
2216
- children: inv.date
2217
- }),
2218
- /* @__PURE__ */ jsxs("td", {
2219
- className: "px-6 py-5 text-sm font-bold text-foreground",
2220
- children: ["$", inv.amount.toFixed(2)]
2221
- }),
2222
- /* @__PURE__ */ jsx("td", {
2223
- className: "px-6 py-5",
2224
- children: /* @__PURE__ */ jsx("span", {
2225
- className: cn$1("px-2 py-1 text-[10px] font-mono rounded uppercase", statusStyle[inv.status] ?? statusStyle.paid),
2226
- children: inv.status
2227
- })
2228
- }),
2229
- /* @__PURE__ */ jsx("td", {
2230
- className: "px-6 py-5 text-right",
2231
- children: /* @__PURE__ */ jsx("button", {
2232
- type: "button",
2233
- onClick: () => onViewInvoice?.(inv.id),
2234
- className: "text-muted-foreground hover:text-foreground transition-colors",
2235
- children: /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" })
2236
- })
2237
- })
2238
- ]
2239
- }, inv.id))
2240
- })]
2241
- })
2242
- }),
2243
- hasMore && onLoadMore && /* @__PURE__ */ jsx("div", {
2244
- className: "mt-6 flex justify-center",
2245
- children: /* @__PURE__ */ jsx("button", {
2246
- type: "button",
2247
- onClick: onLoadMore,
2248
- className: "px-8 py-2 text-[10px] font-mono text-muted-foreground border border-[var(--md3-outline-variant)] rounded-full hover:bg-surface-container-high transition-colors uppercase tracking-widest",
2249
- children: "Load More History"
2250
- })
2251
- })
2252
- ]
2253
- });
2254
- }
2255
- //#endregion
2256
- //#region src/dashboard/plan-cards.tsx
2257
- function PlanCards({ plans, className }) {
2258
- return /* @__PURE__ */ jsxs("section", {
2259
- className,
2260
- children: [/* @__PURE__ */ jsx("h2", {
2261
- className: "text-2xl font-bold text-foreground tracking-tight mb-5 px-2",
2262
- children: "Subscription Plans"
2263
- }), /* @__PURE__ */ jsx("div", {
2264
- className: "grid grid-cols-1 md:grid-cols-3 gap-6",
2265
- children: plans.map((plan) => /* @__PURE__ */ jsxs("div", {
2266
- className: cn$1("p-5 rounded-xl transition-all relative overflow-hidden border", plan.popular ? "bg-surface-container-high border-[var(--md3-outline-variant)]" : "bg-surface-container border-[var(--md3-outline-variant)] hover:bg-surface-container-high hover:border-primary/20"),
2267
- children: [
2268
- plan.popular && /* @__PURE__ */ jsx("div", {
2269
- className: "absolute top-0 right-0 bg-[var(--accent-surface-soft)] border-l border-b border-[var(--md3-outline-variant)] px-4 py-1 text-[10px] font-bold text-[var(--accent-text)] uppercase tracking-widest rounded-bl-lg",
2270
- children: "Popular"
2271
- }),
2272
- /* @__PURE__ */ jsxs("div", {
2273
- className: "mb-4",
2274
- children: [/* @__PURE__ */ jsx("div", {
2275
- className: cn$1("text-xs font-mono uppercase tracking-widest mb-2", plan.popular ? "text-primary" : "text-muted-foreground"),
2276
- children: plan.name
2277
- }), /* @__PURE__ */ jsxs("div", {
2278
- className: "text-3xl font-bold text-foreground",
2279
- children: [
2280
- "$",
2281
- plan.price,
2282
- /* @__PURE__ */ jsxs("span", {
2283
- className: "text-sm font-normal text-muted-foreground tracking-normal",
2284
- children: ["/", plan.period ?? "mo"]
2285
- })
2286
- ]
2287
- })]
2288
- }),
2289
- /* @__PURE__ */ jsx("ul", {
2290
- className: "space-y-2 mb-5 text-sm text-muted-foreground",
2291
- children: plan.features.map((f, i) => /* @__PURE__ */ jsxs("li", {
2292
- className: "flex items-center gap-2",
2293
- children: [/* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-primary shrink-0" }), f.text]
2294
- }, i))
2295
- }),
2296
- /* @__PURE__ */ jsx("button", {
2297
- type: "button",
2298
- onClick: () => plan.onSelect?.(plan.id),
2299
- className: cn$1("w-full py-3 rounded-lg text-xs font-bold uppercase tracking-widest transition-all border", plan.current ? "border-[var(--md3-outline-variant)] text-muted-foreground hover:border-primary/20 hover:text-foreground" : plan.popular ? "bg-[var(--accent-surface-soft)] border-[var(--md3-outline-variant)] text-[var(--accent-text)] hover:bg-[var(--accent-surface-strong)] active:scale-95 transition-transform" : "border-[var(--md3-outline-variant)] text-foreground hover:border-primary/20 hover:text-primary"),
2300
- children: plan.ctaLabel ?? (plan.current ? "Current Plan" : "Upgrade Now")
2301
- })
2302
- ]
2303
- }, plan.id))
2304
- })]
2305
- });
2306
- }
2307
- //#endregion
2308
1959
  //#region src/dashboard/backend-selector.tsx
2309
1960
  function BackendSelector({ backends, selected, onChange, variant = "pill", label = "Model", placeholder = "Select a model", className, triggerClassName }) {
2310
1961
  const current = backends.find((b) => b.type === selected);
@@ -2587,7 +2238,7 @@ function HarnessPicker({ value, onChange, available, optionsOverride, label = "A
2587
2238
  * `.dark` class.
2588
2239
  *
2589
2240
  * The shared theme hook (`@tangle-network/ui`'s `useTheme`, used by
2590
- * {@link RailThemeToggle} and the `appearance` menu) only toggles `.dark`. But
2241
+ * the `appearance` menu) only toggles `.dark`. But
2591
2242
  * `@tangle-network/brand` 0.6 defaults to dark via `[data-sandbox-ui]` (always
2592
2243
  * present on the app's `<html>`) and scopes its light tokens to `.light` /
2593
2244
  * `[data-theme="light"]`. So removing `.dark` alone does NOT switch to light —
@@ -3447,185 +3098,6 @@ function SidebarLayout({ panelOpen, onPanelOpenChange, defaultPanelOpen, railCol
3447
3098
  });
3448
3099
  }
3449
3100
  //#endregion
3450
- //#region src/dashboard/profile-selector.tsx
3451
- function ProfileSelector({ profiles, selectedId, onSelect, onCreateClick, onManageClick, label = "Profile", placeholder = "Default (no custom profile)", showMetrics = true, className }) {
3452
- const selected = profiles.find((p) => p.id === selectedId);
3453
- const builtinProfiles = profiles.filter((p) => p.is_builtin);
3454
- const customProfiles = profiles.filter((p) => !p.is_builtin);
3455
- return /* @__PURE__ */ jsxs("div", {
3456
- className,
3457
- children: [label && /* @__PURE__ */ jsx("label", {
3458
- className: "mb-2 block font-medium text-sm",
3459
- children: label
3460
- }), /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
3461
- asChild: true,
3462
- children: /* @__PURE__ */ jsxs(Button, {
3463
- variant: "outline",
3464
- className: "w-full justify-between",
3465
- children: [/* @__PURE__ */ jsx("span", {
3466
- className: "truncate",
3467
- children: selected ? selected.name : placeholder
3468
- }), /* @__PURE__ */ jsx(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })]
3469
- })
3470
- }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
3471
- className: "w-[300px]",
3472
- align: "start",
3473
- children: [
3474
- /* @__PURE__ */ jsxs(DropdownMenuItem, {
3475
- onClick: () => onSelect(null),
3476
- className: "flex items-center justify-between",
3477
- children: [/* @__PURE__ */ jsx("span", { children: placeholder }), !selectedId && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-[var(--surface-success-text)]" })]
3478
- }),
3479
- builtinProfiles.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
3480
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3481
- /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Built-in Profiles" }),
3482
- builtinProfiles.map((profile) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
3483
- onClick: () => onSelect(profile),
3484
- className: "flex flex-col items-start gap-1",
3485
- children: [/* @__PURE__ */ jsxs("div", {
3486
- className: "flex w-full items-center justify-between",
3487
- children: [/* @__PURE__ */ jsxs("div", {
3488
- className: "flex items-center gap-2",
3489
- children: [/* @__PURE__ */ jsx("span", {
3490
- className: "font-medium",
3491
- children: profile.name
3492
- }), profile.extends && /* @__PURE__ */ jsxs(Badge, {
3493
- variant: "secondary",
3494
- className: "border-0 text-xs",
3495
- children: ["extends ", profile.extends]
3496
- })]
3497
- }), selectedId === profile.id && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-[var(--surface-success-text)]" })]
3498
- }), profile.description && /* @__PURE__ */ jsx("span", {
3499
- className: "line-clamp-1 text-muted-foreground text-xs",
3500
- children: profile.description
3501
- })]
3502
- }, profile.id))
3503
- ] }),
3504
- customProfiles.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
3505
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3506
- /* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Custom Profiles" }),
3507
- customProfiles.map((profile) => /* @__PURE__ */ jsxs(DropdownMenuItem, {
3508
- onClick: () => onSelect(profile),
3509
- className: "flex flex-col items-start gap-1",
3510
- children: [
3511
- /* @__PURE__ */ jsxs("div", {
3512
- className: "flex w-full items-center justify-between",
3513
- children: [/* @__PURE__ */ jsxs("div", {
3514
- className: "flex items-center gap-2",
3515
- children: [/* @__PURE__ */ jsx("span", {
3516
- className: "font-medium",
3517
- children: profile.name
3518
- }), profile.model && /* @__PURE__ */ jsx(Badge, {
3519
- variant: "secondary",
3520
- className: "border-0 text-xs",
3521
- children: profile.model.split("/").pop()
3522
- })]
3523
- }), selectedId === profile.id && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-[var(--surface-success-text)]" })]
3524
- }),
3525
- profile.description && /* @__PURE__ */ jsx("span", {
3526
- className: "line-clamp-1 text-muted-foreground text-xs",
3527
- children: profile.description
3528
- }),
3529
- showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs("div", {
3530
- className: "flex gap-3 text-muted-foreground text-xs",
3531
- children: [
3532
- /* @__PURE__ */ jsxs("span", { children: [profile.metrics.total_runs, " runs"] }),
3533
- /* @__PURE__ */ jsxs("span", { children: [profile.metrics.success_rate.toFixed(0), "% success"] }),
3534
- /* @__PURE__ */ jsxs("span", { children: [
3535
- "~",
3536
- (profile.metrics.avg_duration_ms / 1e3).toFixed(1),
3537
- "s avg"
3538
- ] })
3539
- ]
3540
- })
3541
- ]
3542
- }, profile.id))
3543
- ] }),
3544
- (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs(Fragment, { children: [
3545
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3546
- onCreateClick && /* @__PURE__ */ jsxs(DropdownMenuItem, {
3547
- onClick: onCreateClick,
3548
- className: "text-[var(--surface-info-text)]",
3549
- children: [/* @__PURE__ */ jsx(Plus, { className: "mr-2 h-4 w-4" }), "Create New Profile"]
3550
- }),
3551
- onManageClick && /* @__PURE__ */ jsxs(DropdownMenuItem, {
3552
- onClick: onManageClick,
3553
- className: "text-muted-foreground",
3554
- children: [/* @__PURE__ */ jsx(Settings, { className: "mr-2 h-4 w-4" }), "Manage Profiles"]
3555
- })
3556
- ] })
3557
- ]
3558
- })] })]
3559
- });
3560
- }
3561
- function ProfileComparison({ profiles, className }) {
3562
- const profilesWithMetrics = profiles.filter((p) => p.metrics && p.metrics.total_runs > 0);
3563
- if (profilesWithMetrics.length === 0) return null;
3564
- const bestSuccess = profilesWithMetrics.reduce((best, p) => (p.metrics?.success_rate ?? 0) > (best.metrics?.success_rate ?? 0) ? p : best);
3565
- const fastestProfile = profilesWithMetrics.reduce((best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best);
3566
- return /* @__PURE__ */ jsxs("div", {
3567
- className: `rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container p-4 ${className ?? ""}`,
3568
- children: [/* @__PURE__ */ jsx("h4", {
3569
- className: "mb-3 font-medium text-sm",
3570
- children: "Profile Performance"
3571
- }), /* @__PURE__ */ jsx("div", {
3572
- className: "space-y-3",
3573
- children: profilesWithMetrics.map((profile) => {
3574
- const isBestSuccess = profile.id === bestSuccess.id;
3575
- const isFastest = profile.id === fastestProfile.id;
3576
- return /* @__PURE__ */ jsxs("div", {
3577
- className: "flex items-center justify-between gap-4",
3578
- children: [/* @__PURE__ */ jsxs("div", {
3579
- className: "flex items-center gap-2",
3580
- children: [
3581
- /* @__PURE__ */ jsx("span", {
3582
- className: "font-medium",
3583
- children: profile.name
3584
- }),
3585
- isBestSuccess && /* @__PURE__ */ jsx(Badge, {
3586
- className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs",
3587
- children: "Best Success"
3588
- }),
3589
- isFastest && !isBestSuccess && /* @__PURE__ */ jsx(Badge, {
3590
- className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs",
3591
- children: "Fastest"
3592
- })
3593
- ]
3594
- }), /* @__PURE__ */ jsxs("div", {
3595
- className: "flex items-center gap-4 text-sm",
3596
- children: [
3597
- /* @__PURE__ */ jsxs("span", { children: [
3598
- /* @__PURE__ */ jsx("span", {
3599
- className: "text-muted-foreground",
3600
- children: "Success:"
3601
- }),
3602
- " ",
3603
- /* @__PURE__ */ jsxs("span", {
3604
- className: (profile.metrics?.success_rate ?? 0) >= 80 ? "text-[var(--surface-success-text)]" : (profile.metrics?.success_rate ?? 0) >= 50 ? "text-[var(--surface-warning-text)]" : "text-[var(--surface-danger-text)]",
3605
- children: [profile.metrics?.success_rate.toFixed(0), "%"]
3606
- })
3607
- ] }),
3608
- /* @__PURE__ */ jsxs("span", { children: [
3609
- /* @__PURE__ */ jsx("span", {
3610
- className: "text-muted-foreground",
3611
- children: "Avg:"
3612
- }),
3613
- " ",
3614
- ((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
3615
- "s"
3616
- ] }),
3617
- /* @__PURE__ */ jsxs("span", {
3618
- className: "text-muted-foreground",
3619
- children: [profile.metrics?.total_runs, " runs"]
3620
- })
3621
- ]
3622
- })]
3623
- }, profile.id);
3624
- })
3625
- })]
3626
- });
3627
- }
3628
- //#endregion
3629
3101
  //#region src/dashboard/metric-area-chart.tsx
3630
3102
  const TONE_VARS = {
3631
3103
  primary: "var(--brand-primary, hsl(var(--primary)))",
@@ -3773,181 +3245,6 @@ function MetricAreaChart({ points, label, formatValue, maxValue, detail, tone =
3773
3245
  });
3774
3246
  }
3775
3247
  //#endregion
3776
- //#region src/dashboard/variant-list.tsx
3777
- const statusConfig = {
3778
- pending: {
3779
- icon: Clock,
3780
- color: "text-[var(--surface-warning-text)]",
3781
- bg: "bg-[var(--surface-warning-bg)]",
3782
- border: "border-[var(--surface-warning-border)]",
3783
- label: "Pending",
3784
- animate: false
3785
- },
3786
- running: {
3787
- icon: Loader2,
3788
- color: "text-primary",
3789
- bg: "bg-[var(--accent-surface-soft)]",
3790
- border: "border-[var(--md3-outline-variant)]",
3791
- label: "Running",
3792
- animate: true
3793
- },
3794
- completed: {
3795
- icon: CheckCircle2,
3796
- color: "text-[var(--surface-success-text)]",
3797
- bg: "bg-[var(--surface-success-bg)]",
3798
- border: "border-[var(--surface-success-border)]",
3799
- label: "Completed",
3800
- animate: false
3801
- },
3802
- failed: {
3803
- icon: XCircle,
3804
- color: "text-[var(--surface-danger-text)]",
3805
- bg: "bg-[var(--surface-danger-bg)]",
3806
- border: "border-[var(--surface-danger-border)]",
3807
- label: "Failed",
3808
- animate: false
3809
- },
3810
- cancelled: {
3811
- icon: XCircle,
3812
- color: "text-[var(--surface-neutral-text)]",
3813
- bg: "bg-[var(--surface-neutral-bg)]",
3814
- border: "border-[var(--surface-neutral-border)]",
3815
- label: "Cancelled",
3816
- animate: false
3817
- }
3818
- };
3819
- const outcomeConfig = {
3820
- pending_review: {
3821
- color: "text-[var(--surface-warning-text)]",
3822
- bg: "bg-[var(--surface-warning-bg)]",
3823
- border: "border-[var(--surface-warning-border)]",
3824
- label: "Pending Review"
3825
- },
3826
- accepted: {
3827
- color: "text-[var(--surface-success-text)]",
3828
- bg: "bg-[var(--surface-success-bg)]",
3829
- border: "border-[var(--surface-success-border)]",
3830
- label: "Accepted"
3831
- },
3832
- rejected: {
3833
- color: "text-[var(--surface-danger-text)]",
3834
- bg: "bg-[var(--surface-danger-bg)]",
3835
- border: "border-[var(--surface-danger-border)]",
3836
- label: "Rejected"
3837
- },
3838
- merged_with_conflicts: {
3839
- color: "text-[var(--surface-orange-text)]",
3840
- bg: "bg-[var(--surface-orange-bg)]",
3841
- border: "border-[var(--surface-orange-border)]",
3842
- label: "Merged (conflicts)"
3843
- },
3844
- expired: {
3845
- color: "text-[var(--surface-neutral-text)]",
3846
- bg: "bg-[var(--surface-neutral-bg)]",
3847
- border: "border-[var(--surface-neutral-border)]",
3848
- label: "Expired"
3849
- }
3850
- };
3851
- function VariantList({ variants, selectedId, onSelect, onAccept, onReject, isActioning, className }) {
3852
- return /* @__PURE__ */ jsx("div", {
3853
- className: `space-y-2 ${className || ""}`,
3854
- children: variants.map((variant) => {
3855
- const status = statusConfig[variant.status];
3856
- const StatusIcon = status.icon;
3857
- const isSelected = variant.id === selectedId;
3858
- return /* @__PURE__ */ jsxs("div", {
3859
- className: `cursor-pointer rounded-lg border px-3 py-2.5 transition-colors ${isSelected ? "border-primary/30 bg-[var(--accent-surface-soft)]" : "border-[var(--md3-outline-variant)] bg-surface-container hover:border-primary/20 hover:bg-surface-container-high"}`,
3860
- onClick: () => onSelect?.(variant.id),
3861
- children: [
3862
- /* @__PURE__ */ jsxs("div", {
3863
- className: "flex flex-wrap items-center gap-2",
3864
- children: [
3865
- /* @__PURE__ */ jsxs(Badge, {
3866
- className: `shrink-0 ${status.bg} ${status.border} ${status.color}`,
3867
- children: [/* @__PURE__ */ jsx(StatusIcon, {
3868
- className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`,
3869
- ...status.animate ? { "data-motion": "essential" } : {}
3870
- }), status.label]
3871
- }),
3872
- /* @__PURE__ */ jsx("span", {
3873
- className: "truncate text-sm font-medium text-foreground",
3874
- children: variant.label
3875
- }),
3876
- variant.sublabel && /* @__PURE__ */ jsxs("span", {
3877
- className: "shrink-0 text-xs text-muted-foreground",
3878
- children: [
3879
- "(",
3880
- variant.sublabel,
3881
- ")"
3882
- ]
3883
- }),
3884
- variant.durationMs && /* @__PURE__ */ jsxs("span", {
3885
- className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
3886
- children: [
3887
- /* @__PURE__ */ jsx(Timer, { className: "h-3 w-3" }),
3888
- (variant.durationMs / 1e3).toFixed(1),
3889
- "s"
3890
- ]
3891
- }),
3892
- /* @__PURE__ */ jsxs("div", {
3893
- className: "ml-auto flex min-w-0 flex-wrap items-center justify-end gap-1.5",
3894
- children: [
3895
- variant.outcome && /* @__PURE__ */ jsx("span", {
3896
- className: "flex max-[359px]:w-full max-[359px]:justify-start",
3897
- children: /* @__PURE__ */ jsx(Badge, {
3898
- className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
3899
- children: outcomeConfig[variant.outcome].label
3900
- })
3901
- }),
3902
- variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Button, {
3903
- variant: "outline",
3904
- size: "sm",
3905
- className: "h-7 border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] px-2 text-xs text-[var(--surface-success-text)] hover:bg-[var(--surface-success-border)]",
3906
- onClick: (e) => {
3907
- e.stopPropagation();
3908
- onAccept(variant.id);
3909
- },
3910
- disabled: isActioning === variant.id,
3911
- children: [/* @__PURE__ */ jsx(Check, { className: "mr-1 h-3 w-3" }), "Accept"]
3912
- }), /* @__PURE__ */ jsxs(Button, {
3913
- variant: "outline",
3914
- size: "sm",
3915
- className: "h-7 border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] px-2 text-xs text-[var(--surface-danger-text)] hover:bg-[var(--surface-danger-border)]",
3916
- onClick: (e) => {
3917
- e.stopPropagation();
3918
- onReject(variant.id);
3919
- },
3920
- disabled: isActioning === variant.id,
3921
- children: [/* @__PURE__ */ jsx(X, { className: "mr-1 h-3 w-3" }), "Reject"]
3922
- })] }),
3923
- variant.detailsUrl && /* @__PURE__ */ jsx(Button, {
3924
- variant: "ghost",
3925
- size: "sm",
3926
- className: "h-7 w-7 p-0 text-muted-foreground hover:text-foreground",
3927
- onClick: (e) => {
3928
- e.stopPropagation();
3929
- window.open(variant.detailsUrl, "_blank");
3930
- },
3931
- children: /* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5" })
3932
- })
3933
- ]
3934
- })
3935
- ]
3936
- }),
3937
- variant.error && /* @__PURE__ */ jsx("p", {
3938
- className: "mt-1.5 text-xs text-[var(--surface-danger-text)]",
3939
- children: variant.error
3940
- }),
3941
- variant.summary && /* @__PURE__ */ jsx("p", {
3942
- className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground",
3943
- children: variant.summary
3944
- })
3945
- ]
3946
- }, variant.id);
3947
- })
3948
- });
3949
- }
3950
- //#endregion
3951
3248
  //#region src/dashboard/system-logs.tsx
3952
3249
  function SystemLogsViewer({ apiUrl, token, className }) {
3953
3250
  const [logs, setLogs] = useState([]);
@@ -4416,6 +3713,42 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
4416
3713
  });
4417
3714
  }
4418
3715
  //#endregion
3716
+ //#region src/dashboard/template-card.tsx
3717
+ function TemplateCard({ template, onUseTemplate, className }) {
3718
+ return /* @__PURE__ */ jsxs("div", {
3719
+ className: cn$1("group relative flex flex-col justify-between rounded-xl border border-[var(--md3-outline-variant)] bg-surface-container p-6 transition-colors hover:border-[var(--border-accent)]", className),
3720
+ children: [/* @__PURE__ */ jsxs("div", { children: [
3721
+ /* @__PURE__ */ jsx("div", {
3722
+ className: "mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-surface-container-high border border-[var(--md3-outline-variant)]",
3723
+ children: template.icon ?? /* @__PURE__ */ jsx("span", {
3724
+ className: "text-lg font-bold text-primary",
3725
+ children: template.name.charAt(0).toUpperCase()
3726
+ })
3727
+ }),
3728
+ /* @__PURE__ */ jsx("h3", {
3729
+ className: "mb-1 text-base font-bold text-foreground",
3730
+ children: template.name
3731
+ }),
3732
+ /* @__PURE__ */ jsx("p", {
3733
+ className: "text-sm text-muted-foreground leading-relaxed line-clamp-2",
3734
+ children: template.description
3735
+ }),
3736
+ template.tags && template.tags.length > 0 && /* @__PURE__ */ jsx("div", {
3737
+ className: "mt-3 flex flex-wrap gap-1.5",
3738
+ children: template.tags.map((tag, i) => /* @__PURE__ */ jsx("span", {
3739
+ className: "rounded-full bg-surface-container-high px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
3740
+ children: tag
3741
+ }, `${tag}-${i}`))
3742
+ })
3743
+ ] }), /* @__PURE__ */ jsxs("button", {
3744
+ type: "button",
3745
+ onClick: () => onUseTemplate(template.id),
3746
+ className: "mt-5 inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/10 border border-primary/20 px-4 py-2.5 text-sm font-bold text-primary transition-colors hover:bg-primary hover:text-primary-foreground active:scale-[0.98]",
3747
+ children: ["Use Template", /* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4 transition-transform group-hover:translate-x-0.5" })]
3748
+ })]
3749
+ });
3750
+ }
3751
+ //#endregion
4419
3752
  //#region src/dashboard/process-list.tsx
4420
3753
  function formatUptime(startedAt) {
4421
3754
  if (!startedAt) return "-";
@@ -4556,296 +3889,6 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
4556
3889
  });
4557
3890
  }
4558
3891
  //#endregion
4559
- //#region src/dashboard/network-config.tsx
4560
- function NetworkConfig({ config, onUpdate, loading = false, className }) {
4561
- const [newCidr, setNewCidr] = React$1.useState("");
4562
- const isValidCidr = (value) => {
4563
- const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
4564
- if (!match) return false;
4565
- const octets = [
4566
- match[1],
4567
- match[2],
4568
- match[3],
4569
- match[4]
4570
- ].map(Number);
4571
- const prefix = Number(match[5]);
4572
- return octets.every((o) => o <= 255) && prefix <= 32;
4573
- };
4574
- const handleAddCidr = () => {
4575
- const cidr = newCidr.trim();
4576
- if (cidr && config && isValidCidr(cidr) && !config.allowList.includes(cidr)) {
4577
- onUpdate({ allowList: [...config.allowList, cidr] });
4578
- setNewCidr("");
4579
- }
4580
- };
4581
- const handleRemoveCidr = (cidr) => {
4582
- if (config) onUpdate({ allowList: config.allowList.filter((c) => c !== cidr) });
4583
- };
4584
- if (loading || !config) return /* @__PURE__ */ jsxs("div", {
4585
- className: cn$1("rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container p-6 text-center", className),
4586
- children: [/* @__PURE__ */ jsx(Network, {
4587
- className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2",
4588
- "data-motion": "essential"
4589
- }), /* @__PURE__ */ jsx("p", {
4590
- className: "text-sm text-muted-foreground",
4591
- children: "Loading network configuration..."
4592
- })]
4593
- });
4594
- return /* @__PURE__ */ jsxs("div", {
4595
- className: cn$1("space-y-4", className),
4596
- children: [/* @__PURE__ */ jsxs("div", {
4597
- className: "flex items-center justify-between rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-4 py-3",
4598
- children: [/* @__PURE__ */ jsxs("div", {
4599
- className: "flex items-center gap-3",
4600
- children: [/* @__PURE__ */ jsx(ShieldAlert, { className: "h-4 w-4 text-muted-foreground" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
4601
- className: "text-sm font-medium text-foreground",
4602
- children: "Block Outbound Traffic"
4603
- }), /* @__PURE__ */ jsx("p", {
4604
- className: "text-xs text-muted-foreground",
4605
- children: "Prevent the sandbox from making external network requests"
4606
- })] })]
4607
- }), /* @__PURE__ */ jsx("button", {
4608
- type: "button",
4609
- role: "switch",
4610
- "aria-checked": config.blockOutbound,
4611
- "aria-label": "Block outbound traffic",
4612
- onClick: () => onUpdate({ blockOutbound: !config.blockOutbound }),
4613
- className: cn$1("relative inline-flex h-6 w-11 items-center rounded-full transition-colors", config.blockOutbound ? "bg-destructive" : "bg-surface-container-high"),
4614
- children: /* @__PURE__ */ jsx("span", { className: cn$1("inline-block h-4 w-4 rounded-full bg-white transition-transform shadow-sm", config.blockOutbound ? "translate-x-6" : "translate-x-1") })
4615
- })]
4616
- }), /* @__PURE__ */ jsxs("div", { children: [
4617
- /* @__PURE__ */ jsx("h4", {
4618
- className: "text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider",
4619
- children: "Allowlist (CIDR)"
4620
- }),
4621
- config.allowList.length > 0 ? /* @__PURE__ */ jsx("div", {
4622
- className: "space-y-1.5 mb-3",
4623
- children: config.allowList.map((cidr) => /* @__PURE__ */ jsxs("div", {
4624
- className: "flex items-center justify-between rounded border border-[var(--md3-outline-variant)] bg-surface-container-high px-3 py-2",
4625
- children: [/* @__PURE__ */ jsx("span", {
4626
- className: "font-mono text-xs text-foreground",
4627
- children: cidr
4628
- }), /* @__PURE__ */ jsx("button", {
4629
- type: "button",
4630
- "aria-label": `Remove ${cidr} from allowlist`,
4631
- onClick: () => handleRemoveCidr(cidr),
4632
- className: `p-2 text-muted-foreground hover:text-destructive transition-colors rounded ${focusRing}`,
4633
- children: /* @__PURE__ */ jsx(Trash2, { className: "h-3 w-3" })
4634
- })]
4635
- }, cidr))
4636
- }) : /* @__PURE__ */ jsx("p", {
4637
- className: "text-xs text-muted-foreground mb-3",
4638
- children: "No CIDR rules configured. All traffic is allowed."
4639
- }),
4640
- /* @__PURE__ */ jsxs("div", {
4641
- className: "flex items-center gap-3",
4642
- children: [/* @__PURE__ */ jsx("input", {
4643
- type: "text",
4644
- "aria-label": "CIDR to allow",
4645
- placeholder: "CIDR (e.g. 10.0.0.0/8)",
4646
- value: newCidr,
4647
- onChange: (e) => setNewCidr(e.target.value),
4648
- onKeyDown: (e) => e.key === "Enter" && handleAddCidr(),
4649
- className: `flex-1 rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField}`
4650
- }), /* @__PURE__ */ jsxs("button", {
4651
- type: "button",
4652
- onClick: handleAddCidr,
4653
- disabled: !newCidr.trim(),
4654
- className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
4655
- children: [/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }), "Add"]
4656
- })]
4657
- })
4658
- ] })]
4659
- });
4660
- }
4661
- //#endregion
4662
- //#region src/dashboard/backend-config.tsx
4663
- function BackendConfig({ status, mcpServers, onAddMcp, onRemoveMcp, onRestart, loading = false, className }) {
4664
- const [showAddMcp, setShowAddMcp] = React$1.useState(false);
4665
- const [mcpName, setMcpName] = React$1.useState("");
4666
- const [mcpCommand, setMcpCommand] = React$1.useState("");
4667
- const [mcpArgs, setMcpArgs] = React$1.useState("");
4668
- const handleAddMcp = () => {
4669
- const name = mcpName.trim();
4670
- const command = mcpCommand.trim();
4671
- if (name && command) {
4672
- onAddMcp({
4673
- name,
4674
- command,
4675
- args: mcpArgs.trim() ? mcpArgs.trim().split(/\s+/) : void 0
4676
- });
4677
- setMcpName("");
4678
- setMcpCommand("");
4679
- setMcpArgs("");
4680
- setShowAddMcp(false);
4681
- }
4682
- };
4683
- if (loading || !status) return /* @__PURE__ */ jsxs("div", {
4684
- className: cn$1("rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container p-6 text-center", className),
4685
- children: [/* @__PURE__ */ jsx(Bot, {
4686
- className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2",
4687
- "data-motion": "essential"
4688
- }), /* @__PURE__ */ jsx("p", {
4689
- className: "text-sm text-muted-foreground",
4690
- children: "Loading backend status..."
4691
- })]
4692
- });
4693
- return /* @__PURE__ */ jsxs("div", {
4694
- className: cn$1("space-y-4", className),
4695
- children: [/* @__PURE__ */ jsxs("div", {
4696
- className: "rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container overflow-hidden",
4697
- children: [/* @__PURE__ */ jsxs("div", {
4698
- className: "px-4 py-3 border-b border-[var(--md3-outline-variant)] bg-surface-container-high flex items-center justify-between",
4699
- children: [/* @__PURE__ */ jsx("h4", {
4700
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wider",
4701
- children: "Agent Status"
4702
- }), onRestart ? /* @__PURE__ */ jsx("button", {
4703
- type: "button",
4704
- onClick: onRestart,
4705
- className: "inline-flex items-center gap-1.5 rounded-md bg-surface-container-high px-2.5 py-1 text-xs font-medium text-foreground hover:bg-surface-container-highest transition-colors border border-[var(--md3-outline-variant)]",
4706
- children: "Restart"
4707
- }) : null]
4708
- }), /* @__PURE__ */ jsx("div", {
4709
- className: "p-4",
4710
- children: /* @__PURE__ */ jsxs("dl", {
4711
- className: "grid grid-cols-[100px_1fr] gap-y-3 text-sm",
4712
- children: [
4713
- /* @__PURE__ */ jsx("dt", {
4714
- className: "text-muted-foreground",
4715
- children: "Status"
4716
- }),
4717
- /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("span", {
4718
- className: cn$1("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider", status.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-destructive/10 text-destructive"),
4719
- children: status.running ? "Running" : "Stopped"
4720
- }) }),
4721
- /* @__PURE__ */ jsx("dt", {
4722
- className: "text-muted-foreground",
4723
- children: "Model"
4724
- }),
4725
- /* @__PURE__ */ jsx("dd", {
4726
- className: "font-mono text-xs",
4727
- children: status.model ?? "Default"
4728
- }),
4729
- status.provider && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("dt", {
4730
- className: "text-muted-foreground",
4731
- children: "Provider"
4732
- }), /* @__PURE__ */ jsx("dd", {
4733
- className: "font-mono text-xs",
4734
- children: status.provider
4735
- })] })
4736
- ]
4737
- })
4738
- })]
4739
- }), /* @__PURE__ */ jsxs("div", {
4740
- className: "rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container overflow-hidden",
4741
- children: [
4742
- /* @__PURE__ */ jsxs("div", {
4743
- className: "px-4 py-3 border-b border-[var(--md3-outline-variant)] bg-surface-container-high flex items-center justify-between",
4744
- children: [/* @__PURE__ */ jsxs("h4", {
4745
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2",
4746
- children: [/* @__PURE__ */ jsx(Wrench, { className: "h-3.5 w-3.5" }), "MCP Servers"]
4747
- }), /* @__PURE__ */ jsxs("button", {
4748
- type: "button",
4749
- onClick: () => setShowAddMcp(!showAddMcp),
4750
- className: "inline-flex items-center gap-1.5 rounded-md bg-primary/20 border border-primary/30 px-2.5 py-1 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
4751
- children: [/* @__PURE__ */ jsx(Plus, { className: "h-3 w-3" }), "Add"]
4752
- })]
4753
- }),
4754
- mcpServers.length > 0 ? /* @__PURE__ */ jsx("div", {
4755
- className: "divide-y divide-border",
4756
- children: mcpServers.map((s) => /* @__PURE__ */ jsxs("div", {
4757
- className: "flex items-center justify-between px-4 py-3",
4758
- children: [/* @__PURE__ */ jsxs("div", {
4759
- className: "flex items-center gap-3 min-w-0",
4760
- children: [/* @__PURE__ */ jsx(Server, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }), /* @__PURE__ */ jsxs("div", {
4761
- className: "min-w-0",
4762
- children: [/* @__PURE__ */ jsx("p", {
4763
- className: "text-sm font-medium text-foreground truncate",
4764
- children: s.name
4765
- }), /* @__PURE__ */ jsxs("p", {
4766
- className: "text-xs font-mono text-muted-foreground truncate",
4767
- children: [
4768
- s.command,
4769
- " ",
4770
- s.args?.join(" ") ?? ""
4771
- ]
4772
- })]
4773
- })]
4774
- }), /* @__PURE__ */ jsxs("div", {
4775
- className: "flex items-center gap-2 shrink-0",
4776
- children: [s.status && /* @__PURE__ */ jsx("span", {
4777
- className: cn$1("inline-flex items-center rounded-full px-1.5 py-0.5 text-[9px] font-bold uppercase", s.status === "running" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : s.status === "error" ? "bg-destructive/10 text-destructive" : "bg-surface-container-high text-muted-foreground"),
4778
- children: s.status
4779
- }), /* @__PURE__ */ jsx("button", {
4780
- type: "button",
4781
- "aria-label": `Remove ${s.name} MCP server`,
4782
- onClick: () => onRemoveMcp(s.name),
4783
- className: `p-2 text-muted-foreground hover:text-destructive transition-colors rounded ${focusRing}`,
4784
- children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
4785
- })]
4786
- })]
4787
- }, s.name))
4788
- }) : /* @__PURE__ */ jsx("div", {
4789
- className: "p-4 text-center",
4790
- children: /* @__PURE__ */ jsx("p", {
4791
- className: "text-xs text-muted-foreground",
4792
- children: "No MCP servers configured"
4793
- })
4794
- }),
4795
- showAddMcp && /* @__PURE__ */ jsxs("div", {
4796
- className: "p-4 border-t border-[var(--md3-outline-variant)] bg-surface-container-high space-y-2",
4797
- children: [
4798
- /* @__PURE__ */ jsxs("label", {
4799
- className: "block space-y-1 text-xs font-medium text-muted-foreground",
4800
- children: [/* @__PURE__ */ jsx("span", { children: "Server name" }), /* @__PURE__ */ jsx("input", {
4801
- type: "text",
4802
- value: mcpName,
4803
- onChange: (e) => setMcpName(e.target.value),
4804
- className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm text-foreground ${focusField}`
4805
- })]
4806
- }),
4807
- /* @__PURE__ */ jsxs("label", {
4808
- className: "block space-y-1 text-xs font-medium text-muted-foreground",
4809
- children: [/* @__PURE__ */ jsx("span", { children: "Command" }), /* @__PURE__ */ jsx("input", {
4810
- type: "text",
4811
- placeholder: "npx @server/mcp",
4812
- value: mcpCommand,
4813
- onChange: (e) => setMcpCommand(e.target.value),
4814
- className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField}`
4815
- })]
4816
- }),
4817
- /* @__PURE__ */ jsxs("label", {
4818
- className: "block space-y-1 text-xs font-medium text-muted-foreground",
4819
- children: [/* @__PURE__ */ jsx("span", { children: "Arguments (optional)" }), /* @__PURE__ */ jsx("input", {
4820
- type: "text",
4821
- placeholder: "Space-separated arguments",
4822
- value: mcpArgs,
4823
- onChange: (e) => setMcpArgs(e.target.value),
4824
- className: `w-full rounded-lg border bg-surface-container-low px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField}`
4825
- })]
4826
- }),
4827
- /* @__PURE__ */ jsxs("div", {
4828
- className: "flex justify-end gap-2 pt-1",
4829
- children: [/* @__PURE__ */ jsx("button", {
4830
- type: "button",
4831
- onClick: () => setShowAddMcp(false),
4832
- className: "rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors",
4833
- children: "Cancel"
4834
- }), /* @__PURE__ */ jsx("button", {
4835
- type: "button",
4836
- onClick: handleAddMcp,
4837
- disabled: !mcpName.trim() || !mcpCommand.trim(),
4838
- className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50",
4839
- children: "Add Server"
4840
- })]
4841
- })
4842
- ]
4843
- })
4844
- ]
4845
- })]
4846
- });
4847
- }
4848
- //#endregion
4849
3892
  //#region src/dashboard/snapshot-list.tsx
4850
3893
  function formatBytes(bytes) {
4851
3894
  if (bytes == null || bytes < 0) return "-";
@@ -5090,28 +4133,4 @@ function PromoBanner({ title, description, buttonLabel, href, onClick, icon, dis
5090
4133
  });
5091
4134
  }
5092
4135
  //#endregion
5093
- //#region src/dashboard/info-panel.tsx
5094
- function InfoPanel({ label, title, description, className }) {
5095
- return /* @__PURE__ */ jsxs("div", {
5096
- className: cn$1("rounded-lg bg-[var(--brand-strong)] p-5 text-[var(--brand-strong-text)] relative overflow-hidden", className),
5097
- children: [/* @__PURE__ */ jsxs("div", {
5098
- className: "relative z-10",
5099
- children: [
5100
- /* @__PURE__ */ jsx("p", {
5101
- className: "text-[10px] font-bold uppercase tracking-widest text-[var(--brand-strong-text-dim)]",
5102
- children: label
5103
- }),
5104
- /* @__PURE__ */ jsx("h3", {
5105
- className: "mt-1 text-lg font-bold",
5106
- children: title
5107
- }),
5108
- /* @__PURE__ */ jsx("p", {
5109
- className: "mt-1 text-sm text-[var(--brand-strong-text-muted)]",
5110
- children: description
5111
- })
5112
- ]
5113
- }), /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 h-full w-1/3 bg-white/5 -skew-x-12 translate-x-12 pointer-events-none" })]
5114
- });
5115
- }
5116
- //#endregion
5117
- export { SidebarPanelHeader as $, SandboxStatusPill as A, ProfileAvatar as B, PlanCards as C, SandboxCard as D, NewSandboxCard as E, ClusterStatusBar as F, RailHeader as G, RailCollapseToggle as H, INSUFFICIENT_BALANCE_CODE as I, RailThemeToggle as J, RailModeButton as K, OutOfCreditsModal as L, ActivityFeed as M, ResourceSnapshot as N, canAdminSandbox as O, ResourceMeter as P, SidebarPanelContent as Q, parseInsufficientBalance as R, BackendSelector as S, SandboxTable as T, RailExpandable as U, RailButton as V, RailFlyout as W, SidebarContent as X, Sidebar as Y, SidebarPanel as Z, HARNESS_OPTIONS as _, NetworkConfig as a, SIDEBAR_MOBILE_WIDTH as at, HARNESS_BRAND as b, GitPanel as c, SIDEBAR_RAIL_WIDTH as ct, VariantList as d, useSidebar as dt, SidebarRail as et, MetricAreaChart as f, DashboardLayout as g, SidebarLayout as h, BackendConfig as i, RailTooltip as it, sandboxStatus as j, SANDBOX_STATUS as k, UsageSummary as l, SIDEBAR_TOTAL_WIDTH as lt, ProfileSelector as m, PromoBanner as n, SidebarRailHeader as nt, ProcessList as o, SIDEBAR_PANEL_WIDTH as ot, ProfileComparison as p, RailSeparator as q, SnapshotList as r, SidebarRailNav as rt, PortsList as s, SIDEBAR_RAIL_LABELED_WIDTH as st, InfoPanel as t, SidebarRailFooter as tt, SystemLogsViewer as u, SidebarProvider as ut, HarnessPicker as v, InvoiceTable as w, HarnessLogo as x, chatCapableHarnesses as y, CreditBalance as z };
4136
+ export { useSidebar as $, parseInsufficientBalance as A, SidebarPanel as B, SandboxStatusPill as C, ResourceMeter as D, ResourceSnapshot as E, RailHeader as F, SidebarRailNav as G, SidebarPanelHeader as H, RailModeButton as I, SIDEBAR_PANEL_WIDTH as J, RailTooltip as K, RailSeparator as L, RailButton as M, RailExpandable as N, INSUFFICIENT_BALANCE_CODE as O, RailFlyout as P, SidebarProvider as Q, Sidebar as R, SANDBOX_STATUS as S, ActivityFeed as T, SidebarRail as U, SidebarPanelContent as V, SidebarRailFooter as W, SIDEBAR_RAIL_WIDTH as X, SIDEBAR_RAIL_LABELED_WIDTH as Y, SIDEBAR_TOTAL_WIDTH as Z, BackendSelector as _, PortsList as a, SandboxCard as b, SystemLogsViewer as c, DashboardLayout as d, HARNESS_OPTIONS as f, HarnessLogo as g, HARNESS_BRAND as h, TemplateCard as i, ProfileAvatar as j, OutOfCreditsModal as k, MetricAreaChart as l, chatCapableHarnesses as m, SnapshotList as n, GitPanel as o, HarnessPicker as p, SIDEBAR_MOBILE_WIDTH as q, ProcessList as r, UsageSummary as s, PromoBanner as t, SidebarLayout as u, SandboxTable as v, sandboxStatus as w, canAdminSandbox as x, NewSandboxCard as y, SidebarContent as z };