@tangle-network/sandbox-ui 0.6.1 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/auth.d.ts +10 -6
  2. package/dist/auth.js +3 -3
  3. package/dist/{chat-container-Cg-GwyiK.d.ts → chat-container-f4yEs6KN.d.ts} +9 -1
  4. package/dist/chat.d.ts +12 -2
  5. package/dist/chat.js +10 -10
  6. package/dist/{chunk-TSE423UF.js → chunk-2QZ6G7NM.js} +6 -6
  7. package/dist/{chunk-WBQ7VULC.js → chunk-34A66VBG.js} +7 -7
  8. package/dist/{chunk-JP725R4W.js → chunk-34I7UFSX.js} +2 -2
  9. package/dist/{chunk-YS66Q3RC.js → chunk-3CJ2SOEI.js} +2 -2
  10. package/dist/{chunk-CNWVHQFY.js → chunk-54SQQMMM.js} +6 -24
  11. package/dist/{chunk-DLCFZDGX.js → chunk-5UM2XMEJ.js} +39 -14
  12. package/dist/{chunk-YYGECNZZ.js → chunk-66EZOYZR.js} +3 -3
  13. package/dist/chunk-7U2Z23NE.js +49 -0
  14. package/dist/{chunk-RKXIRRKQ.js → chunk-BUOQTBTO.js} +70 -66
  15. package/dist/{chunk-DCPYTL4W.js → chunk-D4CZWJCD.js} +72 -148
  16. package/dist/{chunk-MXRQ4MJE.js → chunk-DXMIEK4K.js} +34 -23
  17. package/dist/{chunk-ZMWWE5RF.js → chunk-EXSOPXIY.js} +141 -123
  18. package/dist/{chunk-GW4GRAWJ.js → chunk-GSZA3TSY.js} +18 -12
  19. package/dist/{chunk-W4LM3QYZ.js → chunk-HB5Y37YU.js} +8 -8
  20. package/dist/{chunk-E2XT3G52.js → chunk-HFMAXUHV.js} +136 -137
  21. package/dist/{chunk-BRBTD7RH.js → chunk-MA7YKRUP.js} +28 -18
  22. package/dist/{chunk-MJUDMVRU.js → chunk-MT5FJ3ZT.js} +17 -17
  23. package/dist/chunk-OKLQVY3Y.js +139 -0
  24. package/dist/{chunk-KH5UDAJ2.js → chunk-QDH5GEGY.js} +58 -54
  25. package/dist/{chunk-33W2TLUL.js → chunk-QID2OOMG.js} +12 -3
  26. package/dist/{chunk-FJSVPBKY.js → chunk-S7OXQTST.js} +17 -3
  27. package/dist/chunk-T7HMZEVO.js +216 -0
  28. package/dist/{chunk-FNYJFCGU.js → chunk-U6QTHMY6.js} +145 -256
  29. package/dist/{chunk-565V6JTN.js → chunk-UXQMIR3D.js} +60 -99
  30. package/dist/{chunk-XTPAWK7L.js → chunk-VOUV7GGB.js} +25 -47
  31. package/dist/{chunk-OVNLOE3Y.js → chunk-WXK43R62.js} +41 -41
  32. package/dist/{chunk-6V4XVKFY.js → chunk-XXDFEF72.js} +340 -335
  33. package/dist/{chunk-TDYQBLL5.js → chunk-ZMNSRDMH.js} +6 -6
  34. package/dist/dashboard.d.ts +135 -3
  35. package/dist/dashboard.js +848 -8
  36. package/dist/{document-editor-pane-DWWUTTTZ.js → document-editor-pane-TLPVRBBU.js} +3 -3
  37. package/dist/editor.d.ts +9 -8
  38. package/dist/editor.js +3 -3
  39. package/dist/files.js +3 -3
  40. package/dist/globals.css +5304 -68
  41. package/dist/hooks.d.ts +1 -1
  42. package/dist/hooks.js +7 -7
  43. package/dist/index.d.ts +4 -4
  44. package/dist/index.js +28 -28
  45. package/dist/markdown.js +1 -1
  46. package/dist/openui.js +5 -5
  47. package/dist/pages.d.ts +47 -3
  48. package/dist/pages.js +911 -357
  49. package/dist/primitives.d.ts +5 -2
  50. package/dist/primitives.js +10 -10
  51. package/dist/run.js +4 -4
  52. package/dist/sdk-hooks.d.ts +2 -3
  53. package/dist/sdk-hooks.js +5 -5
  54. package/dist/styles.css +5304 -68
  55. package/dist/template-card-BAtvcAkU.d.ts +18 -0
  56. package/dist/terminal.d.ts +3 -1
  57. package/dist/terminal.js +66 -32
  58. package/dist/tokens.css +701 -40
  59. package/dist/{usage-chart-XCoB_7Xu.d.ts → usage-chart-SSiOgeQI.d.ts} +3 -1
  60. package/dist/{use-pty-session-COzVkhtc.d.ts → use-pty-session-0AOuwXgq.d.ts} +2 -0
  61. package/dist/{index-BT_-ecpc.d.ts → variant-list-C8wx2TqF.d.ts} +17 -8
  62. package/dist/workspace.d.ts +1 -1
  63. package/dist/workspace.js +13 -13
  64. package/package.json +3 -1
  65. package/tailwind.config.cjs +3 -2
  66. package/dist/chunk-3HW53XTH.js +0 -228
  67. package/dist/chunk-OKCIKTXQ.js +0 -63
package/dist/pages.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  DialogFooter,
6
6
  DialogHeader,
7
7
  DialogTitle
8
- } from "./chunk-YS66Q3RC.js";
8
+ } from "./chunk-3CJ2SOEI.js";
9
9
  import {
10
10
  Tabs,
11
11
  TabsContent,
@@ -15,23 +15,26 @@ import {
15
15
  import {
16
16
  EmptyState,
17
17
  Input
18
- } from "./chunk-BRBTD7RH.js";
18
+ } from "./chunk-MA7YKRUP.js";
19
+ import {
20
+ TemplateCard
21
+ } from "./chunk-7U2Z23NE.js";
19
22
  import {
20
23
  BillingDashboard,
21
24
  PricingPage,
22
25
  UsageChart
23
- } from "./chunk-565V6JTN.js";
26
+ } from "./chunk-UXQMIR3D.js";
24
27
  import {
25
28
  Skeleton,
26
29
  SkeletonCard
27
- } from "./chunk-YYGECNZZ.js";
30
+ } from "./chunk-66EZOYZR.js";
28
31
  import {
29
32
  Badge,
30
33
  Card
31
- } from "./chunk-TDYQBLL5.js";
34
+ } from "./chunk-ZMNSRDMH.js";
32
35
  import {
33
36
  Button
34
- } from "./chunk-TSE423UF.js";
37
+ } from "./chunk-2QZ6G7NM.js";
35
38
  import {
36
39
  cn
37
40
  } from "./chunk-RQHJBTEU.js";
@@ -294,8 +297,8 @@ function BillingPage({
294
297
 
295
298
  // src/pages/provisioning-wizard.tsx
296
299
  import * as React2 from "react";
297
- import { ArrowLeft, ArrowRight, Layers, Cpu, Bot, Info } from "lucide-react";
298
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
300
+ import { ArrowLeft, Layers, Cpu, Bot, Info, Loader2, Settings, Plus, Trash2 } from "lucide-react";
301
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
299
302
  var STACK_DISPLAY = {
300
303
  universal: { name: "Universal", abbr: "U", color: "violet", textClass: "text-[var(--surface-violet-text)]" },
301
304
  ethereum: { name: "Ethereum", abbr: "\u039E", color: "blue", textClass: "text-[var(--surface-info-text)]" },
@@ -309,7 +312,7 @@ function resolveEnvironment(env) {
309
312
  const name = display?.name ?? (env.id.length > 0 ? env.id.charAt(0).toUpperCase() + env.id.slice(1).replace(/-/g, " ") : "Unknown");
310
313
  const abbr = display?.abbr ?? (env.id.length > 0 ? env.id[0].toUpperCase() : "?");
311
314
  const color = display?.color ?? "slate";
312
- const textClass = display?.textClass ?? "text-[var(--text-muted)]";
315
+ const textClass = display?.textClass ?? "text-muted-foreground";
313
316
  return {
314
317
  id: env.id,
315
318
  name,
@@ -323,7 +326,6 @@ var defaultEnvironments = [
323
326
  { id: "python", name: "Python", description: "v3.11 pre-installed with PyTorch and common data science libraries.", icon: /* @__PURE__ */ jsx2("span", { className: "text-sky-400 text-2xl font-bold", children: "Py" }), color: "blue" },
324
327
  { id: "ubuntu", name: "Ubuntu", description: "Full 22.04 LTS terminal access for custom containerized workloads.", icon: /* @__PURE__ */ jsx2("span", { className: "text-orange-400 text-2xl font-bold", children: "U" }), color: "orange" }
325
328
  ];
326
- var STEPS = ["Stack", "Resources", "Agent", "Review"];
327
329
  var CPU_MIN = 0.5;
328
330
  var CPU_MAX = 8;
329
331
  var RAM_MIN = 2;
@@ -334,14 +336,18 @@ function calcCost(cpu, ram) {
334
336
  const cost = cpu * 0.045 + ram * 5e-3;
335
337
  return cost.toFixed(2);
336
338
  }
337
- var sectionIcon = "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-[var(--accent-surface-soft)] border border-[var(--border-accent)] text-[var(--brand-cool)]";
338
339
  function ProvisioningWizard({
339
340
  environments: environmentsProp,
340
341
  onLoadEnvironments,
341
342
  onSubmit,
342
343
  onBack,
343
- className
344
+ className,
345
+ variant = "flat",
346
+ defaultEnvironment,
347
+ defaultConfig,
348
+ skipToReview
344
349
  }) {
350
+ const dc = defaultConfig;
345
351
  const [envList, setEnvList] = React2.useState(environmentsProp ?? defaultEnvironments);
346
352
  React2.useEffect(() => {
347
353
  if (onLoadEnvironments) {
@@ -351,224 +357,445 @@ function ProvisioningWizard({
351
357
  }
352
358
  }, [onLoadEnvironments, environmentsProp]);
353
359
  const environments = envList;
354
- const [step, setStep] = React2.useState(0);
355
- const [selectedEnv, setSelectedEnv] = React2.useState(environments[0]?.id ?? "");
356
- const [cpuCores, setCpuCores] = React2.useState(4);
357
- const [ramGB, setRamGB] = React2.useState(16);
358
- const [storageGB, setStorageGB] = React2.useState(128);
359
- const [modelTier, setModelTier] = React2.useState("claude-sonnet");
360
- const [systemPrompt, setSystemPrompt] = React2.useState("");
361
- const handleNext = () => {
362
- if (step < STEPS.length - 1) setStep(step + 1);
363
- else onSubmit?.({ environment: selectedEnv, cpuCores, ramGB, storageGB, modelTier, systemPrompt });
360
+ const effectiveDefault = dc?.environment ?? defaultEnvironment;
361
+ const [selectedEnv, setSelectedEnv] = React2.useState(effectiveDefault ?? environments[0]?.id ?? "");
362
+ React2.useEffect(() => {
363
+ if (effectiveDefault && envList.some((e) => e.id === effectiveDefault)) {
364
+ setSelectedEnv(effectiveDefault);
365
+ }
366
+ }, [envList, effectiveDefault]);
367
+ const [cpuCores, setCpuCores] = React2.useState(dc?.cpuCores ?? 4);
368
+ const [ramGB, setRamGB] = React2.useState(dc?.ramGB ?? 16);
369
+ const [storageGB, setStorageGB] = React2.useState(dc?.storageGB ?? 128);
370
+ const [modelTier, setModelTier] = React2.useState(dc?.modelTier ?? "claude-sonnet");
371
+ const [systemPrompt, setSystemPrompt] = React2.useState(dc?.systemPrompt ?? "");
372
+ const [name, setName] = React2.useState(dc?.name ?? "");
373
+ const [gitUrl, setGitUrl] = React2.useState(dc?.gitUrl ?? "");
374
+ const [envVars, setEnvVars] = React2.useState(dc?.envVars ?? [{ key: "", value: "" }]);
375
+ const [driver, setDriver] = React2.useState(dc?.driver ?? "docker");
376
+ const [bare, setBare] = React2.useState(dc?.bare ?? false);
377
+ const [showAdvanced, setShowAdvanced] = React2.useState(false);
378
+ const isMultistep = variant === "multistep";
379
+ const [currentStep, setCurrentStep] = React2.useState(skipToReview && dc && isMultistep ? 3 : 1);
380
+ const [isDeploying, setIsDeploying] = React2.useState(false);
381
+ const handleDeploy = () => {
382
+ setIsDeploying(true);
383
+ onSubmit?.({ environment: selectedEnv, cpuCores, ramGB, storageGB, modelTier, systemPrompt, name, gitUrl, envVars: envVars.filter((e) => e.key.trim() !== ""), driver, bare });
364
384
  };
365
- const handleBack = () => {
366
- if (step > 0) setStep(step - 1);
367
- else onBack?.();
385
+ const applyPreset = (cpu, ram, storage) => {
386
+ setCpuCores(cpu);
387
+ setRamGB(ram);
388
+ setStorageGB(storage);
368
389
  };
369
390
  const hourCost = calcCost(cpuCores, ramGB);
370
- return /* @__PURE__ */ jsxs2("div", { className: cn("max-w-6xl mx-auto", className), children: [
371
- /* @__PURE__ */ jsxs2("div", { className: "mb-10", children: [
372
- /* @__PURE__ */ jsx2("h1", { className: "text-4xl font-extrabold tracking-tight text-[var(--text-primary)] mb-2", children: "Sandbox Provisioning" }),
373
- /* @__PURE__ */ jsx2("p", { className: "text-[var(--text-muted)] max-w-2xl", children: "Configure your high-performance orchestration environment. Select your stack, allocate resources, and prime your agent for deployment." })
374
- ] }),
375
- /* @__PURE__ */ jsx2("div", { className: "grid grid-cols-4 gap-4 mb-10", children: STEPS.map((label, i) => /* @__PURE__ */ jsxs2("div", { className: "relative pt-5", children: [
376
- /* @__PURE__ */ jsx2("div", { className: cn("h-1 w-full rounded-full transition-colors", i <= step ? "bg-[var(--brand-cool)]" : "bg-[var(--depth-3)]") }),
377
- /* @__PURE__ */ jsxs2("span", { className: cn("absolute top-0 left-0 font-mono text-[10px] uppercase tracking-widest font-bold transition-colors", i <= step ? "text-[var(--brand-cool)]" : "text-[var(--text-muted)]"), children: [
378
- String(i + 1).padStart(2, "0"),
379
- " ",
380
- label
391
+ return /* @__PURE__ */ jsxs2("div", { className: cn("max-w-6xl mx-auto flex flex-col", className), children: [
392
+ /* @__PURE__ */ jsxs2("div", { className: "mb-6 flex items-center gap-4 shrink-0", children: [
393
+ onBack && /* @__PURE__ */ jsx2("button", { type: "button", onClick: onBack, className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-border hover:bg-muted/50 transition-colors text-foreground", children: /* @__PURE__ */ jsx2(ArrowLeft, { className: "h-5 w-5" }) }),
394
+ /* @__PURE__ */ jsxs2("div", { children: [
395
+ /* @__PURE__ */ jsx2("h1", { className: "text-3xl font-extrabold tracking-tight text-foreground mb-1", children: "Sandbox Provisioning" }),
396
+ /* @__PURE__ */ jsx2("p", { className: "text-muted-foreground text-sm", children: "Select your stack, allocate resources, and configure your agent." })
381
397
  ] })
382
- ] }, label)) }),
383
- /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-12 gap-8 items-start", children: [
384
- /* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-8 space-y-6", children: [
385
- /* @__PURE__ */ jsxs2("section", { className: "bg-[var(--depth-2)] rounded-xl p-8 border border-[var(--border-subtle)]", children: [
386
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-4 mb-8", children: [
387
- /* @__PURE__ */ jsx2("div", { className: sectionIcon, children: /* @__PURE__ */ jsx2(Layers, { className: "h-5 w-5" }) }),
388
- /* @__PURE__ */ jsx2("h2", { className: "text-xl font-bold text-[var(--text-primary)]", children: "Environment Selection" })
398
+ ] }),
399
+ /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-12 gap-6 flex-1 min-h-0", children: [
400
+ /* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-8 flex flex-col min-h-0", children: [
401
+ isMultistep && /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2 mb-4 glass-panel p-3 rounded-2xl mx-auto max-w-2xl justify-between shrink-0", children: [1, 2, 3].map((s) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center", children: [
402
+ /* @__PURE__ */ jsx2("div", { className: cn("w-7 h-7 rounded-full flex items-center justify-center font-bold text-xs transition-colors shrink-0", currentStep === s ? "bg-primary text-primary-foreground" : currentStep > s ? "bg-primary/40 text-primary-foreground" : "bg-muted text-muted-foreground"), children: s }),
403
+ /* @__PURE__ */ jsxs2("span", { className: cn("ml-2 sm:ml-3 font-bold text-sm tracking-tight hidden sm:inline", currentStep === s ? "text-foreground" : currentStep > s ? "text-primary/60" : "text-muted-foreground"), children: [
404
+ s === 1 && "Environment",
405
+ s === 2 && "Resources",
406
+ s === 3 && "AI Agent"
389
407
  ] }),
390
- /* @__PURE__ */ jsx2("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: environments.map((env) => /* @__PURE__ */ jsxs2(
408
+ s < 3 && /* @__PURE__ */ jsx2("div", { className: cn("w-4 sm:w-8 h-px mx-2 sm:mx-4 transition-colors", currentStep > s ? "bg-primary/40" : "bg-border") })
409
+ ] }, s)) }),
410
+ dc && isMultistep && /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between glass-panel rounded-2xl px-4 py-3 shrink-0", children: [
411
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-sm", children: [
412
+ /* @__PURE__ */ jsx2(Info, { className: "h-4 w-4 text-accent shrink-0" }),
413
+ /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Pre-configured from template." })
414
+ ] }),
415
+ /* @__PURE__ */ jsx2(
391
416
  "button",
392
417
  {
393
418
  type: "button",
394
- onClick: () => setSelectedEnv(env.id),
395
- className: cn(
396
- "group relative p-5 rounded-xl bg-[var(--depth-3)] cursor-pointer hover:bg-[var(--depth-4)] transition-all text-left border",
397
- selectedEnv === env.id ? "border-[var(--border-accent)]" : "border-[var(--border-subtle)]"
398
- ),
399
- children: [
400
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-start mb-4", children: [
401
- /* @__PURE__ */ jsx2("div", { className: "w-12 h-12 rounded-full flex items-center justify-center bg-[var(--depth-1)]", children: env.icon }),
402
- /* @__PURE__ */ jsx2("div", { className: cn("w-5 h-5 rounded-full border-2 flex items-center justify-center", selectedEnv === env.id ? "border-[var(--brand-cool)]" : "border-[var(--border-default)]"), children: selectedEnv === env.id && /* @__PURE__ */ jsx2("div", { className: "w-2.5 h-2.5 bg-[var(--brand-cool)] rounded-full" }) })
403
- ] }),
404
- /* @__PURE__ */ jsx2("h3", { className: "font-bold text-base mb-1 text-[var(--text-primary)]", children: env.name }),
405
- /* @__PURE__ */ jsx2("p", { className: "text-xs text-[var(--text-muted)] leading-relaxed", children: env.description })
406
- ]
407
- },
408
- env.id
409
- )) })
419
+ onClick: () => {
420
+ setCurrentStep(1);
421
+ setCpuCores(4);
422
+ setRamGB(16);
423
+ setStorageGB(128);
424
+ setModelTier("claude-sonnet");
425
+ setSystemPrompt("");
426
+ setBare(false);
427
+ },
428
+ className: "text-xs font-bold text-accent hover:text-accent-deep transition-colors",
429
+ children: "Start from scratch"
430
+ }
431
+ )
410
432
  ] }),
411
- /* @__PURE__ */ jsxs2("section", { className: "bg-[var(--depth-2)] rounded-xl p-8 border border-[var(--border-subtle)]", children: [
412
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-4 mb-8", children: [
413
- /* @__PURE__ */ jsx2("div", { className: sectionIcon, children: /* @__PURE__ */ jsx2(Cpu, { className: "h-5 w-5" }) }),
414
- /* @__PURE__ */ jsx2("h2", { className: "text-xl font-bold text-[var(--text-primary)]", children: "Resource Allocation" })
415
- ] }),
416
- /* @__PURE__ */ jsx2("div", { className: "space-y-8", children: [
417
- { label: "Compute Cores (CPU)", value: cpuCores, setter: setCpuCores, min: CPU_MIN, max: CPU_MAX, step: 0.5, unit: "vCPUs" },
418
- { label: "Memory (RAM)", value: ramGB, setter: setRamGB, min: RAM_MIN, max: RAM_MAX, step: 1, unit: "GB" },
419
- { label: "Ephemeral Storage", value: storageGB, setter: setStorageGB, min: STORAGE_MIN, max: STORAGE_MAX, step: 8, unit: "GB" }
420
- ].map(({ label, value, setter, min, max, step: s, unit }) => /* @__PURE__ */ jsxs2("div", { className: "space-y-3", children: [
421
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-end", children: [
422
- /* @__PURE__ */ jsx2("label", { className: "font-mono text-xs uppercase tracking-widest text-[var(--text-muted)]", children: label }),
423
- /* @__PURE__ */ jsxs2("span", { className: "text-2xl font-bold text-[var(--brand-cool)]", children: [
424
- value,
425
- " ",
426
- /* @__PURE__ */ jsx2("span", { className: "text-xs text-[var(--text-muted)]", children: unit })
427
- ] })
433
+ /* @__PURE__ */ jsxs2("div", { className: "flex-1 overflow-y-auto min-h-0 space-y-4", children: [
434
+ (!isMultistep || currentStep === 1) && /* @__PURE__ */ jsx2(React2.Fragment, { children: /* @__PURE__ */ jsxs2("section", { className: "glass-panel rounded-[24px] p-6 shadow-2xl relative overflow-hidden", children: [
435
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 mb-6", children: [
436
+ /* @__PURE__ */ jsx2("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-accent/10 border border-accent/20 text-accent glow-primary", children: /* @__PURE__ */ jsx2(Layers, { className: "h-5 w-5" }) }),
437
+ /* @__PURE__ */ jsx2("h2", { className: "text-lg font-bold text-foreground tracking-tight", children: "Environment Selection" })
428
438
  ] }),
429
- /* @__PURE__ */ jsx2(
430
- "input",
439
+ /* @__PURE__ */ jsx2("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: environments.map((env) => /* @__PURE__ */ jsxs2(
440
+ "button",
431
441
  {
432
- type: "range",
433
- min,
434
- max,
435
- step: s,
436
- value,
437
- onChange: (e) => setter(+e.target.value),
438
- className: "w-full h-2 bg-[var(--depth-1)] rounded-full appearance-none cursor-pointer accent-[var(--brand-cool)]"
439
- }
440
- ),
441
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[10px] font-mono text-[var(--text-muted)]", children: [
442
- /* @__PURE__ */ jsxs2("span", { children: [
443
- min,
444
- " ",
445
- unit
446
- ] }),
447
- /* @__PURE__ */ jsxs2("span", { children: [
448
- max,
449
- " ",
450
- unit
442
+ type: "button",
443
+ onClick: () => setSelectedEnv(env.id),
444
+ className: cn(
445
+ "group relative p-4 rounded-[16px] transition-all text-left overflow-hidden border border-transparent",
446
+ selectedEnv === env.id ? "glass-panel-heavy border-accent glow-primary" : "glass-panel hover:border-[var(--glass-border-color)]"
447
+ ),
448
+ children: [
449
+ selectedEnv === env.id && /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 bg-gradient-to-br from-accent/10 to-transparent pointer-events-none" }),
450
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-start mb-3 relative z-10", children: [
451
+ /* @__PURE__ */ jsx2("div", { className: "w-10 h-10 rounded-full flex items-center justify-center bg-muted/50 border border-border shadow-inner", children: env.icon }),
452
+ /* @__PURE__ */ jsx2("div", { className: cn("w-5 h-5 rounded-full border-2 flex items-center justify-center transition-colors", selectedEnv === env.id ? "border-accent bg-accent/20" : "border-border"), children: selectedEnv === env.id && /* @__PURE__ */ jsx2("div", { className: "w-2.5 h-2.5 bg-accent rounded-full animate-in zoom-in" }) })
453
+ ] }),
454
+ /* @__PURE__ */ jsx2("h3", { className: "font-bold text-sm mb-0.5 text-foreground relative z-10", children: env.name }),
455
+ /* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground leading-relaxed relative z-10", children: env.description })
456
+ ]
457
+ },
458
+ env.id
459
+ )) })
460
+ ] }) }),
461
+ (!isMultistep || currentStep === 2) && /* @__PURE__ */ jsx2(React2.Fragment, { children: /* @__PURE__ */ jsxs2("section", { className: "glass-panel rounded-[24px] p-6 shadow-2xl relative overflow-hidden", children: [
462
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 mb-5", children: [
463
+ /* @__PURE__ */ jsx2("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-accent/10 border border-accent/20 text-accent glow-primary", children: /* @__PURE__ */ jsx2(Cpu, { className: "h-5 w-5" }) }),
464
+ /* @__PURE__ */ jsx2("h2", { className: "text-lg font-bold text-foreground tracking-tight", children: "Resource Allocation" })
465
+ ] }),
466
+ /* @__PURE__ */ jsxs2("div", { className: "mb-6", children: [
467
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-3", children: "Compute Presets" }),
468
+ /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-3 gap-3", children: [
469
+ /* @__PURE__ */ jsxs2("button", { type: "button", onClick: () => applyPreset(2, 4, 50), className: cn("p-3 rounded-[14px] transition-all text-center group", cpuCores === 2 && ramGB === 4 && storageGB === 50 ? "glass-panel-heavy border-accent glow-primary" : "glass-panel hover:border-[var(--glass-border-color)]"), children: [
470
+ /* @__PURE__ */ jsx2("div", { className: cn("font-bold text-sm transition-colors", cpuCores === 2 && ramGB === 4 && storageGB === 50 ? "text-accent" : "text-foreground"), children: "Lightweight" }),
471
+ /* @__PURE__ */ jsx2("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: "2C / 4G / 50G" })
472
+ ] }),
473
+ /* @__PURE__ */ jsxs2("button", { type: "button", onClick: () => applyPreset(4, 16, 128), className: cn("p-3 rounded-[14px] transition-all text-center group", cpuCores === 4 && ramGB === 16 && storageGB === 128 ? "glass-panel-heavy border-accent glow-primary" : "glass-panel hover:border-[var(--glass-border-color)]"), children: [
474
+ /* @__PURE__ */ jsx2("div", { className: cn("font-bold text-sm transition-colors", cpuCores === 4 && ramGB === 16 && storageGB === 128 ? "text-accent" : "text-foreground"), children: "Standard" }),
475
+ /* @__PURE__ */ jsx2("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: "4C / 16G / 128G" })
476
+ ] }),
477
+ /* @__PURE__ */ jsxs2("button", { type: "button", onClick: () => applyPreset(8, 32, 256), className: cn("p-3 rounded-[14px] transition-all text-center group", cpuCores === 8 && ramGB === 32 && storageGB === 256 ? "glass-panel-heavy border-accent glow-primary" : "glass-panel hover:border-[var(--glass-border-color)]"), children: [
478
+ /* @__PURE__ */ jsx2("div", { className: cn("font-bold text-sm transition-colors", cpuCores === 8 && ramGB === 32 && storageGB === 256 ? "text-accent" : "text-foreground"), children: "Performance" }),
479
+ /* @__PURE__ */ jsx2("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: "8C / 32G / 256G" })
480
+ ] })
451
481
  ] })
452
- ] })
453
- ] }, label)) })
454
- ] }),
455
- /* @__PURE__ */ jsxs2("section", { className: "bg-[var(--depth-2)] rounded-xl p-8 border border-[var(--border-subtle)]", children: [
456
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-4 mb-8", children: [
457
- /* @__PURE__ */ jsx2("div", { className: sectionIcon, children: /* @__PURE__ */ jsx2(Bot, { className: "h-5 w-5" }) }),
458
- /* @__PURE__ */ jsx2("h2", { className: "text-xl font-bold text-[var(--text-primary)]", children: "AI Agent Configuration" })
459
- ] }),
460
- /* @__PURE__ */ jsxs2("div", { className: "space-y-6", children: [
461
- /* @__PURE__ */ jsxs2("div", { children: [
462
- /* @__PURE__ */ jsx2("label", { className: "block font-mono text-xs uppercase tracking-widest text-[var(--text-muted)] mb-3", children: "Model Tier" }),
463
- /* @__PURE__ */ jsxs2(
464
- "select",
465
- {
466
- value: modelTier,
467
- onChange: (e) => setModelTier(e.target.value),
468
- className: "w-full bg-[var(--depth-1)] border border-[var(--border-subtle)] rounded-xl h-12 px-4 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-[var(--border-accent)] text-[var(--text-primary)]",
469
- children: [
470
- /* @__PURE__ */ jsx2("option", { value: "llama-3-8b", children: "Llama-3-8B-Instruct (Lightweight)" }),
471
- /* @__PURE__ */ jsx2("option", { value: "mistral-7b", children: "Mistral-7B-v0.2 (Efficient)" }),
472
- /* @__PURE__ */ jsx2("option", { value: "claude-sonnet", children: "Claude Sonnet 4.6 (Capable)" })
473
- ]
474
- }
475
- )
476
482
  ] }),
477
- /* @__PURE__ */ jsxs2("div", { children: [
478
- /* @__PURE__ */ jsx2("label", { className: "block font-mono text-xs uppercase tracking-widest text-[var(--text-muted)] mb-3", children: "Initial System Prompt" }),
483
+ /* @__PURE__ */ jsx2("div", { className: "space-y-6", children: [
484
+ { label: "Compute Cores (CPU)", value: cpuCores, setter: setCpuCores, min: CPU_MIN, max: CPU_MAX, step: 0.5, unit: "vCPUs" },
485
+ { label: "Memory (RAM)", value: ramGB, setter: setRamGB, min: RAM_MIN, max: RAM_MAX, step: 1, unit: "GB" },
486
+ { label: "Ephemeral Storage", value: storageGB, setter: setStorageGB, min: STORAGE_MIN, max: STORAGE_MAX, step: 8, unit: "GB" }
487
+ ].map(({ label, value, setter, min, max, step: s, unit }) => /* @__PURE__ */ jsxs2("div", { children: [
488
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-end border-b border-border pb-1.5 mb-2", children: [
489
+ /* @__PURE__ */ jsx2("label", { className: "font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: label }),
490
+ /* @__PURE__ */ jsxs2("span", { className: "text-xl font-bold text-foreground tracking-tight", children: [
491
+ value,
492
+ " ",
493
+ /* @__PURE__ */ jsx2("span", { className: "text-xs text-accent/80 ml-1", children: unit })
494
+ ] })
495
+ ] }),
479
496
  /* @__PURE__ */ jsx2(
480
- "textarea",
497
+ "input",
481
498
  {
482
- value: systemPrompt,
483
- onChange: (e) => setSystemPrompt(e.target.value),
484
- className: "w-full bg-[var(--depth-1)] border border-[var(--border-subtle)] rounded-xl p-5 font-mono text-sm focus:outline-none focus:ring-2 focus:ring-[var(--border-accent)] h-40 resize-none text-[var(--text-primary)] placeholder:text-[var(--text-muted)]",
485
- placeholder: "Define the core persona of your agent..."
499
+ type: "range",
500
+ min,
501
+ max,
502
+ step: s,
503
+ value,
504
+ onChange: (e) => setter(+e.target.value),
505
+ className: "w-full h-1.5 bg-muted rounded-full appearance-none cursor-pointer accent-accent"
486
506
  }
487
- )
507
+ ),
508
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground/60 mt-1", children: [
509
+ /* @__PURE__ */ jsxs2("span", { children: [
510
+ min,
511
+ unit
512
+ ] }),
513
+ /* @__PURE__ */ jsxs2("span", { children: [
514
+ max,
515
+ unit
516
+ ] })
517
+ ] })
518
+ ] }, label)) })
519
+ ] }) }),
520
+ (!isMultistep || currentStep === 3) && /* @__PURE__ */ jsx2(React2.Fragment, { children: /* @__PURE__ */ jsxs2("section", { className: "glass-panel rounded-[24px] p-6 shadow-2xl relative overflow-hidden", children: [
521
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 mb-5", children: [
522
+ /* @__PURE__ */ jsx2("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-accent/10 border border-accent/20 text-accent glow-primary", children: /* @__PURE__ */ jsx2(Bot, { className: "h-5 w-5" }) }),
523
+ /* @__PURE__ */ jsx2("h2", { className: "text-lg font-bold text-foreground tracking-tight", children: "AI Agent Capability" })
524
+ ] }),
525
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-5", children: [
526
+ /* @__PURE__ */ jsxs2("div", { children: [
527
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Model Engine" }),
528
+ /* @__PURE__ */ jsxs2(
529
+ "select",
530
+ {
531
+ value: modelTier,
532
+ onChange: (e) => setModelTier(e.target.value),
533
+ className: "w-full glass-panel rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent appearance-none",
534
+ children: [
535
+ /* @__PURE__ */ jsx2("option", { value: "llama-3-8b", className: "bg-gray-900", children: "Llama-3-8B-Instruct (Lightweight)" }),
536
+ /* @__PURE__ */ jsx2("option", { value: "mistral-7b", className: "bg-gray-900", children: "Mistral-7B-v0.2 (Efficient)" }),
537
+ /* @__PURE__ */ jsx2("option", { value: "claude-sonnet", className: "bg-gray-900", children: "Claude Sonnet 4.6 (Highly Capable)" })
538
+ ]
539
+ }
540
+ )
541
+ ] }),
542
+ /* @__PURE__ */ jsxs2("div", { children: [
543
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Core Directives (System Prompt)" }),
544
+ /* @__PURE__ */ jsx2(
545
+ "textarea",
546
+ {
547
+ value: systemPrompt,
548
+ onChange: (e) => setSystemPrompt(e.target.value),
549
+ className: "w-full glass-panel rounded-xl p-4 font-mono text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent h-32 resize-none placeholder:text-muted-foreground",
550
+ placeholder: "Define the autonomous directives or operational boundaries..."
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsxs2("div", { className: "pt-4 border-t border-border", children: [
555
+ /* @__PURE__ */ jsxs2(
556
+ "button",
557
+ {
558
+ type: "button",
559
+ onClick: () => setShowAdvanced(!showAdvanced),
560
+ className: "flex items-center gap-2 text-foreground/70 hover:text-foreground transition-colors text-sm font-bold focus:outline-none",
561
+ children: [
562
+ /* @__PURE__ */ jsx2(Settings, { className: "w-4 h-4" }),
563
+ showAdvanced ? "Hide Advanced Options" : "Show Advanced Options"
564
+ ]
565
+ }
566
+ ),
567
+ showAdvanced && /* @__PURE__ */ jsxs2("div", { className: "mt-6 space-y-5 animate-in slide-in-from-top-4 fade-in duration-300", children: [
568
+ /* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
569
+ /* @__PURE__ */ jsxs2("div", { children: [
570
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Workspace Name" }),
571
+ /* @__PURE__ */ jsx2(
572
+ "input",
573
+ {
574
+ type: "text",
575
+ value: name,
576
+ onChange: (e) => setName(e.target.value),
577
+ className: "w-full glass-panel rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent placeholder:text-muted-foreground",
578
+ placeholder: "my-cool-sandbox"
579
+ }
580
+ )
581
+ ] }),
582
+ /* @__PURE__ */ jsxs2("div", { children: [
583
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Virtualization Driver" }),
584
+ /* @__PURE__ */ jsxs2(
585
+ "select",
586
+ {
587
+ value: driver,
588
+ onChange: (e) => setDriver(e.target.value),
589
+ className: "w-full glass-panel rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent appearance-none",
590
+ children: [
591
+ /* @__PURE__ */ jsx2("option", { value: "docker", className: "bg-gray-900", children: "Docker container (Default)" }),
592
+ /* @__PURE__ */ jsx2("option", { value: "firecracker", className: "bg-gray-900", children: "Firecracker microVM (Secure)" }),
593
+ /* @__PURE__ */ jsx2("option", { value: "tangle", className: "bg-gray-900", children: "Tangle Distributed Node" })
594
+ ]
595
+ }
596
+ )
597
+ ] })
598
+ ] }),
599
+ /* @__PURE__ */ jsxs2("div", { children: [
600
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Git Repository URL" }),
601
+ /* @__PURE__ */ jsx2(
602
+ "input",
603
+ {
604
+ type: "text",
605
+ value: gitUrl,
606
+ onChange: (e) => setGitUrl(e.target.value),
607
+ className: "w-full glass-panel rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent placeholder:text-muted-foreground",
608
+ placeholder: "https://github.com/my-org/my-repo.git"
609
+ }
610
+ )
611
+ ] }),
612
+ /* @__PURE__ */ jsxs2("div", { children: [
613
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center mb-2", children: [
614
+ /* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Environment Variables" }),
615
+ /* @__PURE__ */ jsxs2("button", { type: "button", onClick: () => setEnvVars([...envVars, { key: "", value: "" }]), className: "flex items-center gap-1 text-xs text-accent hover:text-accent-deep transition-colors font-bold", children: [
616
+ /* @__PURE__ */ jsx2(Plus, { className: "h-3 w-3" }),
617
+ " Add Var"
618
+ ] })
619
+ ] }),
620
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
621
+ envVars.map((env, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
622
+ /* @__PURE__ */ jsx2(
623
+ "input",
624
+ {
625
+ type: "text",
626
+ value: env.key,
627
+ onChange: (e) => setEnvVars(envVars.map((v, idx) => idx === i ? { ...v, key: e.target.value } : v)),
628
+ className: "flex-1 glass-panel rounded-xl h-10 px-3 font-mono text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-accent placeholder:text-muted-foreground",
629
+ placeholder: "API_KEY"
630
+ }
631
+ ),
632
+ /* @__PURE__ */ jsx2(
633
+ "input",
634
+ {
635
+ type: "password",
636
+ value: env.value,
637
+ onChange: (e) => setEnvVars(envVars.map((v, idx) => idx === i ? { ...v, value: e.target.value } : v)),
638
+ className: "flex-[2] glass-panel rounded-xl h-10 px-3 font-mono text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-accent placeholder:text-muted-foreground",
639
+ placeholder: "sk-xxxxxxxxxxx"
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => setEnvVars(envVars.filter((_, idx) => idx !== i)), className: "h-10 w-10 flex items-center justify-center shrink-0 rounded-xl glass-panel text-red-400 hover:bg-red-500/10 hover:border-red-500/30 transition-colors", children: /* @__PURE__ */ jsx2(Trash2, { className: "h-4 w-4" }) })
643
+ ] }, i)),
644
+ envVars.length === 0 && /* @__PURE__ */ jsx2("div", { className: "text-center p-3 glass-panel rounded-xl text-muted-foreground/60 text-sm italic", children: "No environment variables set" })
645
+ ] })
646
+ ] }),
647
+ /* @__PURE__ */ jsx2("div", { className: "pt-2 border-t border-border", children: /* @__PURE__ */ jsxs2("label", { className: "flex items-center gap-3 cursor-pointer group", children: [
648
+ /* @__PURE__ */ jsxs2("div", { className: "relative flex items-center justify-center shrink-0", children: [
649
+ /* @__PURE__ */ jsx2("input", { type: "checkbox", className: "sr-only peer", checked: bare, onChange: (e) => setBare(e.target.checked) }),
650
+ /* @__PURE__ */ jsx2("div", { className: "w-10 h-6 bg-muted peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-accent hover:bg-white/20 transition-colors" })
651
+ ] }),
652
+ /* @__PURE__ */ jsxs2("div", { children: [
653
+ /* @__PURE__ */ jsx2("div", { className: "text-sm font-bold text-foreground mb-0.5 group-hover:text-accent transition-colors", children: "Bare Mode" }),
654
+ /* @__PURE__ */ jsx2("div", { className: "text-xs text-muted-foreground", children: "Start as a raw container without an embedded AI Agent backend." })
655
+ ] })
656
+ ] }) })
657
+ ] })
658
+ ] })
488
659
  ] })
489
- ] })
490
- ] }),
491
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center py-4", children: [
492
- /* @__PURE__ */ jsxs2("button", { type: "button", onClick: handleBack, className: "px-8 py-3 rounded-xl border border-[var(--border-subtle)] hover:bg-[var(--depth-3)] transition-colors text-sm font-bold text-[var(--text-secondary)] flex items-center gap-2", children: [
493
- /* @__PURE__ */ jsx2(ArrowLeft, { className: "h-4 w-4" }),
494
- "Back"
495
- ] }),
496
- /* @__PURE__ */ jsxs2("button", { type: "button", onClick: handleNext, className: "px-10 py-3 bg-[var(--accent-surface-soft)] border border-[var(--border-accent)] text-[var(--accent-text)] font-bold rounded-xl hover:bg-[var(--accent-surface-strong)] active:scale-95 transition-all flex items-center gap-2 group", children: [
497
- step < STEPS.length - 1 ? "Continue" : "Launch Sandbox",
498
- /* @__PURE__ */ jsx2(ArrowRight, { className: "h-4 w-4 group-hover:translate-x-1 transition-transform" })
499
- ] })
660
+ ] }) })
500
661
  ] })
501
662
  ] }),
502
- /* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-4 sticky top-24 space-y-6", children: [
503
- /* @__PURE__ */ jsxs2("div", { className: "bg-[var(--depth-2)] rounded-xl overflow-hidden border border-[var(--border-subtle)]", children: [
504
- /* @__PURE__ */ jsx2("div", { className: "bg-[var(--depth-1)] border-b border-[var(--border-subtle)] px-4 py-3 flex items-center justify-between", children: /* @__PURE__ */ jsx2("div", { className: "font-mono text-[10px] text-[var(--text-muted)] uppercase tracking-tighter", children: "config_stream.sh" }) }),
505
- /* @__PURE__ */ jsxs2("div", { className: "p-6 font-mono text-xs space-y-3 min-h-[280px]", children: [
506
- /* @__PURE__ */ jsx2("div", { className: "text-[var(--code-success)]", children: "$ tangle-cli provision --new" }),
507
- /* @__PURE__ */ jsx2("div", { className: "text-[var(--text-muted)]", children: "Initializing handshake..." }),
508
- /* @__PURE__ */ jsxs2("div", { className: "text-[var(--text-secondary)]", children: [
509
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--brand-cool)]", children: "\u2713" }),
510
- " Platform: ",
511
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--text-primary)]", children: environments.find((e) => e.id === selectedEnv)?.name ?? "Node.js" })
663
+ /* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-4 sticky top-4 space-y-4", children: [
664
+ /* @__PURE__ */ jsxs2("div", { className: "glass-panel-heavy rounded-[24px] overflow-hidden shadow-2xl relative", children: [
665
+ /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 bg-[radial-gradient(circle_at_top,rgba(173,163,255,0.05)_0,transparent_100%)] pointer-events-none" }),
666
+ /* @__PURE__ */ jsxs2("div", { className: "bg-muted/50 border-b border-border px-4 py-3 flex items-center gap-3", children: [
667
+ /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
668
+ /* @__PURE__ */ jsx2("div", { className: "h-3 w-3 rounded-full bg-[#ff5f56]/80" }),
669
+ /* @__PURE__ */ jsx2("div", { className: "h-3 w-3 rounded-full bg-[#ffbd2e]/80" }),
670
+ /* @__PURE__ */ jsx2("div", { className: "h-3 w-3 rounded-full bg-[#27c93f]/80" })
512
671
  ] }),
513
- /* @__PURE__ */ jsxs2("div", { className: "text-[var(--text-secondary)]", children: [
514
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--brand-cool)]", children: "\u2713" }),
515
- " Compute: ",
516
- /* @__PURE__ */ jsxs2("span", { className: "text-[var(--text-primary)]", children: [
672
+ /* @__PURE__ */ jsx2("div", { className: "font-mono text-[10px] text-muted-foreground uppercase tracking-widest ml-2 border-l border-border pl-3", children: "deploy_sequence.sh" })
673
+ ] }),
674
+ /* @__PURE__ */ jsxs2("div", { className: "p-5 font-mono text-xs space-y-3 min-h-[240px] relative z-10 text-[13px]", children: [
675
+ /* @__PURE__ */ jsxs2("div", { className: "text-green-400", children: [
676
+ "root@tangle:~# ",
677
+ /* @__PURE__ */ jsx2("span", { className: "text-foreground/80", children: "tangle-cli provision --new" })
678
+ ] }),
679
+ /* @__PURE__ */ jsx2("div", { className: "text-muted-foreground/70", children: "Initializing deployment handshake..." }),
680
+ /* @__PURE__ */ jsxs2("div", { className: "text-foreground/70", children: [
681
+ /* @__PURE__ */ jsx2("span", { className: "text-accent mr-2", children: "\u2713" }),
682
+ " Bound Platform: ",
683
+ /* @__PURE__ */ jsx2("span", { className: "text-foreground font-bold", children: environments.find((e) => e.id === selectedEnv)?.name ?? "Node.js" })
684
+ ] }),
685
+ /* @__PURE__ */ jsxs2("div", { className: "text-foreground/70", children: [
686
+ /* @__PURE__ */ jsx2("span", { className: "text-accent mr-2", children: "\u2713" }),
687
+ " Allocation CPU: ",
688
+ /* @__PURE__ */ jsxs2("span", { className: "text-foreground font-bold", children: [
517
689
  cpuCores,
518
- " vCPUs"
690
+ " Cores"
519
691
  ] })
520
692
  ] }),
521
- /* @__PURE__ */ jsxs2("div", { className: "text-[var(--text-secondary)]", children: [
522
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--brand-cool)]", children: "\u2713" }),
523
- " Memory: ",
524
- /* @__PURE__ */ jsxs2("span", { className: "text-[var(--text-primary)]", children: [
693
+ /* @__PURE__ */ jsxs2("div", { className: "text-foreground/70", children: [
694
+ /* @__PURE__ */ jsx2("span", { className: "text-accent mr-2", children: "\u2713" }),
695
+ " Allocation RAM: ",
696
+ /* @__PURE__ */ jsxs2("span", { className: "text-foreground font-bold", children: [
525
697
  ramGB,
526
698
  "GB"
527
699
  ] })
528
700
  ] }),
529
- /* @__PURE__ */ jsxs2("div", { className: "text-[var(--text-secondary)]", children: [
530
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--brand-cool)]", children: "\u2713" }),
531
- " Disk: ",
532
- /* @__PURE__ */ jsxs2("span", { className: "text-[var(--text-primary)]", children: [
701
+ /* @__PURE__ */ jsxs2("div", { className: "text-foreground/70", children: [
702
+ /* @__PURE__ */ jsx2("span", { className: "text-accent mr-2", children: "\u2713" }),
703
+ " Mounted Storage: ",
704
+ /* @__PURE__ */ jsxs2("span", { className: "text-foreground font-bold", children: [
533
705
  storageGB,
534
706
  "GB NVMe"
535
707
  ] })
536
708
  ] }),
537
- /* @__PURE__ */ jsxs2("div", { className: "pt-4 flex items-center gap-2", children: [
538
- /* @__PURE__ */ jsx2("div", { className: "w-2 h-4 bg-[var(--brand-cool)] animate-pulse" }),
539
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--text-muted)]", children: "Ready for review..." })
709
+ /* @__PURE__ */ jsxs2("div", { className: "pt-3 flex items-center gap-3", children: [
710
+ /* @__PURE__ */ jsx2("div", { className: "w-2 h-4 bg-accent animate-pulse" }),
711
+ /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: "Awaiting user confirmation..." })
540
712
  ] })
541
713
  ] })
542
714
  ] }),
543
- /* @__PURE__ */ jsxs2("div", { className: "p-6 rounded-xl bg-[var(--depth-3)] border border-[var(--border-accent)]", children: [
544
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center mb-4", children: [
545
- /* @__PURE__ */ jsx2("span", { className: "text-sm font-bold text-[var(--text-secondary)]", children: "Estimated Run Cost" }),
546
- /* @__PURE__ */ jsx2(Info, { className: "h-4 w-4 text-[var(--brand-cool)]" })
715
+ /* @__PURE__ */ jsxs2("div", { className: "p-6 rounded-2xl bg-accent/5 backdrop-blur-md border border-accent/20 shadow-[0_0_30px_rgba(173,163,255,0.1)] relative overflow-hidden", children: [
716
+ /* @__PURE__ */ jsx2("div", { className: "absolute -top-20 -right-20 w-40 h-40 bg-accent/20 blur-[50px] rounded-full" }),
717
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center mb-4 relative z-10", children: [
718
+ /* @__PURE__ */ jsx2("span", { className: "font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Run Cost" }),
719
+ /* @__PURE__ */ jsx2("div", { className: "h-7 w-7 rounded-full bg-muted/30 flex items-center justify-center border border-border", children: /* @__PURE__ */ jsx2(Info, { className: "h-3.5 w-3.5 text-accent" }) })
547
720
  ] }),
548
- /* @__PURE__ */ jsxs2("div", { className: "flex items-baseline gap-2 mb-6", children: [
549
- /* @__PURE__ */ jsxs2("span", { className: "text-4xl font-extrabold text-[var(--text-primary)]", children: [
721
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-baseline gap-2 mb-5 relative z-10", children: [
722
+ /* @__PURE__ */ jsxs2("span", { className: "text-4xl font-black text-foreground tracking-tighter", children: [
550
723
  "$",
551
724
  hourCost
552
725
  ] }),
553
- /* @__PURE__ */ jsx2("span", { className: "text-[var(--text-muted)] text-sm", children: "/ hour" })
726
+ /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground text-sm font-bold", children: "/ hour" })
554
727
  ] }),
555
- /* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
556
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[10px] font-mono uppercase tracking-widest text-[var(--text-muted)]", children: [
557
- /* @__PURE__ */ jsx2("span", { children: "Compute" }),
558
- /* @__PURE__ */ jsxs2("span", { className: "text-[var(--text-secondary)]", children: [
728
+ /* @__PURE__ */ jsxs2("div", { className: "space-y-2 relative z-10 glass-panel rounded-xl p-3 border border-border", children: [
729
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
730
+ /* @__PURE__ */ jsx2("span", { children: "COMPUTE" }),
731
+ /* @__PURE__ */ jsxs2("span", { className: "text-foreground", children: [
559
732
  "$",
560
- (cpuCores * 0.045).toFixed(2)
733
+ (cpuCores * 0.045).toFixed(2),
734
+ "/h"
561
735
  ] })
562
736
  ] }),
563
- /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[10px] font-mono uppercase tracking-widest text-[var(--text-muted)]", children: [
564
- /* @__PURE__ */ jsx2("span", { children: "Memory" }),
565
- /* @__PURE__ */ jsxs2("span", { className: "text-[var(--text-secondary)]", children: [
737
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
738
+ /* @__PURE__ */ jsx2("span", { children: "MEMORY" }),
739
+ /* @__PURE__ */ jsxs2("span", { className: "text-foreground/80", children: [
566
740
  "$",
567
741
  (ramGB * 5e-3).toFixed(2)
568
742
  ] })
569
743
  ] })
570
744
  ] })
571
- ] })
745
+ ] }),
746
+ /* @__PURE__ */ jsx2("div", { className: "space-y-3", children: isMultistep ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
747
+ currentStep < 3 ? /* @__PURE__ */ jsxs2(
748
+ "button",
749
+ {
750
+ type: "button",
751
+ onClick: () => setCurrentStep((s) => s + 1),
752
+ className: "w-full relative overflow-hidden h-12 bg-accent/10 text-accent font-extrabold text-sm rounded-2xl border border-accent/20 hover:bg-accent/20 transition-colors shadow-sm shadow-accent/10",
753
+ children: [
754
+ "Continue to ",
755
+ currentStep === 1 ? "Resources" : "Agent Config"
756
+ ]
757
+ }
758
+ ) : /* @__PURE__ */ jsxs2(
759
+ "button",
760
+ {
761
+ type: "button",
762
+ onClick: handleDeploy,
763
+ disabled: isDeploying || !selectedEnv,
764
+ className: "w-full relative overflow-hidden h-12 bg-gradient-to-r from-accent to-accent-deep text-white font-extrabold text-sm rounded-2xl tracking-wide shadow-[0_0_20px_rgba(130,99,255,0.2)] disabled:opacity-50 transition-transform active:scale-[0.98]",
765
+ children: [
766
+ isDeploying ? /* @__PURE__ */ jsxs2("span", { className: "relative z-10 flex items-center justify-center gap-2", children: [
767
+ /* @__PURE__ */ jsx2(Loader2, { className: "h-4 w-4 animate-spin" }),
768
+ "Deploying..."
769
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "relative z-10", children: "Deploy Workspace" }),
770
+ /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 bg-white/20 opacity-0 hover:opacity-100 transition-opacity" })
771
+ ]
772
+ }
773
+ ),
774
+ currentStep > 1 && /* @__PURE__ */ jsx2(
775
+ "button",
776
+ {
777
+ type: "button",
778
+ onClick: () => setCurrentStep((s) => s - 1),
779
+ className: "w-full h-10 glass-panel text-foreground/70 font-bold text-sm rounded-2xl hover:text-foreground hover:border-[var(--glass-border-color)] transition-colors",
780
+ children: "Back"
781
+ }
782
+ )
783
+ ] }) : /* @__PURE__ */ jsxs2(
784
+ "button",
785
+ {
786
+ type: "button",
787
+ onClick: handleDeploy,
788
+ disabled: isDeploying || !selectedEnv,
789
+ className: "w-full relative overflow-hidden h-12 bg-gradient-to-r from-accent to-accent-deep text-white font-extrabold text-sm rounded-2xl tracking-wide shadow-[0_0_20px_rgba(130,99,255,0.2)] disabled:opacity-50 transition-transform active:scale-[0.98]",
790
+ children: [
791
+ isDeploying ? /* @__PURE__ */ jsxs2("span", { className: "relative z-10 flex items-center justify-center gap-2", children: [
792
+ /* @__PURE__ */ jsx2(Loader2, { className: "h-4 w-4 animate-spin" }),
793
+ "Spinning up environment..."
794
+ ] }) : /* @__PURE__ */ jsx2("span", { className: "relative z-10", children: "Deploy Workspace" }),
795
+ /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 bg-white/20 opacity-0 hover:opacity-100 transition-opacity" })
796
+ ]
797
+ }
798
+ ) })
572
799
  ] })
573
800
  ] })
574
801
  ] });
@@ -576,73 +803,28 @@ function ProvisioningWizard({
576
803
 
577
804
  // src/pages/pricing-page.tsx
578
805
  import * as React3 from "react";
806
+ import { ChevronDown } from "lucide-react";
579
807
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
580
- var variantColors = {
581
- sandbox: {
582
- accent: "text-[var(--accent-text)]",
583
- gradient: "bg-[image:var(--accent-gradient-strong)]"
584
- }
585
- };
586
808
  async function fetchTiersFromApi(apiBasePath) {
587
809
  const res = await fetch(`${apiBasePath}/v1/billing/tiers`);
588
- if (!res.ok) {
589
- throw new Error("Failed to fetch pricing tiers");
590
- }
810
+ if (!res.ok) throw new Error("Failed to fetch pricing tiers");
591
811
  const data = await res.json();
592
812
  return data.tiers || data;
593
813
  }
594
- function PricingPageSkeleton() {
595
- return /* @__PURE__ */ jsxs3("div", { className: "space-y-8", children: [
596
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-center gap-4", children: [
597
- /* @__PURE__ */ jsx3(Skeleton, { className: "h-10 w-24" }),
598
- /* @__PURE__ */ jsx3(Skeleton, { className: "h-10 w-24" })
599
- ] }),
600
- /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: [
601
- /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-96" }),
602
- /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-96" }),
603
- /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-96" })
604
- ] })
605
- ] });
606
- }
607
- function PricingPageError({
608
- message,
609
- onRetry
610
- }) {
611
- return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center space-y-4 rounded-xl border border-destructive/20 bg-destructive/5 p-8 text-center", children: [
612
- /* @__PURE__ */ jsx3("div", { className: "rounded-full bg-destructive/10 p-3", children: /* @__PURE__ */ jsxs3(
613
- "svg",
614
- {
615
- xmlns: "http://www.w3.org/2000/svg",
616
- viewBox: "0 0 24 24",
617
- fill: "none",
618
- stroke: "currentColor",
619
- strokeWidth: "2",
620
- strokeLinecap: "round",
621
- strokeLinejoin: "round",
622
- className: "h-6 w-6 text-destructive",
623
- children: [
624
- /* @__PURE__ */ jsx3("title", { children: "Error icon" }),
625
- /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
626
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12", y1: "8", y2: "12" }),
627
- /* @__PURE__ */ jsx3("line", { x1: "12", x2: "12.01", y1: "16", y2: "16" })
628
- ]
629
- }
630
- ) }),
631
- /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
632
- /* @__PURE__ */ jsx3("h3", { className: "font-semibold text-lg", children: "Failed to load pricing" }),
633
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-sm", children: message })
634
- ] }),
635
- /* @__PURE__ */ jsx3(
636
- "button",
637
- {
638
- type: "button",
639
- onClick: onRetry,
640
- className: "rounded-lg bg-primary px-4 py-2 font-medium text-primary-foreground text-sm transition-colors hover:bg-primary/90",
641
- children: "Try Again"
642
- }
643
- )
644
- ] });
645
- }
814
+ var FAQ = [
815
+ {
816
+ q: "What are credits?",
817
+ a: "Credits are used to pay for AI model usage. Different models consume different amounts of credits based on their complexity and the length of your requests."
818
+ },
819
+ {
820
+ q: "Can I change plans later?",
821
+ a: "Yes. You can upgrade or downgrade your plan at any time. When you upgrade, you are charged the prorated difference. When you downgrade, the change takes effect at the end of your billing cycle."
822
+ },
823
+ {
824
+ q: "Do unused credits roll over?",
825
+ a: "Monthly credits do not roll over to the next month. However, purchased credit packs never expire and can be used at any time."
826
+ }
827
+ ];
646
828
  function StandalonePricingPage({
647
829
  variant = "sandbox",
648
830
  initialTiers,
@@ -653,7 +835,6 @@ function StandalonePricingPage({
653
835
  subtitle = "Choose the plan that fits your needs. Upgrade or downgrade at any time.",
654
836
  className
655
837
  }) {
656
- const colors = variantColors[variant];
657
838
  const [state, setState] = React3.useState({
658
839
  tiers: initialTiers || [],
659
840
  loading: !initialTiers,
@@ -690,20 +871,12 @@ function StandalonePricingPage({
690
871
  const res = await fetch(`${apiBasePath}/v1/billing/subscribe`, {
691
872
  method: "POST",
692
873
  headers: { "Content-Type": "application/json" },
693
- body: JSON.stringify({
694
- tierId,
695
- billingPeriod: state.billingPeriod
696
- })
874
+ body: JSON.stringify({ tierId, billingPeriod: state.billingPeriod })
697
875
  });
698
- if (!res.ok) {
699
- throw new Error("Failed to initiate subscription");
700
- }
876
+ if (!res.ok) throw new Error("Failed to initiate subscription");
701
877
  const { checkoutUrl, loginUrl } = await res.json();
702
- if (loginUrl) {
703
- window.location.href = loginUrl;
704
- } else if (checkoutUrl) {
705
- window.location.href = checkoutUrl;
706
- }
878
+ if (loginUrl) window.location.href = loginUrl;
879
+ else if (checkoutUrl) window.location.href = checkoutUrl;
707
880
  } catch (err) {
708
881
  setState((prev) => ({
709
882
  ...prev,
@@ -714,111 +887,52 @@ function StandalonePricingPage({
714
887
  },
715
888
  [apiBasePath, state.billingPeriod, onSelectTier]
716
889
  );
717
- const handleBillingPeriodChange = React3.useCallback(
718
- (period) => {
719
- setState((prev) => ({ ...prev, billingPeriod: period }));
720
- },
721
- []
722
- );
723
- return /* @__PURE__ */ jsxs3("div", { className: cn("w-full space-y-12", className), children: [
890
+ return /* @__PURE__ */ jsxs3("div", { className: cn("mx-auto max-w-6xl px-6 py-16 space-y-16", className), children: [
724
891
  /* @__PURE__ */ jsxs3("div", { className: "space-y-4 text-center", children: [
892
+ /* @__PURE__ */ jsx3("h1", { className: "text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl", children: title }),
893
+ /* @__PURE__ */ jsx3("p", { className: "mx-auto max-w-2xl text-lg text-muted-foreground", children: subtitle })
894
+ ] }),
895
+ state.loading ? /* @__PURE__ */ jsxs3("div", { className: "space-y-8", children: [
896
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-center gap-4", children: [
897
+ /* @__PURE__ */ jsx3(Skeleton, { className: "h-10 w-24" }),
898
+ /* @__PURE__ */ jsx3(Skeleton, { className: "h-10 w-24" })
899
+ ] }),
900
+ /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-3", children: [
901
+ /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-[500px]" }),
902
+ /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-[500px]" }),
903
+ /* @__PURE__ */ jsx3(SkeletonCard, { className: "h-[500px]" })
904
+ ] })
905
+ ] }) : state.error ? /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center space-y-4 rounded-xl border border-destructive/20 bg-destructive/5 p-8 text-center", children: [
906
+ /* @__PURE__ */ jsx3("p", { className: "text-destructive text-sm font-medium", children: state.error }),
725
907
  /* @__PURE__ */ jsx3(
726
- "h1",
908
+ "button",
727
909
  {
728
- className: cn(
729
- "font-bold text-4xl tracking-tight sm:text-5xl",
730
- "bg-clip-text text-transparent",
731
- colors.gradient
732
- ),
733
- children: title
910
+ type: "button",
911
+ onClick: loadTiers,
912
+ className: "rounded-lg bg-primary px-4 py-2 font-medium text-primary-foreground text-sm hover:bg-primary/90 transition-colors",
913
+ children: "Try Again"
734
914
  }
735
- ),
736
- /* @__PURE__ */ jsx3("p", { className: "mx-auto max-w-2xl text-lg text-muted-foreground", children: subtitle })
737
- ] }),
738
- state.loading ? /* @__PURE__ */ jsx3(PricingPageSkeleton, {}) : state.error ? /* @__PURE__ */ jsx3(PricingPageError, { message: state.error, onRetry: loadTiers }) : /* @__PURE__ */ jsx3(
915
+ )
916
+ ] }) : /* @__PURE__ */ jsx3(
739
917
  PricingPage,
740
918
  {
741
919
  tiers: state.tiers,
742
920
  billingPeriod: state.billingPeriod,
743
- onBillingPeriodChange: handleBillingPeriodChange,
921
+ onBillingPeriodChange: (p) => setState((prev) => ({ ...prev, billingPeriod: p })),
744
922
  onSelectTier: handleSelectTier,
745
923
  variant,
746
924
  loading: state.selectingTier
747
925
  }
748
926
  ),
749
- /* @__PURE__ */ jsxs3("div", { className: "mx-auto max-w-3xl space-y-6 border-border border-t pt-8", children: [
750
- /* @__PURE__ */ jsx3("h2", { className: "text-center font-semibold text-xl", children: "Frequently Asked Questions" }),
751
- /* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
752
- /* @__PURE__ */ jsxs3("details", { className: "group rounded-lg border border-border bg-card p-4", children: [
753
- /* @__PURE__ */ jsxs3("summary", { className: "flex cursor-pointer list-none items-center justify-between font-medium", children: [
754
- "What are credits?",
755
- /* @__PURE__ */ jsxs3(
756
- "svg",
757
- {
758
- xmlns: "http://www.w3.org/2000/svg",
759
- viewBox: "0 0 24 24",
760
- fill: "none",
761
- stroke: "currentColor",
762
- strokeWidth: "2",
763
- strokeLinecap: "round",
764
- strokeLinejoin: "round",
765
- className: "h-4 w-4 transition-transform group-open:rotate-180",
766
- children: [
767
- /* @__PURE__ */ jsx3("title", { children: "Toggle icon" }),
768
- /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" })
769
- ]
770
- }
771
- )
772
- ] }),
773
- /* @__PURE__ */ jsx3("p", { className: "mt-3 text-muted-foreground text-sm", children: "Credits are used to pay for AI model usage. Different models consume different amounts of credits based on their complexity and the length of your requests." })
927
+ /* @__PURE__ */ jsxs3("div", { className: "mx-auto max-w-2xl space-y-4 border-t border-border pt-12", children: [
928
+ /* @__PURE__ */ jsx3("h2", { className: "text-center text-xl font-bold text-foreground mb-6", children: "Frequently Asked Questions" }),
929
+ FAQ.map(({ q, a }) => /* @__PURE__ */ jsxs3("details", { className: "group rounded-xl border border-border bg-card overflow-hidden", children: [
930
+ /* @__PURE__ */ jsxs3("summary", { className: "flex cursor-pointer items-center justify-between px-6 py-4 font-medium text-foreground text-sm", children: [
931
+ q,
932
+ /* @__PURE__ */ jsx3(ChevronDown, { className: "h-4 w-4 text-muted-foreground transition-transform group-open:rotate-180" })
774
933
  ] }),
775
- /* @__PURE__ */ jsxs3("details", { className: "group rounded-lg border border-border bg-card p-4", children: [
776
- /* @__PURE__ */ jsxs3("summary", { className: "flex cursor-pointer list-none items-center justify-between font-medium", children: [
777
- "Can I change plans later?",
778
- /* @__PURE__ */ jsxs3(
779
- "svg",
780
- {
781
- xmlns: "http://www.w3.org/2000/svg",
782
- viewBox: "0 0 24 24",
783
- fill: "none",
784
- stroke: "currentColor",
785
- strokeWidth: "2",
786
- strokeLinecap: "round",
787
- strokeLinejoin: "round",
788
- className: "h-4 w-4 transition-transform group-open:rotate-180",
789
- children: [
790
- /* @__PURE__ */ jsx3("title", { children: "Toggle icon" }),
791
- /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" })
792
- ]
793
- }
794
- )
795
- ] }),
796
- /* @__PURE__ */ jsx3("p", { className: "mt-3 text-muted-foreground text-sm", children: "Yes! You can upgrade or downgrade your plan at any time. When you upgrade, you will be charged the prorated difference. When you downgrade, the change takes effect at the end of your billing cycle." })
797
- ] }),
798
- /* @__PURE__ */ jsxs3("details", { className: "group rounded-lg border border-border bg-card p-4", children: [
799
- /* @__PURE__ */ jsxs3("summary", { className: "flex cursor-pointer list-none items-center justify-between font-medium", children: [
800
- "Do unused credits roll over?",
801
- /* @__PURE__ */ jsxs3(
802
- "svg",
803
- {
804
- xmlns: "http://www.w3.org/2000/svg",
805
- viewBox: "0 0 24 24",
806
- fill: "none",
807
- stroke: "currentColor",
808
- strokeWidth: "2",
809
- strokeLinecap: "round",
810
- strokeLinejoin: "round",
811
- className: "h-4 w-4 transition-transform group-open:rotate-180",
812
- children: [
813
- /* @__PURE__ */ jsx3("title", { children: "Toggle icon" }),
814
- /* @__PURE__ */ jsx3("path", { d: "m6 9 6 6 6-6" })
815
- ]
816
- }
817
- )
818
- ] }),
819
- /* @__PURE__ */ jsx3("p", { className: "mt-3 text-muted-foreground text-sm", children: "Monthly credits do not roll over to the next month. However, purchased credit packs never expire and can be used at any time." })
820
- ] })
821
- ] })
934
+ /* @__PURE__ */ jsx3("div", { className: "px-6 pb-4", children: /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground leading-relaxed", children: a }) })
935
+ ] }, q))
822
936
  ] })
823
937
  ] });
824
938
  }
@@ -829,11 +943,11 @@ import {
829
943
  ChevronRight,
830
944
  Copy,
831
945
  Edit2,
832
- Loader2,
833
- Plus,
946
+ Loader2 as Loader22,
947
+ Plus as Plus2,
834
948
  Search,
835
949
  Settings2,
836
- Trash2
950
+ Trash2 as Trash22
837
951
  } from "lucide-react";
838
952
  import * as React4 from "react";
839
953
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -910,7 +1024,7 @@ function ProfilesPage({
910
1024
  onClick: () => setCreateDialogOpen(true),
911
1025
  disabled: !canCreateMore,
912
1026
  children: [
913
- /* @__PURE__ */ jsx4(Plus, { className: "mr-2 h-4 w-4" }),
1027
+ /* @__PURE__ */ jsx4(Plus2, { className: "mr-2 h-4 w-4" }),
914
1028
  "Create Profile"
915
1029
  ]
916
1030
  }
@@ -942,7 +1056,7 @@ function ProfilesPage({
942
1056
  /* @__PURE__ */ jsx4("span", { children: error }),
943
1057
  /* @__PURE__ */ jsx4(Button, { variant: "ghost", size: "sm", onClick: loadProfiles, children: "Retry" })
944
1058
  ] }),
945
- loading && /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx4(Loader2, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }),
1059
+ loading && /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx4(Loader22, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }),
946
1060
  !loading && /* @__PURE__ */ jsxs4("div", { className: "space-y-8", children: [
947
1061
  /* @__PURE__ */ jsxs4("section", { children: [
948
1062
  /* @__PURE__ */ jsx4("div", { className: "mb-3 flex items-center justify-between", children: /* @__PURE__ */ jsxs4("h2", { className: "font-medium text-lg", children: [
@@ -959,7 +1073,7 @@ function ProfilesPage({
959
1073
  title: "No custom profiles yet",
960
1074
  description: "Create a profile to customize agent behavior",
961
1075
  action: canCreateMore ? /* @__PURE__ */ jsxs4(Button, { onClick: () => setCreateDialogOpen(true), children: [
962
- /* @__PURE__ */ jsx4(Plus, { className: "mr-2 h-4 w-4" }),
1076
+ /* @__PURE__ */ jsx4(Plus2, { className: "mr-2 h-4 w-4" }),
963
1077
  "Create Profile"
964
1078
  ] }) : void 0
965
1079
  }
@@ -1083,7 +1197,7 @@ function ProfileCard({
1083
1197
  size: "icon",
1084
1198
  onClick: onDelete,
1085
1199
  "aria-label": "Delete profile",
1086
- children: /* @__PURE__ */ jsx4(Trash2, { className: "h-4 w-4 text-[var(--surface-danger-text)]" })
1200
+ children: /* @__PURE__ */ jsx4(Trash22, { className: "h-4 w-4 text-[var(--surface-danger-text)]" })
1087
1201
  }
1088
1202
  )
1089
1203
  ] })
@@ -1301,7 +1415,7 @@ function ProfileFormDialog({
1301
1415
  /* @__PURE__ */ jsxs4(DialogFooter, { children: [
1302
1416
  /* @__PURE__ */ jsx4(Button, { type: "button", variant: "outline", onClick: onClose, children: "Cancel" }),
1303
1417
  /* @__PURE__ */ jsxs4(Button, { type: "submit", disabled: saving || !formData.name, children: [
1304
- saving && /* @__PURE__ */ jsx4(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1418
+ saving && /* @__PURE__ */ jsx4(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
1305
1419
  isEditing ? "Save Changes" : "Create Profile"
1306
1420
  ] })
1307
1421
  ] })
@@ -1356,7 +1470,7 @@ function DeleteProfileDialog({
1356
1470
  onClick: handleDelete,
1357
1471
  disabled: deleting,
1358
1472
  children: [
1359
- deleting && /* @__PURE__ */ jsx4(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1473
+ deleting && /* @__PURE__ */ jsx4(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
1360
1474
  "Delete Profile"
1361
1475
  ]
1362
1476
  }
@@ -1460,10 +1574,450 @@ function ProfileDetailDialog({
1460
1574
  ] })
1461
1575
  ] }) });
1462
1576
  }
1577
+
1578
+ // src/pages/secrets-page.tsx
1579
+ import * as React5 from "react";
1580
+ import { Lock, Plus as Plus3, Trash2 as Trash23, Eye, EyeOff, AlertCircle as AlertCircle2 } from "lucide-react";
1581
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1582
+ function SecretsPage({ apiClient, className }) {
1583
+ const [secrets, setSecrets] = React5.useState([]);
1584
+ const [loading, setLoading] = React5.useState(true);
1585
+ const [error, setError] = React5.useState(null);
1586
+ const [isCreateOpen, setIsCreateOpen] = React5.useState(false);
1587
+ const [newName, setNewName] = React5.useState("");
1588
+ const [newValue, setNewValue] = React5.useState("");
1589
+ const [showValue, setShowValue] = React5.useState(false);
1590
+ const [isCreating, setIsCreating] = React5.useState(false);
1591
+ const [createError, setCreateError] = React5.useState(null);
1592
+ const [deleteTarget, setDeleteTarget] = React5.useState(null);
1593
+ const [isDeleting, setIsDeleting] = React5.useState(false);
1594
+ const apiRef = React5.useRef(apiClient);
1595
+ apiRef.current = apiClient;
1596
+ const loadSecrets = React5.useCallback(async () => {
1597
+ try {
1598
+ setLoading(true);
1599
+ setError(null);
1600
+ const data = await apiRef.current.listSecrets();
1601
+ setSecrets(data);
1602
+ } catch (err) {
1603
+ setError(err instanceof Error ? err.message : "Failed to load secrets");
1604
+ } finally {
1605
+ setLoading(false);
1606
+ }
1607
+ }, []);
1608
+ React5.useEffect(() => {
1609
+ loadSecrets();
1610
+ }, [loadSecrets]);
1611
+ const handleCreate = async () => {
1612
+ if (!newName.trim()) return;
1613
+ setIsCreating(true);
1614
+ setCreateError(null);
1615
+ try {
1616
+ await apiRef.current.createSecret(newName.trim(), newValue);
1617
+ setIsCreateOpen(false);
1618
+ setNewName("");
1619
+ setNewValue("");
1620
+ setShowValue(false);
1621
+ loadSecrets();
1622
+ } catch (err) {
1623
+ setCreateError(err instanceof Error ? err.message : "Failed to create secret");
1624
+ } finally {
1625
+ setIsCreating(false);
1626
+ }
1627
+ };
1628
+ const handleDelete = async (name) => {
1629
+ setIsDeleting(true);
1630
+ try {
1631
+ await apiRef.current.deleteSecret(name);
1632
+ setDeleteTarget(null);
1633
+ loadSecrets();
1634
+ } catch (err) {
1635
+ setError(err instanceof Error ? err.message : "Failed to delete secret");
1636
+ } finally {
1637
+ setIsDeleting(false);
1638
+ }
1639
+ };
1640
+ const formatDate = (dateStr) => {
1641
+ try {
1642
+ const ts = /^\d+$/.test(dateStr) ? Number(dateStr) : dateStr;
1643
+ const date = new Date(ts);
1644
+ if (Number.isNaN(date.getTime())) return dateStr;
1645
+ return date.toLocaleDateString();
1646
+ } catch {
1647
+ return dateStr;
1648
+ }
1649
+ };
1650
+ return /* @__PURE__ */ jsxs5("div", { className: cn("space-y-6", className), children: [
1651
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
1652
+ /* @__PURE__ */ jsxs5("div", { children: [
1653
+ /* @__PURE__ */ jsx5("h1", { className: "font-bold text-3xl text-foreground", children: "Secrets" }),
1654
+ /* @__PURE__ */ jsx5("p", { className: "mt-1 text-muted-foreground", children: "Secrets securely stored here will be automatically exposed as environment variables across all your new sandboxes." })
1655
+ ] }),
1656
+ /* @__PURE__ */ jsxs5(
1657
+ "button",
1658
+ {
1659
+ type: "button",
1660
+ onClick: () => setIsCreateOpen(true),
1661
+ className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-bold text-primary hover:bg-primary hover:text-primary-foreground transition-colors active:scale-[0.97]",
1662
+ children: [
1663
+ /* @__PURE__ */ jsx5(Plus3, { className: "h-4 w-4" }),
1664
+ "Create Secret"
1665
+ ]
1666
+ }
1667
+ )
1668
+ ] }),
1669
+ error && /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-destructive/30 bg-destructive/10 p-4 flex items-center gap-3", children: [
1670
+ /* @__PURE__ */ jsx5(AlertCircle2, { className: "h-5 w-5 text-destructive shrink-0" }),
1671
+ /* @__PURE__ */ jsx5("p", { className: "text-destructive text-sm font-medium", children: error })
1672
+ ] }),
1673
+ /* @__PURE__ */ jsx5(Dialog, { open: isCreateOpen, onOpenChange: (open) => {
1674
+ if (!open) {
1675
+ setIsCreateOpen(false);
1676
+ setNewName("");
1677
+ setNewValue("");
1678
+ setCreateError(null);
1679
+ setShowValue(false);
1680
+ }
1681
+ }, children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-w-md", children: [
1682
+ /* @__PURE__ */ jsxs5(DialogHeader, { children: [
1683
+ /* @__PURE__ */ jsx5(DialogTitle, { children: "Create Secret" }),
1684
+ /* @__PURE__ */ jsx5(DialogDescription, { children: "Secrets securely stored here will be automatically exposed as environment variables across all your new sandboxes." })
1685
+ ] }),
1686
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
1687
+ /* @__PURE__ */ jsxs5("div", { children: [
1688
+ /* @__PURE__ */ jsx5("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: "Name" }),
1689
+ /* @__PURE__ */ jsx5(
1690
+ "input",
1691
+ {
1692
+ type: "text",
1693
+ value: newName,
1694
+ onChange: (e) => setNewName(e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g, "_")),
1695
+ placeholder: "MY_SECRET_KEY",
1696
+ className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
1697
+ }
1698
+ )
1699
+ ] }),
1700
+ /* @__PURE__ */ jsxs5("div", { children: [
1701
+ /* @__PURE__ */ jsx5("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: "Value" }),
1702
+ /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
1703
+ /* @__PURE__ */ jsx5(
1704
+ "input",
1705
+ {
1706
+ type: showValue ? "text" : "password",
1707
+ value: newValue,
1708
+ onChange: (e) => setNewValue(e.target.value),
1709
+ placeholder: "Enter secret value...",
1710
+ className: "w-full rounded-lg border border-border bg-background px-3 py-2 pr-10 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
1711
+ }
1712
+ ),
1713
+ /* @__PURE__ */ jsx5(
1714
+ "button",
1715
+ {
1716
+ type: "button",
1717
+ onClick: () => setShowValue(!showValue),
1718
+ className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 text-muted-foreground hover:text-foreground",
1719
+ children: showValue ? /* @__PURE__ */ jsx5(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx5(Eye, { className: "h-4 w-4" })
1720
+ }
1721
+ )
1722
+ ] }),
1723
+ /* @__PURE__ */ jsx5("p", { className: "mt-1.5 text-xs text-muted-foreground", children: "This value cannot be retrieved after creation." })
1724
+ ] })
1725
+ ] }),
1726
+ createError && /* @__PURE__ */ jsx5("p", { className: "mt-3 text-sm text-destructive", children: createError }),
1727
+ /* @__PURE__ */ jsxs5(DialogFooter, { children: [
1728
+ /* @__PURE__ */ jsx5(
1729
+ "button",
1730
+ {
1731
+ type: "button",
1732
+ onClick: () => {
1733
+ setIsCreateOpen(false);
1734
+ setNewName("");
1735
+ setNewValue("");
1736
+ setCreateError(null);
1737
+ },
1738
+ className: "rounded-lg border border-border bg-muted px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/80 transition-colors",
1739
+ children: "Cancel"
1740
+ }
1741
+ ),
1742
+ /* @__PURE__ */ jsx5(
1743
+ "button",
1744
+ {
1745
+ type: "button",
1746
+ onClick: handleCreate,
1747
+ disabled: !newName.trim() || !newValue || isCreating,
1748
+ className: "rounded-lg bg-primary px-4 py-2 text-sm font-bold text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 active:scale-[0.97]",
1749
+ children: isCreating ? "Creating..." : "Create Secret"
1750
+ }
1751
+ )
1752
+ ] })
1753
+ ] }) }),
1754
+ /* @__PURE__ */ jsx5(Dialog, { open: !!deleteTarget, onOpenChange: (open) => {
1755
+ if (!open) setDeleteTarget(null);
1756
+ }, children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-w-sm", children: [
1757
+ /* @__PURE__ */ jsxs5(DialogHeader, { children: [
1758
+ /* @__PURE__ */ jsx5(DialogTitle, { children: "Delete Secret?" }),
1759
+ /* @__PURE__ */ jsxs5(DialogDescription, { children: [
1760
+ "This will permanently delete ",
1761
+ /* @__PURE__ */ jsx5("span", { className: "font-mono font-bold text-foreground", children: deleteTarget }),
1762
+ ". Sandboxes using this secret will lose access to it."
1763
+ ] })
1764
+ ] }),
1765
+ /* @__PURE__ */ jsxs5(DialogFooter, { children: [
1766
+ /* @__PURE__ */ jsx5(
1767
+ "button",
1768
+ {
1769
+ type: "button",
1770
+ onClick: () => setDeleteTarget(null),
1771
+ className: "rounded-lg border border-border bg-muted px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/80 transition-colors",
1772
+ children: "Cancel"
1773
+ }
1774
+ ),
1775
+ /* @__PURE__ */ jsx5(
1776
+ "button",
1777
+ {
1778
+ type: "button",
1779
+ onClick: () => deleteTarget && handleDelete(deleteTarget),
1780
+ disabled: isDeleting,
1781
+ className: "rounded-lg bg-destructive px-4 py-2 text-sm font-bold text-destructive-foreground hover:bg-destructive/90 transition-colors disabled:opacity-50 active:scale-[0.97]",
1782
+ children: isDeleting ? "Deleting..." : "Delete Secret"
1783
+ }
1784
+ )
1785
+ ] })
1786
+ ] }) }),
1787
+ /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-border bg-card shadow-sm overflow-hidden", children: [
1788
+ /* @__PURE__ */ jsxs5("div", { className: "border-b border-border bg-muted/20 px-6 py-4 flex items-center justify-between", children: [
1789
+ /* @__PURE__ */ jsx5("h2", { className: "text-sm font-bold text-foreground", children: "Your Secrets" }),
1790
+ /* @__PURE__ */ jsxs5("span", { className: "text-xs text-muted-foreground font-mono", children: [
1791
+ secrets.length,
1792
+ " secret",
1793
+ secrets.length !== 1 ? "s" : ""
1794
+ ] })
1795
+ ] }),
1796
+ loading ? /* @__PURE__ */ jsx5("div", { className: "p-12 text-center", children: /* @__PURE__ */ jsx5("div", { className: "mx-auto h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : secrets.length === 0 ? /* @__PURE__ */ jsxs5("div", { className: "p-12 text-center", children: [
1797
+ /* @__PURE__ */ jsx5(Lock, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }),
1798
+ /* @__PURE__ */ jsx5("p", { className: "text-sm font-medium text-foreground mb-1", children: "No secrets yet" }),
1799
+ /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground mb-4", children: "Create a secret to inject into your sandboxes." }),
1800
+ /* @__PURE__ */ jsxs5(
1801
+ "button",
1802
+ {
1803
+ type: "button",
1804
+ onClick: () => setIsCreateOpen(true),
1805
+ className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-bold text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
1806
+ children: [
1807
+ /* @__PURE__ */ jsx5(Plus3, { className: "h-4 w-4" }),
1808
+ "Create Secret"
1809
+ ]
1810
+ }
1811
+ )
1812
+ ] }) : /* @__PURE__ */ jsxs5("table", { className: "w-full text-sm", children: [
1813
+ /* @__PURE__ */ jsx5("thead", { className: "bg-muted/10 border-b border-border", children: /* @__PURE__ */ jsxs5("tr", { children: [
1814
+ /* @__PURE__ */ jsx5("th", { className: "px-6 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Name" }),
1815
+ /* @__PURE__ */ jsx5("th", { className: "px-6 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Created" }),
1816
+ /* @__PURE__ */ jsx5("th", { className: "px-6 py-2.5 text-right text-xs font-medium text-muted-foreground w-16" })
1817
+ ] }) }),
1818
+ /* @__PURE__ */ jsx5("tbody", { className: "divide-y divide-border", children: secrets.map((secret) => /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-muted/30 transition-colors", children: [
1819
+ /* @__PURE__ */ jsx5("td", { className: "px-6 py-3", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
1820
+ /* @__PURE__ */ jsx5(Lock, { className: "h-3.5 w-3.5 text-muted-foreground" }),
1821
+ /* @__PURE__ */ jsx5("span", { className: "font-mono text-xs font-bold text-foreground", children: secret.name })
1822
+ ] }) }),
1823
+ /* @__PURE__ */ jsx5("td", { className: "px-6 py-3 text-xs text-muted-foreground", children: formatDate(secret.createdAt) }),
1824
+ /* @__PURE__ */ jsx5("td", { className: "px-6 py-3 text-right", children: /* @__PURE__ */ jsx5(
1825
+ "button",
1826
+ {
1827
+ type: "button",
1828
+ onClick: () => setDeleteTarget(secret.name),
1829
+ className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
1830
+ children: /* @__PURE__ */ jsx5(Trash23, { className: "h-4 w-4" })
1831
+ }
1832
+ ) })
1833
+ ] }, secret.name)) })
1834
+ ] })
1835
+ ] })
1836
+ ] });
1837
+ }
1838
+
1839
+ // src/pages/templates-page.tsx
1840
+ import { Layers as Layers2 } from "lucide-react";
1841
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1842
+ function TemplatesPage({ templates, loading = false, onUseTemplate, className }) {
1843
+ return /* @__PURE__ */ jsxs6("div", { className: cn("space-y-8", className), children: [
1844
+ /* @__PURE__ */ jsxs6("div", { children: [
1845
+ /* @__PURE__ */ jsx6("h1", { className: "font-bold text-3xl text-foreground", children: "Templates" }),
1846
+ /* @__PURE__ */ jsx6("p", { className: "mt-1 text-muted-foreground", children: "Pre-configured environments to get started quickly" })
1847
+ ] }),
1848
+ loading || !templates ? /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx6(Skeleton, { className: "h-56 rounded-2xl" }, i)) }) : templates.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "rounded-2xl border border-border bg-card p-16 text-center", children: [
1849
+ /* @__PURE__ */ jsx6(Layers2, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }),
1850
+ /* @__PURE__ */ jsx6("p", { className: "text-sm font-medium text-foreground mb-1", children: "No templates available" }),
1851
+ /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "Check back later for pre-configured environments." })
1852
+ ] }) : /* @__PURE__ */ jsx6("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: templates.map((template) => /* @__PURE__ */ jsx6(
1853
+ TemplateCard,
1854
+ {
1855
+ template,
1856
+ onUseTemplate
1857
+ },
1858
+ template.id
1859
+ )) })
1860
+ ] });
1861
+ }
1862
+
1863
+ // src/lib/template-presets.ts
1864
+ var BLOCKCHAIN_PATTERNS = [
1865
+ "ethereum",
1866
+ "solana",
1867
+ "arbitrum",
1868
+ "base-aa",
1869
+ "base-l2",
1870
+ "polygon",
1871
+ "tangle",
1872
+ "chainlink",
1873
+ "foundry",
1874
+ "hardhat",
1875
+ "optimism",
1876
+ "zksync",
1877
+ "starknet",
1878
+ "cosmos",
1879
+ "near",
1880
+ "aptos",
1881
+ "sui",
1882
+ "ton",
1883
+ "injective",
1884
+ "gnosis",
1885
+ "linea",
1886
+ "monad",
1887
+ "reth",
1888
+ "soneium",
1889
+ "xlayer",
1890
+ "coinbase",
1891
+ "farcaster",
1892
+ "worldcoin",
1893
+ "x402-payments",
1894
+ "xmtp",
1895
+ "openzeppelin",
1896
+ "biconomy",
1897
+ "gelato",
1898
+ "hyperlane",
1899
+ "hyperliquid",
1900
+ "lifi",
1901
+ "polymer",
1902
+ "risc0",
1903
+ "stylus",
1904
+ "succinct",
1905
+ "fhenix",
1906
+ "rindexer",
1907
+ "ai-agent-web3"
1908
+ ];
1909
+ var AI_ML_PATTERNS = [
1910
+ "pytorch",
1911
+ "tensorflow",
1912
+ "huggingface",
1913
+ "chromadb",
1914
+ "langchain",
1915
+ "llamaindex",
1916
+ "ai-sdk",
1917
+ "ollama",
1918
+ "vllm",
1919
+ "pgvector",
1920
+ "qdrant",
1921
+ "milvus",
1922
+ "weaviate",
1923
+ "mlops",
1924
+ "jupyter",
1925
+ "scientific-python"
1926
+ ];
1927
+ var FRONTEND_PATTERNS = [
1928
+ "react",
1929
+ "next",
1930
+ "vue",
1931
+ "angular",
1932
+ "svelte",
1933
+ "vite",
1934
+ "astro",
1935
+ "remix",
1936
+ "gatsby",
1937
+ "nuxt"
1938
+ ];
1939
+ var INFRASTRUCTURE_PATTERNS = [
1940
+ "redis",
1941
+ "postgresql",
1942
+ "mongodb",
1943
+ "kafka",
1944
+ "elasticsearch",
1945
+ "clickhouse",
1946
+ "minio",
1947
+ "kubernetes",
1948
+ "terraform",
1949
+ "pulumi",
1950
+ "blockscout",
1951
+ "tempo",
1952
+ "convex"
1953
+ ];
1954
+ function categorizeTemplate(id) {
1955
+ const lower = id.toLowerCase();
1956
+ if (BLOCKCHAIN_PATTERNS.some((p) => lower.includes(p))) return "blockchain";
1957
+ if (AI_ML_PATTERNS.some((p) => lower.includes(p))) return "ai-ml";
1958
+ if (FRONTEND_PATTERNS.some((p) => lower.includes(p))) return "frontend";
1959
+ if (INFRASTRUCTURE_PATTERNS.some((p) => lower.includes(p))) return "infrastructure";
1960
+ return "general";
1961
+ }
1962
+ var CATEGORY_DEFAULTS = {
1963
+ blockchain: {
1964
+ environment: "",
1965
+ cpuCores: 4,
1966
+ ramGB: 16,
1967
+ storageGB: 128,
1968
+ modelTier: "claude-sonnet",
1969
+ systemPrompt: "You are a blockchain development assistant. Help with smart contract development, testing, and deployment. Follow security best practices and suggest gas optimizations where relevant.",
1970
+ bare: false
1971
+ },
1972
+ "ai-ml": {
1973
+ environment: "",
1974
+ cpuCores: 8,
1975
+ ramGB: 32,
1976
+ storageGB: 256,
1977
+ modelTier: "claude-sonnet",
1978
+ systemPrompt: "You are an AI/ML development assistant. Help with model training, data processing, and experiment management. Suggest efficient approaches for the available compute resources.",
1979
+ bare: false
1980
+ },
1981
+ frontend: {
1982
+ environment: "",
1983
+ cpuCores: 2,
1984
+ ramGB: 4,
1985
+ storageGB: 50,
1986
+ modelTier: "claude-sonnet",
1987
+ systemPrompt: "You are a frontend development assistant. Help build modern, accessible, and performant user interfaces.",
1988
+ bare: false
1989
+ },
1990
+ infrastructure: {
1991
+ environment: "",
1992
+ cpuCores: 4,
1993
+ ramGB: 16,
1994
+ storageGB: 128,
1995
+ modelTier: "claude-sonnet",
1996
+ systemPrompt: "You are an infrastructure and DevOps assistant. Help with service configuration, deployment, monitoring, and operational best practices.",
1997
+ bare: false
1998
+ },
1999
+ general: {
2000
+ environment: "",
2001
+ cpuCores: 4,
2002
+ ramGB: 16,
2003
+ storageGB: 128,
2004
+ modelTier: "claude-sonnet",
2005
+ systemPrompt: "",
2006
+ bare: false
2007
+ }
2008
+ };
2009
+ function getPresetForTemplate(id) {
2010
+ const category = categorizeTemplate(id);
2011
+ const defaults = CATEGORY_DEFAULTS[category];
2012
+ return { ...defaults, environment: id };
2013
+ }
1463
2014
  export {
1464
2015
  BillingPage,
1465
2016
  ProfilesPage,
1466
2017
  ProvisioningWizard,
2018
+ SecretsPage,
1467
2019
  StandalonePricingPage,
2020
+ TemplatesPage,
2021
+ getPresetForTemplate,
1468
2022
  resolveEnvironment
1469
2023
  };