@tangle-network/sandbox-ui 0.10.9 → 0.11.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.
@@ -1274,9 +1274,376 @@ function BackendSelector({
1274
1274
  ] });
1275
1275
  }
1276
1276
 
1277
+ // src/dashboard/harness-picker.tsx
1278
+ import { jsx as jsx12 } from "react/jsx-runtime";
1279
+ var HARNESS_OPTIONS = [
1280
+ {
1281
+ type: "opencode",
1282
+ label: "OpenCode",
1283
+ description: "Default agent \u2014 broad model support, deterministic streaming"
1284
+ },
1285
+ {
1286
+ type: "claude-code",
1287
+ label: "Claude Code",
1288
+ description: "Native Claude skills and tools (requires ANTHROPIC_API_KEY)"
1289
+ },
1290
+ {
1291
+ type: "codex",
1292
+ label: "Codex",
1293
+ description: "OpenAI Codex CLI (requires OPENAI_API_KEY)"
1294
+ },
1295
+ {
1296
+ type: "amp",
1297
+ label: "AMP",
1298
+ description: "Sourcegraph AMP agent"
1299
+ },
1300
+ {
1301
+ type: "factory-droids",
1302
+ label: "Factory Droids",
1303
+ description: "Factory Droid agent"
1304
+ },
1305
+ {
1306
+ type: "cli-base",
1307
+ label: "CLI base (no agent)",
1308
+ description: "Shell tools only \u2014 for non-AI scheduled tasks"
1309
+ }
1310
+ ];
1311
+ function HarnessPicker({
1312
+ value,
1313
+ onChange,
1314
+ available,
1315
+ optionsOverride,
1316
+ label = "Agent harness",
1317
+ ...rest
1318
+ }) {
1319
+ const allowed = new Set(available ?? HARNESS_OPTIONS.map((h) => h.type));
1320
+ const backends = HARNESS_OPTIONS.filter((h) => allowed.has(h.type)).map((h) => {
1321
+ const override = optionsOverride?.[h.type];
1322
+ return {
1323
+ type: h.type,
1324
+ label: override?.label ?? h.label,
1325
+ description: override?.description ?? h.description
1326
+ };
1327
+ });
1328
+ return /* @__PURE__ */ jsx12(
1329
+ BackendSelector,
1330
+ {
1331
+ backends,
1332
+ selected: value,
1333
+ onChange: (next) => onChange(next),
1334
+ label,
1335
+ ...rest
1336
+ }
1337
+ );
1338
+ }
1339
+
1340
+ // src/dashboard/model-picker.tsx
1341
+ import * as React4 from "react";
1342
+ import { ChevronDown as ChevronDown2, Search, Sparkles, Zap, Brain, Star, Loader2 } from "lucide-react";
1343
+ import * as Popover from "@radix-ui/react-dropdown-menu";
1344
+ import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1345
+ function canonicalModelId(model) {
1346
+ const id = model.id;
1347
+ if (id.includes("/")) return id;
1348
+ const provider = model._provider ?? model.provider;
1349
+ return provider ? `${provider}/${id}` : id;
1350
+ }
1351
+ function formatPricing(pricing) {
1352
+ const prompt = Number(pricing?.prompt ?? 0);
1353
+ const completion = Number(pricing?.completion ?? 0);
1354
+ if (!prompt && !completion) return null;
1355
+ const fmt = (n) => {
1356
+ const perM = n * 1e6;
1357
+ if (perM === 0) return "0";
1358
+ if (perM >= 1) return `$${perM.toFixed(2)}`;
1359
+ return `$${perM.toFixed(2)}`;
1360
+ };
1361
+ return `${fmt(prompt)} / ${fmt(completion)} per 1M`;
1362
+ }
1363
+ function formatContext(ctx) {
1364
+ if (!ctx) return null;
1365
+ if (ctx >= 1e6) return `${(ctx / 1e6).toFixed(1)}M ctx`;
1366
+ if (ctx >= 1e3) return `${Math.round(ctx / 1e3)}k ctx`;
1367
+ return `${ctx} ctx`;
1368
+ }
1369
+ var DEFAULT_PRESETS = [
1370
+ {
1371
+ id: "fast",
1372
+ label: "Fast",
1373
+ hint: "Cheapest, lowest latency",
1374
+ icon: Zap,
1375
+ match: (models) => {
1376
+ const ids = models.map(canonicalModelId);
1377
+ return ids.find((m) => /gpt-5\.\d+-mini$/.test(m)) ?? ids.find((m) => /gpt-5-mini$/.test(m)) ?? ids.find((m) => m.endsWith("/claude-haiku-4.5")) ?? ids.find((m) => /haiku/.test(m));
1378
+ }
1379
+ },
1380
+ {
1381
+ id: "balanced",
1382
+ label: "Balanced",
1383
+ hint: "Best value for most chat",
1384
+ icon: Sparkles,
1385
+ match: (models) => {
1386
+ const ids = models.map(canonicalModelId);
1387
+ return ids.find((m) => /^openai\/gpt-5\.\d+$/.test(m)) ?? ids.find((m) => /^openai\/gpt-5$/.test(m)) ?? ids.find((m) => m.endsWith("/claude-sonnet-4-6")) ?? ids.find((m) => /sonnet/.test(m));
1388
+ }
1389
+ },
1390
+ {
1391
+ id: "best",
1392
+ label: "Best",
1393
+ hint: "Hardest reasoning, highest quality",
1394
+ icon: Brain,
1395
+ match: (models) => {
1396
+ const ids = models.map(canonicalModelId);
1397
+ return ids.find((m) => /^openai\/gpt-5\.\d+-pro$/.test(m)) ?? ids.find((m) => /^openai\/o3$/.test(m)) ?? ids.find((m) => m.endsWith("/claude-opus-4-7")) ?? ids.find((m) => /opus/.test(m));
1398
+ }
1399
+ }
1400
+ ];
1401
+ function ModelPicker({
1402
+ value,
1403
+ onChange,
1404
+ models,
1405
+ loading = false,
1406
+ recents,
1407
+ presets = DEFAULT_PRESETS,
1408
+ excludeProviders,
1409
+ modalities,
1410
+ variant = "field",
1411
+ label = "Model",
1412
+ placeholder = "Choose a model",
1413
+ className,
1414
+ disabled
1415
+ }) {
1416
+ const [query, setQuery] = React4.useState("");
1417
+ const [open, setOpen] = React4.useState(false);
1418
+ const filtered = React4.useMemo(() => {
1419
+ const excluded = new Set((excludeProviders ?? []).map((p) => p.toLowerCase()));
1420
+ const allowedModalities = modalities ? new Set(modalities) : null;
1421
+ const q = query.trim().toLowerCase();
1422
+ return models.filter((m) => {
1423
+ const provider = (m._provider ?? m.provider ?? "").toLowerCase();
1424
+ if (excluded.has(provider)) return false;
1425
+ if (allowedModalities && m.architecture?.modality && !allowedModalities.has(m.architecture.modality)) return false;
1426
+ if (!q) return true;
1427
+ const id = canonicalModelId(m).toLowerCase();
1428
+ const name = (m.name ?? "").toLowerCase();
1429
+ return id.includes(q) || name.includes(q) || provider.includes(q);
1430
+ });
1431
+ }, [models, query, modalities, excludeProviders]);
1432
+ const grouped = React4.useMemo(() => {
1433
+ const groups = /* @__PURE__ */ new Map();
1434
+ for (const m of filtered) {
1435
+ const provider = m._provider ?? m.provider ?? "other";
1436
+ const list = groups.get(provider);
1437
+ if (list) list.push(m);
1438
+ else groups.set(provider, [m]);
1439
+ }
1440
+ return Array.from(groups.entries()).sort(([a], [b]) => a.localeCompare(b));
1441
+ }, [filtered]);
1442
+ const current = React4.useMemo(
1443
+ () => models.find((m) => canonicalModelId(m) === value),
1444
+ [models, value]
1445
+ );
1446
+ const currentLabel = current?.name ?? current?.id ?? value;
1447
+ const recentIds = React4.useMemo(() => {
1448
+ if (!recents?.length) return [];
1449
+ const lookup = new Map(models.map((m) => [canonicalModelId(m), m]));
1450
+ return recents.map((id) => lookup.get(id)).filter((m) => Boolean(m)).slice(0, 4);
1451
+ }, [recents, models]);
1452
+ const handleSelect = (id) => {
1453
+ onChange(id);
1454
+ setOpen(false);
1455
+ setQuery("");
1456
+ };
1457
+ const trigger = variant === "pill" ? /* @__PURE__ */ jsxs11(
1458
+ "button",
1459
+ {
1460
+ type: "button",
1461
+ disabled,
1462
+ className: cn(
1463
+ "inline-flex items-center gap-1.5 rounded-full border border-border bg-card",
1464
+ "px-2.5 py-1 text-xs font-medium text-foreground",
1465
+ "transition-colors duration-[var(--transition-fast)]",
1466
+ "hover:border-primary/30 hover:bg-accent/30",
1467
+ "focus:outline-none focus:border-primary/40",
1468
+ "data-[state=open]:border-primary/40 data-[state=open]:bg-accent/30",
1469
+ "disabled:opacity-50 disabled:cursor-not-allowed",
1470
+ className
1471
+ ),
1472
+ children: [
1473
+ /* @__PURE__ */ jsx13(Sparkles, { className: "h-3 w-3 text-muted-foreground" }),
1474
+ /* @__PURE__ */ jsx13("span", { className: "truncate max-w-[160px]", children: currentLabel || placeholder }),
1475
+ /* @__PURE__ */ jsx13(ChevronDown2, { className: "h-3 w-3 text-muted-foreground transition-transform data-[state=open]:rotate-180" })
1476
+ ]
1477
+ }
1478
+ ) : /* @__PURE__ */ jsxs11(
1479
+ "button",
1480
+ {
1481
+ type: "button",
1482
+ disabled,
1483
+ className: cn(
1484
+ "flex w-full items-center justify-between gap-2 rounded-[var(--radius-md)]",
1485
+ "border border-border bg-card px-3 py-2.5 text-sm text-left",
1486
+ "transition-colors duration-[var(--transition-fast)]",
1487
+ "hover:border-primary/20 hover:bg-accent/30",
1488
+ "focus:outline-none focus:border-primary/30",
1489
+ "data-[state=open]:border-primary/30 data-[state=open]:bg-accent/30",
1490
+ "disabled:opacity-50 disabled:cursor-not-allowed",
1491
+ className
1492
+ ),
1493
+ children: [
1494
+ /* @__PURE__ */ jsx13("span", { className: cn("truncate", current ? "text-foreground font-medium" : "text-muted-foreground"), children: currentLabel || placeholder }),
1495
+ /* @__PURE__ */ jsx13(ChevronDown2, { className: "h-4 w-4 shrink-0 text-muted-foreground transition-transform data-[state=open]:rotate-180" })
1496
+ ]
1497
+ }
1498
+ );
1499
+ return /* @__PURE__ */ jsxs11("div", { className: cn(variant === "field" ? "space-y-1.5" : "inline-flex", variant === "field" ? className : void 0), children: [
1500
+ variant === "field" && label && /* @__PURE__ */ jsx13("label", { className: "block text-xs font-medium text-muted-foreground uppercase tracking-[0.06em]", children: label }),
1501
+ /* @__PURE__ */ jsxs11(Popover.Root, { open, onOpenChange: setOpen, children: [
1502
+ /* @__PURE__ */ jsx13(Popover.Trigger, { asChild: true, children: trigger }),
1503
+ /* @__PURE__ */ jsx13(Popover.Portal, { children: /* @__PURE__ */ jsxs11(
1504
+ Popover.Content,
1505
+ {
1506
+ sideOffset: 4,
1507
+ align: variant === "pill" ? "start" : "start",
1508
+ className: cn(
1509
+ "z-50 w-[var(--radix-dropdown-menu-trigger-width)] min-w-[320px] max-w-[460px]",
1510
+ "max-h-[440px] overflow-hidden flex flex-col",
1511
+ "rounded-[var(--radius-md)] border border-border bg-card shadow-[var(--shadow-dropdown)]",
1512
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
1513
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1514
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
1515
+ ),
1516
+ children: [
1517
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 border-b border-border px-3 py-2", children: [
1518
+ /* @__PURE__ */ jsx13(Search, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }),
1519
+ /* @__PURE__ */ jsx13(
1520
+ "input",
1521
+ {
1522
+ type: "text",
1523
+ value: query,
1524
+ onChange: (e) => setQuery(e.target.value),
1525
+ placeholder: "Search models...",
1526
+ autoFocus: true,
1527
+ className: "flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
1528
+ }
1529
+ ),
1530
+ loading && /* @__PURE__ */ jsx13(Loader2, { className: "h-3.5 w-3.5 animate-spin text-muted-foreground" })
1531
+ ] }),
1532
+ /* @__PURE__ */ jsxs11("div", { className: "flex-1 overflow-y-auto", children: [
1533
+ !query && presets.length > 0 && /* @__PURE__ */ jsx13(Section, { label: "Presets", children: presets.map((preset) => {
1534
+ const Icon2 = preset.icon ?? Star;
1535
+ const matchedId = preset.match(models);
1536
+ if (!matchedId) return null;
1537
+ const matched = models.find((m) => canonicalModelId(m) === matchedId);
1538
+ const isCurrent = matchedId === value;
1539
+ return /* @__PURE__ */ jsxs11(
1540
+ PickerItem,
1541
+ {
1542
+ onSelect: () => handleSelect(matchedId),
1543
+ active: isCurrent,
1544
+ children: [
1545
+ /* @__PURE__ */ jsx13(Icon2, { className: "h-3.5 w-3.5 shrink-0 text-[var(--accent-text)]" }),
1546
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
1547
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
1548
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium", children: preset.label }),
1549
+ /* @__PURE__ */ jsxs11("span", { className: "text-[10px] text-muted-foreground truncate", children: [
1550
+ "\u2192 ",
1551
+ matched?.name ?? matchedId
1552
+ ] })
1553
+ ] }),
1554
+ /* @__PURE__ */ jsx13("span", { className: "text-xs text-muted-foreground", children: preset.hint })
1555
+ ] })
1556
+ ]
1557
+ },
1558
+ preset.id
1559
+ );
1560
+ }) }),
1561
+ !query && recentIds.length > 0 && /* @__PURE__ */ jsx13(Section, { label: "Recent", children: recentIds.map((m) => /* @__PURE__ */ jsx13(
1562
+ ModelRow,
1563
+ {
1564
+ model: m,
1565
+ active: canonicalModelId(m) === value,
1566
+ onSelect: handleSelect
1567
+ },
1568
+ `recent-${canonicalModelId(m)}`
1569
+ )) }),
1570
+ grouped.length === 0 ? /* @__PURE__ */ jsx13("div", { className: "px-3 py-8 text-center text-xs text-muted-foreground", children: loading ? "Loading models..." : query ? "No models match." : "No models available." }) : grouped.map(([provider, list]) => /* @__PURE__ */ jsx13(Section, { label: provider, children: list.map((m) => /* @__PURE__ */ jsx13(
1571
+ ModelRow,
1572
+ {
1573
+ model: m,
1574
+ active: canonicalModelId(m) === value,
1575
+ onSelect: handleSelect
1576
+ },
1577
+ canonicalModelId(m)
1578
+ )) }, provider))
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs11("div", { className: "border-t border-border px-3 py-1.5 text-[10px] text-muted-foreground", children: [
1581
+ filtered.length,
1582
+ " of ",
1583
+ models.length,
1584
+ " model",
1585
+ models.length === 1 ? "" : "s"
1586
+ ] })
1587
+ ]
1588
+ }
1589
+ ) })
1590
+ ] })
1591
+ ] });
1592
+ }
1593
+ function Section({ label, children }) {
1594
+ return /* @__PURE__ */ jsxs11("div", { className: "py-1", children: [
1595
+ /* @__PURE__ */ jsx13("div", { className: "px-3 pt-1.5 pb-0.5 text-[10px] font-mono uppercase tracking-widest text-muted-foreground", children: label }),
1596
+ /* @__PURE__ */ jsx13("div", { children })
1597
+ ] });
1598
+ }
1599
+ function PickerItem({
1600
+ onSelect,
1601
+ active,
1602
+ children
1603
+ }) {
1604
+ return /* @__PURE__ */ jsx13(
1605
+ Popover.Item,
1606
+ {
1607
+ onSelect: (e) => {
1608
+ e.preventDefault();
1609
+ onSelect();
1610
+ },
1611
+ className: cn(
1612
+ "flex cursor-pointer items-start gap-2 px-3 py-2 outline-none",
1613
+ "transition-colors duration-[var(--transition-fast)]",
1614
+ "hover:bg-accent/40 focus:bg-accent/40",
1615
+ active && "bg-[var(--accent-surface-soft)] text-[var(--accent-text)]"
1616
+ ),
1617
+ children
1618
+ }
1619
+ );
1620
+ }
1621
+ function ModelRow({
1622
+ model,
1623
+ active,
1624
+ onSelect
1625
+ }) {
1626
+ const id = canonicalModelId(model);
1627
+ const pricing = formatPricing(model.pricing);
1628
+ const ctx = formatContext(model.context_length);
1629
+ return /* @__PURE__ */ jsx13(PickerItem, { onSelect: () => onSelect(id), active, children: /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
1630
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-baseline justify-between gap-2", children: [
1631
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium truncate", children: model.name ?? model.id }),
1632
+ ctx && /* @__PURE__ */ jsx13("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: ctx })
1633
+ ] }),
1634
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-[11px] text-muted-foreground", children: [
1635
+ /* @__PURE__ */ jsx13("span", { className: "truncate", children: id }),
1636
+ pricing && /* @__PURE__ */ jsxs11(Fragment7, { children: [
1637
+ /* @__PURE__ */ jsx13("span", { className: "shrink-0", children: "\xB7" }),
1638
+ /* @__PURE__ */ jsx13("span", { className: "shrink-0 font-mono", children: pricing })
1639
+ ] })
1640
+ ] })
1641
+ ] }) });
1642
+ }
1643
+
1277
1644
  // src/dashboard/profile-selector.tsx
1278
- import { Check as Check2, ChevronDown as ChevronDown2, Plus as Plus3, Settings } from "lucide-react";
1279
- import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1645
+ import { Check as Check2, ChevronDown as ChevronDown3, Plus as Plus3, Settings } from "lucide-react";
1646
+ import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1280
1647
  function ProfileSelector({
1281
1648
  profiles,
1282
1649
  selectedId,
@@ -1291,77 +1658,77 @@ function ProfileSelector({
1291
1658
  const selected = profiles.find((p) => p.id === selectedId);
1292
1659
  const builtinProfiles = profiles.filter((p) => p.is_builtin);
1293
1660
  const customProfiles = profiles.filter((p) => !p.is_builtin);
1294
- return /* @__PURE__ */ jsxs11("div", { className, children: [
1295
- label && /* @__PURE__ */ jsx12("label", { className: "mb-2 block font-medium text-sm", children: label }),
1296
- /* @__PURE__ */ jsxs11(DropdownMenu, { children: [
1297
- /* @__PURE__ */ jsx12(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(Button, { variant: "outline", className: "w-full justify-between", children: [
1298
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: selected ? selected.name : placeholder }),
1299
- /* @__PURE__ */ jsx12(ChevronDown2, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
1661
+ return /* @__PURE__ */ jsxs12("div", { className, children: [
1662
+ label && /* @__PURE__ */ jsx14("label", { className: "mb-2 block font-medium text-sm", children: label }),
1663
+ /* @__PURE__ */ jsxs12(DropdownMenu, { children: [
1664
+ /* @__PURE__ */ jsx14(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(Button, { variant: "outline", className: "w-full justify-between", children: [
1665
+ /* @__PURE__ */ jsx14("span", { className: "truncate", children: selected ? selected.name : placeholder }),
1666
+ /* @__PURE__ */ jsx14(ChevronDown3, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
1300
1667
  ] }) }),
1301
- /* @__PURE__ */ jsxs11(DropdownMenuContent, { className: "w-[300px]", align: "start", children: [
1302
- /* @__PURE__ */ jsxs11(
1668
+ /* @__PURE__ */ jsxs12(DropdownMenuContent, { className: "w-[300px]", align: "start", children: [
1669
+ /* @__PURE__ */ jsxs12(
1303
1670
  DropdownMenuItem,
1304
1671
  {
1305
1672
  onClick: () => onSelect(null),
1306
1673
  className: "flex items-center justify-between",
1307
1674
  children: [
1308
- /* @__PURE__ */ jsx12("span", { children: placeholder }),
1309
- !selectedId && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1675
+ /* @__PURE__ */ jsx14("span", { children: placeholder }),
1676
+ !selectedId && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1310
1677
  ]
1311
1678
  }
1312
1679
  ),
1313
- builtinProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment7, { children: [
1314
- /* @__PURE__ */ jsx12(DropdownMenuSeparator, {}),
1315
- /* @__PURE__ */ jsx12(DropdownMenuLabel, { children: "Built-in Profiles" }),
1316
- builtinProfiles.map((profile) => /* @__PURE__ */ jsxs11(
1680
+ builtinProfiles.length > 0 && /* @__PURE__ */ jsxs12(Fragment8, { children: [
1681
+ /* @__PURE__ */ jsx14(DropdownMenuSeparator, {}),
1682
+ /* @__PURE__ */ jsx14(DropdownMenuLabel, { children: "Built-in Profiles" }),
1683
+ builtinProfiles.map((profile) => /* @__PURE__ */ jsxs12(
1317
1684
  DropdownMenuItem,
1318
1685
  {
1319
1686
  onClick: () => onSelect(profile),
1320
1687
  className: "flex flex-col items-start gap-1",
1321
1688
  children: [
1322
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center justify-between", children: [
1323
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1324
- /* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
1325
- profile.extends && /* @__PURE__ */ jsxs11(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
1689
+ /* @__PURE__ */ jsxs12("div", { className: "flex w-full items-center justify-between", children: [
1690
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1691
+ /* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
1692
+ profile.extends && /* @__PURE__ */ jsxs12(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
1326
1693
  "extends ",
1327
1694
  profile.extends
1328
1695
  ] })
1329
1696
  ] }),
1330
- selectedId === profile.id && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1697
+ selectedId === profile.id && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1331
1698
  ] }),
1332
- profile.description && /* @__PURE__ */ jsx12("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
1699
+ profile.description && /* @__PURE__ */ jsx14("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
1333
1700
  ]
1334
1701
  },
1335
1702
  profile.id
1336
1703
  ))
1337
1704
  ] }),
1338
- customProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment7, { children: [
1339
- /* @__PURE__ */ jsx12(DropdownMenuSeparator, {}),
1340
- /* @__PURE__ */ jsx12(DropdownMenuLabel, { children: "Custom Profiles" }),
1341
- customProfiles.map((profile) => /* @__PURE__ */ jsxs11(
1705
+ customProfiles.length > 0 && /* @__PURE__ */ jsxs12(Fragment8, { children: [
1706
+ /* @__PURE__ */ jsx14(DropdownMenuSeparator, {}),
1707
+ /* @__PURE__ */ jsx14(DropdownMenuLabel, { children: "Custom Profiles" }),
1708
+ customProfiles.map((profile) => /* @__PURE__ */ jsxs12(
1342
1709
  DropdownMenuItem,
1343
1710
  {
1344
1711
  onClick: () => onSelect(profile),
1345
1712
  className: "flex flex-col items-start gap-1",
1346
1713
  children: [
1347
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center justify-between", children: [
1348
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1349
- /* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
1350
- profile.model && /* @__PURE__ */ jsx12(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
1714
+ /* @__PURE__ */ jsxs12("div", { className: "flex w-full items-center justify-between", children: [
1715
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1716
+ /* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
1717
+ profile.model && /* @__PURE__ */ jsx14(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
1351
1718
  ] }),
1352
- selectedId === profile.id && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1719
+ selectedId === profile.id && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
1353
1720
  ] }),
1354
- profile.description && /* @__PURE__ */ jsx12("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
1355
- showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs11("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
1356
- /* @__PURE__ */ jsxs11("span", { children: [
1721
+ profile.description && /* @__PURE__ */ jsx14("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
1722
+ showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs12("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
1723
+ /* @__PURE__ */ jsxs12("span", { children: [
1357
1724
  profile.metrics.total_runs,
1358
1725
  " runs"
1359
1726
  ] }),
1360
- /* @__PURE__ */ jsxs11("span", { children: [
1727
+ /* @__PURE__ */ jsxs12("span", { children: [
1361
1728
  profile.metrics.success_rate.toFixed(0),
1362
1729
  "% success"
1363
1730
  ] }),
1364
- /* @__PURE__ */ jsxs11("span", { children: [
1731
+ /* @__PURE__ */ jsxs12("span", { children: [
1365
1732
  "~",
1366
1733
  (profile.metrics.avg_duration_ms / 1e3).toFixed(1),
1367
1734
  "s avg"
@@ -1372,26 +1739,26 @@ function ProfileSelector({
1372
1739
  profile.id
1373
1740
  ))
1374
1741
  ] }),
1375
- (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs11(Fragment7, { children: [
1376
- /* @__PURE__ */ jsx12(DropdownMenuSeparator, {}),
1377
- onCreateClick && /* @__PURE__ */ jsxs11(
1742
+ (onCreateClick || onManageClick) && /* @__PURE__ */ jsxs12(Fragment8, { children: [
1743
+ /* @__PURE__ */ jsx14(DropdownMenuSeparator, {}),
1744
+ onCreateClick && /* @__PURE__ */ jsxs12(
1378
1745
  DropdownMenuItem,
1379
1746
  {
1380
1747
  onClick: onCreateClick,
1381
1748
  className: "text-[var(--surface-info-text)]",
1382
1749
  children: [
1383
- /* @__PURE__ */ jsx12(Plus3, { className: "mr-2 h-4 w-4" }),
1750
+ /* @__PURE__ */ jsx14(Plus3, { className: "mr-2 h-4 w-4" }),
1384
1751
  "Create New Profile"
1385
1752
  ]
1386
1753
  }
1387
1754
  ),
1388
- onManageClick && /* @__PURE__ */ jsxs11(
1755
+ onManageClick && /* @__PURE__ */ jsxs12(
1389
1756
  DropdownMenuItem,
1390
1757
  {
1391
1758
  onClick: onManageClick,
1392
1759
  className: "text-muted-foreground",
1393
1760
  children: [
1394
- /* @__PURE__ */ jsx12(Settings, { className: "mr-2 h-4 w-4" }),
1761
+ /* @__PURE__ */ jsx14(Settings, { className: "mr-2 h-4 w-4" }),
1395
1762
  "Manage Profiles"
1396
1763
  ]
1397
1764
  }
@@ -1417,26 +1784,26 @@ function ProfileComparison({
1417
1784
  const fastestProfile = profilesWithMetrics.reduce(
1418
1785
  (best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
1419
1786
  );
1420
- return /* @__PURE__ */ jsxs11("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
1421
- /* @__PURE__ */ jsx12("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
1422
- /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
1787
+ return /* @__PURE__ */ jsxs12("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
1788
+ /* @__PURE__ */ jsx14("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
1789
+ /* @__PURE__ */ jsx14("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
1423
1790
  const isBestSuccess = profile.id === bestSuccess.id;
1424
1791
  const isFastest = profile.id === fastestProfile.id;
1425
- return /* @__PURE__ */ jsxs11(
1792
+ return /* @__PURE__ */ jsxs12(
1426
1793
  "div",
1427
1794
  {
1428
1795
  className: "flex items-center justify-between gap-4",
1429
1796
  children: [
1430
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1431
- /* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
1432
- isBestSuccess && /* @__PURE__ */ jsx12(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
1433
- isFastest && !isBestSuccess && /* @__PURE__ */ jsx12(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
1797
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1798
+ /* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
1799
+ isBestSuccess && /* @__PURE__ */ jsx14(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
1800
+ isFastest && !isBestSuccess && /* @__PURE__ */ jsx14(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
1434
1801
  ] }),
1435
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4 text-sm", children: [
1436
- /* @__PURE__ */ jsxs11("span", { children: [
1437
- /* @__PURE__ */ jsx12("span", { className: "text-muted-foreground", children: "Success:" }),
1802
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-4 text-sm", children: [
1803
+ /* @__PURE__ */ jsxs12("span", { children: [
1804
+ /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground", children: "Success:" }),
1438
1805
  " ",
1439
- /* @__PURE__ */ jsxs11(
1806
+ /* @__PURE__ */ jsxs12(
1440
1807
  "span",
1441
1808
  {
1442
1809
  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)]",
@@ -1447,13 +1814,13 @@ function ProfileComparison({
1447
1814
  }
1448
1815
  )
1449
1816
  ] }),
1450
- /* @__PURE__ */ jsxs11("span", { children: [
1451
- /* @__PURE__ */ jsx12("span", { className: "text-muted-foreground", children: "Avg:" }),
1817
+ /* @__PURE__ */ jsxs12("span", { children: [
1818
+ /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground", children: "Avg:" }),
1452
1819
  " ",
1453
1820
  ((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
1454
1821
  "s"
1455
1822
  ] }),
1456
- /* @__PURE__ */ jsxs11("span", { className: "text-muted-foreground", children: [
1823
+ /* @__PURE__ */ jsxs12("span", { className: "text-muted-foreground", children: [
1457
1824
  profile.metrics?.total_runs,
1458
1825
  " runs"
1459
1826
  ] })
@@ -1472,12 +1839,12 @@ import {
1472
1839
  CheckCircle2,
1473
1840
  Clock as Clock2,
1474
1841
  ExternalLink,
1475
- Loader2,
1842
+ Loader2 as Loader22,
1476
1843
  Timer,
1477
1844
  X,
1478
1845
  XCircle
1479
1846
  } from "lucide-react";
1480
- import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1847
+ import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1481
1848
  var statusConfig = {
1482
1849
  pending: {
1483
1850
  icon: Clock2,
@@ -1488,7 +1855,7 @@ var statusConfig = {
1488
1855
  animate: false
1489
1856
  },
1490
1857
  running: {
1491
- icon: Loader2,
1858
+ icon: Loader22,
1492
1859
  color: "text-primary",
1493
1860
  bg: "bg-[var(--accent-surface-soft)]",
1494
1861
  border: "border-border",
@@ -1561,19 +1928,19 @@ function VariantList({
1561
1928
  isActioning,
1562
1929
  className
1563
1930
  }) {
1564
- return /* @__PURE__ */ jsx13("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
1931
+ return /* @__PURE__ */ jsx15("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
1565
1932
  const status = statusConfig[variant.status];
1566
1933
  const StatusIcon = status.icon;
1567
1934
  const isSelected = variant.id === selectedId;
1568
- return /* @__PURE__ */ jsxs12(
1935
+ return /* @__PURE__ */ jsxs13(
1569
1936
  "div",
1570
1937
  {
1571
1938
  className: `cursor-pointer rounded-lg border px-3 py-2.5 transition-colors ${isSelected ? "border-primary/30 bg-[var(--accent-surface-soft)]" : "border-border bg-card hover:border-primary/20 hover:bg-muted/50"}`,
1572
1939
  onClick: () => onSelect?.(variant.id),
1573
1940
  children: [
1574
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1575
- /* @__PURE__ */ jsxs12(Badge, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
1576
- /* @__PURE__ */ jsx13(
1941
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1942
+ /* @__PURE__ */ jsxs13(Badge, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
1943
+ /* @__PURE__ */ jsx15(
1577
1944
  StatusIcon,
1578
1945
  {
1579
1946
  className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
@@ -1581,27 +1948,27 @@ function VariantList({
1581
1948
  ),
1582
1949
  status.label
1583
1950
  ] }),
1584
- /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
1585
- variant.sublabel && /* @__PURE__ */ jsxs12("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
1951
+ /* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
1952
+ variant.sublabel && /* @__PURE__ */ jsxs13("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
1586
1953
  "(",
1587
1954
  variant.sublabel,
1588
1955
  ")"
1589
1956
  ] }),
1590
- variant.durationMs && /* @__PURE__ */ jsxs12("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
1591
- /* @__PURE__ */ jsx13(Timer, { className: "h-3 w-3" }),
1957
+ variant.durationMs && /* @__PURE__ */ jsxs13("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
1958
+ /* @__PURE__ */ jsx15(Timer, { className: "h-3 w-3" }),
1592
1959
  (variant.durationMs / 1e3).toFixed(1),
1593
1960
  "s"
1594
1961
  ] }),
1595
- /* @__PURE__ */ jsxs12("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
1596
- variant.outcome && /* @__PURE__ */ jsx13(
1962
+ /* @__PURE__ */ jsxs13("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
1963
+ variant.outcome && /* @__PURE__ */ jsx15(
1597
1964
  Badge,
1598
1965
  {
1599
1966
  className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
1600
1967
  children: outcomeConfig[variant.outcome].label
1601
1968
  }
1602
1969
  ),
1603
- variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs12(Fragment8, { children: [
1604
- /* @__PURE__ */ jsxs12(
1970
+ variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs13(Fragment9, { children: [
1971
+ /* @__PURE__ */ jsxs13(
1605
1972
  Button,
1606
1973
  {
1607
1974
  variant: "outline",
@@ -1613,12 +1980,12 @@ function VariantList({
1613
1980
  },
1614
1981
  disabled: isActioning === variant.id,
1615
1982
  children: [
1616
- /* @__PURE__ */ jsx13(Check3, { className: "mr-1 h-3 w-3" }),
1983
+ /* @__PURE__ */ jsx15(Check3, { className: "mr-1 h-3 w-3" }),
1617
1984
  "Accept"
1618
1985
  ]
1619
1986
  }
1620
1987
  ),
1621
- /* @__PURE__ */ jsxs12(
1988
+ /* @__PURE__ */ jsxs13(
1622
1989
  Button,
1623
1990
  {
1624
1991
  variant: "outline",
@@ -1630,13 +1997,13 @@ function VariantList({
1630
1997
  },
1631
1998
  disabled: isActioning === variant.id,
1632
1999
  children: [
1633
- /* @__PURE__ */ jsx13(X, { className: "mr-1 h-3 w-3" }),
2000
+ /* @__PURE__ */ jsx15(X, { className: "mr-1 h-3 w-3" }),
1634
2001
  "Reject"
1635
2002
  ]
1636
2003
  }
1637
2004
  )
1638
2005
  ] }),
1639
- variant.detailsUrl && /* @__PURE__ */ jsx13(
2006
+ variant.detailsUrl && /* @__PURE__ */ jsx15(
1640
2007
  Button,
1641
2008
  {
1642
2009
  variant: "ghost",
@@ -1646,13 +2013,13 @@ function VariantList({
1646
2013
  e.stopPropagation();
1647
2014
  window.open(variant.detailsUrl, "_blank");
1648
2015
  },
1649
- children: /* @__PURE__ */ jsx13(ExternalLink, { className: "h-3.5 w-3.5" })
2016
+ children: /* @__PURE__ */ jsx15(ExternalLink, { className: "h-3.5 w-3.5" })
1650
2017
  }
1651
2018
  )
1652
2019
  ] })
1653
2020
  ] }),
1654
- variant.error && /* @__PURE__ */ jsx13("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
1655
- variant.summary && /* @__PURE__ */ jsx13("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
2021
+ variant.error && /* @__PURE__ */ jsx15("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
2022
+ variant.summary && /* @__PURE__ */ jsx15("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
1656
2023
  ]
1657
2024
  },
1658
2025
  variant.id
@@ -1691,6 +2058,12 @@ export {
1691
2058
  NewSandboxCard,
1692
2059
  SandboxTable,
1693
2060
  BackendSelector,
2061
+ HARNESS_OPTIONS,
2062
+ HarnessPicker,
2063
+ canonicalModelId,
2064
+ formatPricing,
2065
+ formatContext,
2066
+ ModelPicker,
1694
2067
  ProfileSelector,
1695
2068
  ProfileComparison,
1696
2069
  VariantList
@@ -1,4 +1,4 @@
1
- export { B as Backend, a as BackendSelector, b as BackendSelectorProps, C as ClusterStatusBar, c as ClusterStatusBarProps, d as ClusterStatusItem, e as CreditBalance, f as CreditBalanceProps, D as DashboardLayout, g as DashboardLayoutProps, ah as DashboardProfile, h as DashboardUser, I as Invoice, i as InvoiceTable, j as InvoiceTableProps, N as NavItem, k as NewSandboxCard, l as NewSandboxCardProps, m as PlanCardData, n as PlanCards, o as PlanCardsProps, ai as PlanFeature, p as ProductVariant, q as ProfileAvatar, r as ProfileAvatarProps, s as ProfileComparison, t as ProfileComparisonProps, u as ProfileSelector, v as ProfileSelectorProps, R as RailButton, w as RailButtonProps, x as RailModeButton, y as RailModeButtonProps, z as RailSeparator, A as RailSeparatorProps, E as ResourceMeter, F as ResourceMeterProps, S as SIDEBAR_MOBILE_WIDTH, G as SIDEBAR_PANEL_WIDTH, H as SIDEBAR_RAIL_WIDTH, J as SIDEBAR_TOTAL_WIDTH, K as SandboxCard, L as SandboxCardData, M as SandboxCardProps, O as SandboxStatus, Q as SandboxTable, T as SandboxTableProps, U as Sidebar, V as SidebarContent, W as SidebarContentProps, X as SidebarPanel, Y as SidebarPanelContent, Z as SidebarPanelContentProps, _ as SidebarPanelHeader, $ as SidebarPanelHeaderProps, a0 as SidebarPanelProps, a1 as SidebarProps, a2 as SidebarProvider, a3 as SidebarProviderProps, a4 as SidebarRail, a5 as SidebarRailFooter, a6 as SidebarRailFooterProps, a7 as SidebarRailHeader, a8 as SidebarRailHeaderProps, a9 as SidebarRailNav, aa as SidebarRailNavProps, ab as SidebarRailProps, ac as SidebarUser, aj as TeamRole, ak as Variant, ae as VariantList, af as VariantListProps, al as VariantOutcome, am as VariantStatus, an as canAdminSandbox, ag as useSidebar } from './variant-list-DAhiR-7S.js';
1
+ export { B as Backend, a as BackendSelector, b as BackendSelectorProps, C as ClusterStatusBar, c as ClusterStatusBarProps, d as ClusterStatusItem, e as CreditBalance, f as CreditBalanceProps, D as DashboardLayout, g as DashboardLayoutProps, at as DashboardProfile, h as DashboardUser, H as HARNESS_OPTIONS, i as HarnessPicker, j as HarnessPickerProps, k as HarnessType, I as Invoice, l as InvoiceTable, m as InvoiceTableProps, M as ModelInfo, n as ModelPicker, o as ModelPickerProps, p as ModelPickerVariant, q as ModelPreset, N as NavItem, r as NewSandboxCard, s as NewSandboxCardProps, t as PlanCardData, u as PlanCards, v as PlanCardsProps, au as PlanFeature, w as ProductVariant, x as ProfileAvatar, y as ProfileAvatarProps, z as ProfileComparison, A as ProfileComparisonProps, E as ProfileSelector, F as ProfileSelectorProps, R as RailButton, G as RailButtonProps, J as RailModeButton, K as RailModeButtonProps, L as RailSeparator, O as RailSeparatorProps, Q as ResourceMeter, S as ResourceMeterProps, T as SIDEBAR_MOBILE_WIDTH, U as SIDEBAR_PANEL_WIDTH, V as SIDEBAR_RAIL_WIDTH, W as SIDEBAR_TOTAL_WIDTH, X as SandboxCard, Y as SandboxCardData, Z as SandboxCardProps, _ as SandboxStatus, $ as SandboxTable, a0 as SandboxTableProps, a1 as Sidebar, a2 as SidebarContent, a3 as SidebarContentProps, a4 as SidebarPanel, a5 as SidebarPanelContent, a6 as SidebarPanelContentProps, a7 as SidebarPanelHeader, a8 as SidebarPanelHeaderProps, a9 as SidebarPanelProps, aa as SidebarProps, ab as SidebarProvider, ac as SidebarProviderProps, ad as SidebarRail, ae as SidebarRailFooter, af as SidebarRailFooterProps, ag as SidebarRailHeader, ah as SidebarRailHeaderProps, ai as SidebarRailNav, aj as SidebarRailNavProps, ak as SidebarRailProps, al as SidebarUser, av as TeamRole, aw as Variant, an as VariantList, ao as VariantListProps, ax as VariantOutcome, ay as VariantStatus, az as canAdminSandbox, ap as canonicalModelId, aq as formatContext, ar as formatPricing, as as useSidebar } from './variant-list-BrHYcBCk.js';
2
2
  export { a as BillingBalance, c as BillingDashboard, d as BillingDashboardProps, B as BillingSubscription, b as BillingUsage, e as PricingPage, f as PricingPageProps, P as PricingTier, g as UsageChart, h as UsageChartProps, U as UsageDataPoint, i as formatPrice } from './usage-chart-CPTcNlGs.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  export { a as TemplateCard, T as TemplateCardData, b as TemplateCardProps } from './template-card-BAtvcAkU.js';
package/dist/dashboard.js CHANGED
@@ -7,7 +7,10 @@ import {
7
7
  ClusterStatusBar,
8
8
  CreditBalance,
9
9
  DashboardLayout,
10
+ HARNESS_OPTIONS,
11
+ HarnessPicker,
10
12
  InvoiceTable,
13
+ ModelPicker,
11
14
  NewSandboxCard,
12
15
  PlanCards,
13
16
  ProfileAvatar,
@@ -35,8 +38,11 @@ import {
35
38
  SidebarRailNav,
36
39
  VariantList,
37
40
  canAdminSandbox,
41
+ canonicalModelId,
42
+ formatContext,
43
+ formatPricing,
38
44
  useSidebar
39
- } from "./chunk-Z5PSS3VD.js";
45
+ } from "./chunk-NKUPJC34.js";
40
46
  import {
41
47
  BillingDashboard,
42
48
  PricingPage,
@@ -931,8 +937,11 @@ export {
931
937
  CreditBalance,
932
938
  DashboardLayout,
933
939
  GitPanel,
940
+ HARNESS_OPTIONS,
941
+ HarnessPicker,
934
942
  InfoPanel,
935
943
  InvoiceTable,
944
+ ModelPicker,
936
945
  NetworkConfig,
937
946
  NewSandboxCard,
938
947
  PlanCards,
@@ -970,6 +979,9 @@ export {
970
979
  UsageSummary,
971
980
  VariantList,
972
981
  canAdminSandbox,
982
+ canonicalModelId,
983
+ formatContext,
973
984
  formatPrice,
985
+ formatPricing,
974
986
  useSidebar
975
987
  };
package/dist/globals.css CHANGED
@@ -1139,6 +1139,9 @@
1139
1139
  .max-h-\[160px\] {
1140
1140
  max-height: 160px;
1141
1141
  }
1142
+ .max-h-\[440px\] {
1143
+ max-height: 440px;
1144
+ }
1142
1145
  .min-h-0 {
1143
1146
  min-height: calc(var(--spacing) * 0);
1144
1147
  }
@@ -1343,6 +1346,9 @@
1343
1346
  .w-\[var\(--indicator-dot-size\)\] {
1344
1347
  width: var(--indicator-dot-size);
1345
1348
  }
1349
+ .w-\[var\(--radix-dropdown-menu-trigger-width\)\] {
1350
+ width: var(--radix-dropdown-menu-trigger-width);
1351
+ }
1346
1352
  .w-\[var\(--radix-select-trigger-width\)\] {
1347
1353
  width: var(--radix-select-trigger-width);
1348
1354
  }
@@ -1403,12 +1409,18 @@
1403
1409
  .max-w-\[150px\] {
1404
1410
  max-width: 150px;
1405
1411
  }
1412
+ .max-w-\[160px\] {
1413
+ max-width: 160px;
1414
+ }
1406
1415
  .max-w-\[250px\] {
1407
1416
  max-width: 250px;
1408
1417
  }
1409
1418
  .max-w-\[300px\] {
1410
1419
  max-width: 300px;
1411
1420
  }
1421
+ .max-w-\[460px\] {
1422
+ max-width: 460px;
1423
+ }
1412
1424
  .max-w-full {
1413
1425
  max-width: 100%;
1414
1426
  }
@@ -1448,6 +1460,9 @@
1448
1460
  .min-w-\[180px\] {
1449
1461
  min-width: 180px;
1450
1462
  }
1463
+ .min-w-\[320px\] {
1464
+ min-width: 320px;
1465
+ }
1451
1466
  .min-w-\[var\(--radix-select-trigger-width\)\] {
1452
1467
  min-width: var(--radix-select-trigger-width);
1453
1468
  }
@@ -2602,6 +2617,9 @@
2602
2617
  .pt-1 {
2603
2618
  padding-top: calc(var(--spacing) * 1);
2604
2619
  }
2620
+ .pt-1\.5 {
2621
+ padding-top: calc(var(--spacing) * 1.5);
2622
+ }
2605
2623
  .pt-2 {
2606
2624
  padding-top: calc(var(--spacing) * 2);
2607
2625
  }
@@ -2641,6 +2659,9 @@
2641
2659
  .pb-0 {
2642
2660
  padding-bottom: calc(var(--spacing) * 0);
2643
2661
  }
2662
+ .pb-0\.5 {
2663
+ padding-bottom: calc(var(--spacing) * 0.5);
2664
+ }
2644
2665
  .pb-1 {
2645
2666
  padding-bottom: calc(var(--spacing) * 1);
2646
2667
  }
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ import { b as ToolPart } from './parts-CyGkM6Fp.js';
15
15
  export { R as ReasoningPart, S as SessionMessage, a as SessionPart, T as TextPart, c as ToolState, d as ToolStatus, e as ToolTime } from './parts-CyGkM6Fp.js';
16
16
  export { F as FileNode, a as FileTabData, b as FileTabs, c as FileTabsProps, d as FileTree, e as FileTreeProps, f as FileTreeVisibilityOptions, g as filterFileTree } from './file-tabs-BLfxfmAH.js';
17
17
  export { FileArtifactPane, FileArtifactPaneProps, FilePreview, FilePreviewProps } from './files.js';
18
- export { B as Backend, a as BackendSelector, b as BackendSelectorProps, C as ClusterStatusBar, c as ClusterStatusBarProps, d as ClusterStatusItem, e as CreditBalance, f as CreditBalanceProps, D as DashboardLayout, g as DashboardLayoutProps, h as DashboardUser, I as Invoice, i as InvoiceTable, j as InvoiceTableProps, N as NavItem, k as NewSandboxCard, l as NewSandboxCardProps, P as PanelConfig, m as PlanCardData, n as PlanCards, o as PlanCardsProps, p as ProductVariant, q as ProfileAvatar, r as ProfileAvatarProps, s as ProfileComparison, t as ProfileComparisonProps, u as ProfileSelector, v as ProfileSelectorProps, R as RailButton, w as RailButtonProps, x as RailModeButton, y as RailModeButtonProps, z as RailSeparator, A as RailSeparatorProps, E as ResourceMeter, F as ResourceMeterProps, S as SIDEBAR_MOBILE_WIDTH, G as SIDEBAR_PANEL_WIDTH, H as SIDEBAR_RAIL_WIDTH, J as SIDEBAR_TOTAL_WIDTH, K as SandboxCard, L as SandboxCardData, M as SandboxCardProps, O as SandboxStatus, Q as SandboxTable, T as SandboxTableProps, U as Sidebar, V as SidebarContent, W as SidebarContentProps, X as SidebarPanel, Y as SidebarPanelContent, Z as SidebarPanelContentProps, _ as SidebarPanelHeader, $ as SidebarPanelHeaderProps, a0 as SidebarPanelProps, a1 as SidebarProps, a2 as SidebarProvider, a3 as SidebarProviderProps, a4 as SidebarRail, a5 as SidebarRailFooter, a6 as SidebarRailFooterProps, a7 as SidebarRailHeader, a8 as SidebarRailHeaderProps, a9 as SidebarRailNav, aa as SidebarRailNavProps, ab as SidebarRailProps, ac as SidebarUser, ad as TopNavLink, ae as VariantList, af as VariantListProps, ag as useSidebar } from './variant-list-DAhiR-7S.js';
18
+ export { B as Backend, a as BackendSelector, b as BackendSelectorProps, C as ClusterStatusBar, c as ClusterStatusBarProps, d as ClusterStatusItem, e as CreditBalance, f as CreditBalanceProps, D as DashboardLayout, g as DashboardLayoutProps, h as DashboardUser, H as HARNESS_OPTIONS, i as HarnessPicker, j as HarnessPickerProps, k as HarnessType, I as Invoice, l as InvoiceTable, m as InvoiceTableProps, M as ModelInfo, n as ModelPicker, o as ModelPickerProps, p as ModelPickerVariant, q as ModelPreset, N as NavItem, r as NewSandboxCard, s as NewSandboxCardProps, P as PanelConfig, t as PlanCardData, u as PlanCards, v as PlanCardsProps, w as ProductVariant, x as ProfileAvatar, y as ProfileAvatarProps, z as ProfileComparison, A as ProfileComparisonProps, E as ProfileSelector, F as ProfileSelectorProps, R as RailButton, G as RailButtonProps, J as RailModeButton, K as RailModeButtonProps, L as RailSeparator, O as RailSeparatorProps, Q as ResourceMeter, S as ResourceMeterProps, T as SIDEBAR_MOBILE_WIDTH, U as SIDEBAR_PANEL_WIDTH, V as SIDEBAR_RAIL_WIDTH, W as SIDEBAR_TOTAL_WIDTH, X as SandboxCard, Y as SandboxCardData, Z as SandboxCardProps, _ as SandboxStatus, $ as SandboxTable, a0 as SandboxTableProps, a1 as Sidebar, a2 as SidebarContent, a3 as SidebarContentProps, a4 as SidebarPanel, a5 as SidebarPanelContent, a6 as SidebarPanelContentProps, a7 as SidebarPanelHeader, a8 as SidebarPanelHeaderProps, a9 as SidebarPanelProps, aa as SidebarProps, ab as SidebarProvider, ac as SidebarProviderProps, ad as SidebarRail, ae as SidebarRailFooter, af as SidebarRailFooterProps, ag as SidebarRailHeader, ah as SidebarRailHeaderProps, ai as SidebarRailNav, aj as SidebarRailNavProps, ak as SidebarRailProps, al as SidebarUser, am as TopNavLink, an as VariantList, ao as VariantListProps, ap as canonicalModelId, aq as formatContext, ar as formatPricing, as as useSidebar } from './variant-list-BrHYcBCk.js';
19
19
  export { c as BillingDashboard, d as BillingDashboardProps, e as PricingCards, f as PricingPageProps, g as UsageChart, h as UsageChartProps, U as UsageDataPoint } from './usage-chart-CPTcNlGs.js';
20
20
  export { AuthHeader, GitHubLoginButton, LoginLayout, LoginLayoutProps, UserMenu } from './auth.js';
21
21
  export { CodeBlock, CodeBlock as CodeBlockDisplay, CopyButton, Markdown, MarkdownProps } from './markdown.js';
package/dist/index.js CHANGED
@@ -189,7 +189,10 @@ import {
189
189
  ClusterStatusBar,
190
190
  CreditBalance,
191
191
  DashboardLayout,
192
+ HARNESS_OPTIONS,
193
+ HarnessPicker,
192
194
  InvoiceTable,
195
+ ModelPicker,
193
196
  NewSandboxCard,
194
197
  PlanCards,
195
198
  ProfileAvatar,
@@ -216,8 +219,11 @@ import {
216
219
  SidebarRailHeader,
217
220
  SidebarRailNav,
218
221
  VariantList,
222
+ canonicalModelId,
223
+ formatContext,
224
+ formatPricing,
219
225
  useSidebar
220
- } from "./chunk-Z5PSS3VD.js";
226
+ } from "./chunk-NKUPJC34.js";
221
227
  import {
222
228
  BillingDashboard,
223
229
  PricingPage,
@@ -428,6 +434,8 @@ export {
428
434
  GitHubLoginButton,
429
435
  GlobResultsPreview,
430
436
  GrepResultsPreview,
437
+ HARNESS_OPTIONS,
438
+ HarnessPicker,
431
439
  InlineCode,
432
440
  InlineThinkingItem,
433
441
  InlineToolItem,
@@ -438,6 +446,7 @@ export {
438
446
  Logo,
439
447
  Markdown,
440
448
  MessageList,
449
+ ModelPicker,
441
450
  NewSandboxCard,
442
451
  OpenUIArtifactRenderer,
443
452
  PlanCards,
@@ -530,12 +539,15 @@ export {
530
539
  WriteFilePreview,
531
540
  badgeVariants,
532
541
  buttonVariants,
542
+ canonicalModelId,
533
543
  cn,
534
544
  copyText,
535
545
  createAuthFetcher,
536
546
  filterFileTree,
537
547
  formatBytes,
548
+ formatContext,
538
549
  formatDuration,
550
+ formatPricing,
539
551
  formatUptime,
540
552
  getToolCategory,
541
553
  getToolDisplayMetadata,
package/dist/styles.css CHANGED
@@ -1139,6 +1139,9 @@
1139
1139
  .max-h-\[160px\] {
1140
1140
  max-height: 160px;
1141
1141
  }
1142
+ .max-h-\[440px\] {
1143
+ max-height: 440px;
1144
+ }
1142
1145
  .min-h-0 {
1143
1146
  min-height: calc(var(--spacing) * 0);
1144
1147
  }
@@ -1343,6 +1346,9 @@
1343
1346
  .w-\[var\(--indicator-dot-size\)\] {
1344
1347
  width: var(--indicator-dot-size);
1345
1348
  }
1349
+ .w-\[var\(--radix-dropdown-menu-trigger-width\)\] {
1350
+ width: var(--radix-dropdown-menu-trigger-width);
1351
+ }
1346
1352
  .w-\[var\(--radix-select-trigger-width\)\] {
1347
1353
  width: var(--radix-select-trigger-width);
1348
1354
  }
@@ -1403,12 +1409,18 @@
1403
1409
  .max-w-\[150px\] {
1404
1410
  max-width: 150px;
1405
1411
  }
1412
+ .max-w-\[160px\] {
1413
+ max-width: 160px;
1414
+ }
1406
1415
  .max-w-\[250px\] {
1407
1416
  max-width: 250px;
1408
1417
  }
1409
1418
  .max-w-\[300px\] {
1410
1419
  max-width: 300px;
1411
1420
  }
1421
+ .max-w-\[460px\] {
1422
+ max-width: 460px;
1423
+ }
1412
1424
  .max-w-full {
1413
1425
  max-width: 100%;
1414
1426
  }
@@ -1448,6 +1460,9 @@
1448
1460
  .min-w-\[180px\] {
1449
1461
  min-width: 180px;
1450
1462
  }
1463
+ .min-w-\[320px\] {
1464
+ min-width: 320px;
1465
+ }
1451
1466
  .min-w-\[var\(--radix-select-trigger-width\)\] {
1452
1467
  min-width: var(--radix-select-trigger-width);
1453
1468
  }
@@ -2602,6 +2617,9 @@
2602
2617
  .pt-1 {
2603
2618
  padding-top: calc(var(--spacing) * 1);
2604
2619
  }
2620
+ .pt-1\.5 {
2621
+ padding-top: calc(var(--spacing) * 1.5);
2622
+ }
2605
2623
  .pt-2 {
2606
2624
  padding-top: calc(var(--spacing) * 2);
2607
2625
  }
@@ -2641,6 +2659,9 @@
2641
2659
  .pb-0 {
2642
2660
  padding-bottom: calc(var(--spacing) * 0);
2643
2661
  }
2662
+ .pb-0\.5 {
2663
+ padding-bottom: calc(var(--spacing) * 0.5);
2664
+ }
2644
2665
  .pb-1 {
2645
2666
  padding-bottom: calc(var(--spacing) * 1);
2646
2667
  }
@@ -358,6 +358,125 @@ interface BackendSelectorProps {
358
358
  }
359
359
  declare function BackendSelector({ backends, selected, onChange, label, placeholder, className, }: BackendSelectorProps): react_jsx_runtime.JSX.Element;
360
360
 
361
+ /**
362
+ * Sandbox agent harness types — mirrors `BackendType` from
363
+ * `@tangle-network/sandbox` SDK. Kept in lockstep with that enum:
364
+ * if the SDK adds a backend, add it here too.
365
+ */
366
+ type HarnessType = "opencode" | "claude-code" | "codex" | "amp" | "factory-droids" | "cli-base";
367
+ interface HarnessOption extends Backend {
368
+ type: HarnessType;
369
+ }
370
+ /**
371
+ * Default option list with human-readable copy. Order is curated so the
372
+ * recommended choice (`opencode`) appears first; `cli-base` (no agent) last.
373
+ */
374
+ declare const HARNESS_OPTIONS: readonly HarnessOption[];
375
+ interface HarnessPickerProps extends Omit<BackendSelectorProps, "backends" | "selected" | "onChange"> {
376
+ value: HarnessType;
377
+ onChange: (next: HarnessType) => void;
378
+ /** Filter the available harnesses (e.g. by plan tier). Defaults to all. */
379
+ available?: ReadonlyArray<HarnessType>;
380
+ /** Override or extend the option metadata. Keys are HarnessType. */
381
+ optionsOverride?: Partial<Record<HarnessType, Partial<Omit<HarnessOption, "type">>>>;
382
+ }
383
+ /**
384
+ * Type-safe harness/backend selector for sandbox-backed agent products.
385
+ *
386
+ * Wraps the generic {@link BackendSelector} with the canonical harness list
387
+ * baked in, so consumers don't have to re-declare it (or risk drifting from
388
+ * the SDK enum).
389
+ */
390
+ declare function HarnessPicker({ value, onChange, available, optionsOverride, label, ...rest }: HarnessPickerProps): react_jsx_runtime.JSX.Element;
391
+
392
+ /**
393
+ * Wire-format model entry as returned by `/v1/models` on the Tangle Router
394
+ * (and most OpenAI-compatible gateways). Field names match the upstream
395
+ * response so consumers can pass `data.data` straight through.
396
+ */
397
+ interface ModelInfo {
398
+ /** Provider-local id, e.g. "gpt-5.4" or "anthropic/claude-sonnet-4-6". */
399
+ id: string;
400
+ /** Human label (defaults to id if absent). */
401
+ name?: string;
402
+ /** Provider key, e.g. "openai", "anthropic". Underscored for compat with router. */
403
+ _provider?: string;
404
+ /** Alternative provider field on some gateways. */
405
+ provider?: string;
406
+ /**
407
+ * Per-token prices in USD as decimal strings. Multiply by 1_000_000 for
408
+ * the conventional $/M tokens display.
409
+ */
410
+ pricing?: {
411
+ prompt?: string | null;
412
+ completion?: string | null;
413
+ };
414
+ context_length?: number;
415
+ description?: string | null;
416
+ architecture?: {
417
+ modality?: string;
418
+ input_modalities?: string[];
419
+ output_modalities?: string[];
420
+ };
421
+ }
422
+ /**
423
+ * Curated preset bucket. Three are surfaced by default — they map to typical
424
+ * cost/quality tradeoffs without forcing the consumer to pick a specific
425
+ * model. `match` resolves the preset against the loaded model list.
426
+ */
427
+ interface ModelPreset {
428
+ id: "fast" | "balanced" | "best" | string;
429
+ label: string;
430
+ hint: string;
431
+ icon?: React.ComponentType<{
432
+ className?: string;
433
+ }>;
434
+ /**
435
+ * Pick the canonical model id for this preset given the loaded list.
436
+ * Should return undefined if no acceptable model is loaded yet.
437
+ */
438
+ match: (models: ModelInfo[]) => string | undefined;
439
+ }
440
+ type ModelPickerVariant = "field" | "pill";
441
+ interface ModelPickerProps {
442
+ /** Canonical model id (provider-prefixed, e.g. "openai/gpt-5.4"). */
443
+ value: string;
444
+ onChange: (modelId: string) => void;
445
+ /** Models to choose from. Pass `[]` while loading. */
446
+ models: ModelInfo[];
447
+ /** Show the loading state (overrides empty-list copy). */
448
+ loading?: boolean;
449
+ /** Recently-used canonical ids to surface at the top. */
450
+ recents?: ReadonlyArray<string>;
451
+ /**
452
+ * Curated presets shown above the full list. Defaults to Fast/Balanced/Best
453
+ * resolved against common gpt-5/Claude families.
454
+ */
455
+ presets?: ReadonlyArray<ModelPreset>;
456
+ /** Drop providers from the picker entirely (e.g. "audio", "embedding"). */
457
+ excludeProviders?: ReadonlyArray<string>;
458
+ /** Restrict to these architectures (e.g. ["text"]). Default: all. */
459
+ modalities?: ReadonlyArray<string>;
460
+ /** Trigger appearance. "field" = full-width form field; "pill" = inline chat input pill. */
461
+ variant?: ModelPickerVariant;
462
+ label?: string;
463
+ placeholder?: string;
464
+ className?: string;
465
+ disabled?: boolean;
466
+ }
467
+ /**
468
+ * Resolve the canonical id for a model. Some upstreams already prefix the
469
+ * provider in the id (e.g. "anthropic/claude-haiku-4.5"); others put it in
470
+ * `_provider` and leave the id bare. Always returns "<provider>/<model>"
471
+ * unless the id is already prefixed.
472
+ */
473
+ declare function canonicalModelId(model: ModelInfo): string;
474
+ /** Format $/M tokens. Returns null if pricing is missing or zero. */
475
+ declare function formatPricing(pricing: ModelInfo["pricing"]): string | null;
476
+ /** Format context length compactly (e.g. 200_000 → "200k"). */
477
+ declare function formatContext(ctx: number | undefined): string | null;
478
+ declare function ModelPicker({ value, onChange, models, loading, recents, presets, excludeProviders, modalities, variant, label, placeholder, className, disabled, }: ModelPickerProps): react_jsx_runtime.JSX.Element;
479
+
361
480
  interface Profile {
362
481
  id: string;
363
482
  name: string;
@@ -418,4 +537,4 @@ interface VariantListProps {
418
537
  }
419
538
  declare function VariantList({ variants, selectedId, onSelect, onAccept, onReject, isActioning, className, }: VariantListProps): react_jsx_runtime.JSX.Element;
420
539
 
421
- export { type SidebarPanelHeaderProps as $, type RailSeparatorProps as A, type Backend as B, ClusterStatusBar as C, DashboardLayout as D, ResourceMeter as E, type ResourceMeterProps as F, SIDEBAR_PANEL_WIDTH as G, SIDEBAR_RAIL_WIDTH as H, type Invoice as I, SIDEBAR_TOTAL_WIDTH as J, SandboxCard as K, type SandboxCardData as L, type SandboxCardProps as M, type NavItem as N, type SandboxStatus as O, type PanelConfig as P, SandboxTable as Q, RailButton as R, SIDEBAR_MOBILE_WIDTH as S, type SandboxTableProps as T, Sidebar as U, SidebarContent as V, type SidebarContentProps as W, SidebarPanel as X, SidebarPanelContent as Y, type SidebarPanelContentProps as Z, SidebarPanelHeader as _, BackendSelector as a, type SidebarPanelProps as a0, type SidebarProps as a1, SidebarProvider as a2, type SidebarProviderProps as a3, SidebarRail as a4, SidebarRailFooter as a5, type SidebarRailFooterProps as a6, SidebarRailHeader as a7, type SidebarRailHeaderProps as a8, SidebarRailNav as a9, type SidebarRailNavProps as aa, type SidebarRailProps as ab, type SidebarUser as ac, type TopNavLink as ad, VariantList as ae, type VariantListProps as af, useSidebar as ag, type Profile as ah, type PlanFeature as ai, type TeamRole as aj, type Variant as ak, type VariantOutcome as al, type VariantStatus as am, canAdminSandbox as an, type BackendSelectorProps as b, type ClusterStatusBarProps as c, type ClusterStatusItem as d, CreditBalance as e, type CreditBalanceProps as f, type DashboardLayoutProps as g, type DashboardUser as h, InvoiceTable as i, type InvoiceTableProps as j, NewSandboxCard as k, type NewSandboxCardProps as l, type PlanCardData as m, PlanCards as n, type PlanCardsProps as o, type ProductVariant as p, ProfileAvatar as q, type ProfileAvatarProps as r, ProfileComparison as s, type ProfileComparisonProps as t, ProfileSelector as u, type ProfileSelectorProps as v, type RailButtonProps as w, RailModeButton as x, type RailModeButtonProps as y, RailSeparator as z };
540
+ export { SandboxTable as $, type ProfileComparisonProps as A, type Backend as B, ClusterStatusBar as C, DashboardLayout as D, ProfileSelector as E, type ProfileSelectorProps as F, type RailButtonProps as G, HARNESS_OPTIONS as H, type Invoice as I, RailModeButton as J, type RailModeButtonProps as K, RailSeparator as L, type ModelInfo as M, type NavItem as N, type RailSeparatorProps as O, type PanelConfig as P, ResourceMeter as Q, RailButton as R, type ResourceMeterProps as S, SIDEBAR_MOBILE_WIDTH as T, SIDEBAR_PANEL_WIDTH as U, SIDEBAR_RAIL_WIDTH as V, SIDEBAR_TOTAL_WIDTH as W, SandboxCard as X, type SandboxCardData as Y, type SandboxCardProps as Z, type SandboxStatus as _, BackendSelector as a, type SandboxTableProps as a0, Sidebar as a1, SidebarContent as a2, type SidebarContentProps as a3, SidebarPanel as a4, SidebarPanelContent as a5, type SidebarPanelContentProps as a6, SidebarPanelHeader as a7, type SidebarPanelHeaderProps as a8, type SidebarPanelProps as a9, type SidebarProps as aa, SidebarProvider as ab, type SidebarProviderProps as ac, SidebarRail as ad, SidebarRailFooter as ae, type SidebarRailFooterProps as af, SidebarRailHeader as ag, type SidebarRailHeaderProps as ah, SidebarRailNav as ai, type SidebarRailNavProps as aj, type SidebarRailProps as ak, type SidebarUser as al, type TopNavLink as am, VariantList as an, type VariantListProps as ao, canonicalModelId as ap, formatContext as aq, formatPricing as ar, useSidebar as as, type Profile as at, type PlanFeature as au, type TeamRole as av, type Variant as aw, type VariantOutcome as ax, type VariantStatus as ay, canAdminSandbox as az, type BackendSelectorProps as b, type ClusterStatusBarProps as c, type ClusterStatusItem as d, CreditBalance as e, type CreditBalanceProps as f, type DashboardLayoutProps as g, type DashboardUser as h, HarnessPicker as i, type HarnessPickerProps as j, type HarnessType as k, InvoiceTable as l, type InvoiceTableProps as m, ModelPicker as n, type ModelPickerProps as o, type ModelPickerVariant as p, type ModelPreset as q, NewSandboxCard as r, type NewSandboxCardProps as s, type PlanCardData as t, PlanCards as u, type PlanCardsProps as v, type ProductVariant as w, ProfileAvatar as x, type ProfileAvatarProps as y, ProfileComparison as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-ui",
3
- "version": "0.10.9",
3
+ "version": "0.11.0",
4
4
  "description": "Unified UI component library for Tangle Sandbox — primitives, chat, dashboard, terminal, editor, and workspace components",
5
5
  "repository": {
6
6
  "type": "git",