@tangle-network/sandbox-ui 0.24.1 → 0.24.2

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.
package/dist/pages.js CHANGED
@@ -8,6 +8,12 @@ import {
8
8
  import {
9
9
  Badge,
10
10
  Button,
11
+ Dialog,
12
+ DialogContent,
13
+ DialogDescription,
14
+ DialogFooter,
15
+ DialogHeader,
16
+ DialogTitle,
11
17
  Input,
12
18
  Switch,
13
19
  Textarea
@@ -462,19 +468,177 @@ function BillingPage({
462
468
  }
463
469
 
464
470
  // src/pages/provisioning-wizard.tsx
465
- import * as React2 from "react";
471
+ import * as React3 from "react";
466
472
  import {
467
473
  ArrowLeft,
468
474
  Layers,
469
475
  Cpu,
470
476
  Info,
471
- Loader2,
477
+ Loader2 as Loader22,
472
478
  Settings,
473
479
  Plus,
474
480
  Trash2,
475
481
  Check
476
482
  } from "lucide-react";
477
- import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
483
+
484
+ // src/pages/add-ssh-key-dialog.tsx
485
+ import * as React2 from "react";
486
+ import { Loader2 } from "lucide-react";
487
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
488
+ var NAME_INPUT_ID = "add-ssh-key-name";
489
+ var KEY_INPUT_ID = "add-ssh-key-public-key";
490
+ var SSH_PUBLIC_KEY_PATTERN = /^(ssh-rsa|ssh-dss|ssh-ed25519|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|sk-ecdsa-sha2-nistp256@openssh\.com|sk-ssh-ed25519@openssh\.com)\s+[A-Za-z0-9+/]+={0,3}(\s+.+)?$/;
491
+ function validateSshPublicKey(value) {
492
+ const trimmed = value.trim();
493
+ if (!trimmed) return "Public key is required";
494
+ if (!SSH_PUBLIC_KEY_PATTERN.test(trimmed))
495
+ return "Enter a valid public key, e.g. ssh-ed25519 AAAAC3NzaC1lZDI1NTE5...";
496
+ return null;
497
+ }
498
+ function AddSshKeyDialog({
499
+ open,
500
+ onOpenChange,
501
+ onCreateKey,
502
+ onRefreshKeys,
503
+ onCreatedKeyId
504
+ }) {
505
+ const [name, setName] = React2.useState("");
506
+ const [publicKey, setPublicKey] = React2.useState("");
507
+ const [errors, setErrors] = React2.useState({
508
+ name: null,
509
+ publicKey: null
510
+ });
511
+ const [submitError, setSubmitError] = React2.useState(null);
512
+ const [isSaving, setIsSaving] = React2.useState(false);
513
+ const resetForm = React2.useCallback(() => {
514
+ setName("");
515
+ setPublicKey("");
516
+ setErrors({ name: null, publicKey: null });
517
+ setSubmitError(null);
518
+ }, []);
519
+ const handleSave = async () => {
520
+ const nameError = name.trim() ? null : "Name is required";
521
+ const keyError = validateSshPublicKey(publicKey);
522
+ if (nameError || keyError) {
523
+ setErrors({ name: nameError, publicKey: keyError });
524
+ return;
525
+ }
526
+ setIsSaving(true);
527
+ setSubmitError(null);
528
+ try {
529
+ const created = await onCreateKey({
530
+ name: name.trim(),
531
+ publicKey: publicKey.trim()
532
+ });
533
+ if (onRefreshKeys) {
534
+ await onRefreshKeys();
535
+ }
536
+ if (created && created.id) {
537
+ onCreatedKeyId?.(created.id);
538
+ }
539
+ resetForm();
540
+ onOpenChange(false);
541
+ } catch (err) {
542
+ setSubmitError(
543
+ err instanceof Error ? err.message : "Failed to add SSH key"
544
+ );
545
+ } finally {
546
+ setIsSaving(false);
547
+ }
548
+ };
549
+ const handleSubmit = (e) => {
550
+ e.preventDefault();
551
+ if (!isSaving) handleSave();
552
+ };
553
+ return /* @__PURE__ */ jsx3(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs3(DialogContent, { className: "max-w-md", children: [
554
+ /* @__PURE__ */ jsxs3(DialogHeader, { children: [
555
+ /* @__PURE__ */ jsx3(DialogTitle, { children: "Add SSH key" }),
556
+ /* @__PURE__ */ jsx3(DialogDescription, { children: "Save a public key to your account. It will be available to select for this and future sandboxes." })
557
+ ] }),
558
+ /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
559
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-1.5", children: [
560
+ /* @__PURE__ */ jsx3(
561
+ "label",
562
+ {
563
+ htmlFor: NAME_INPUT_ID,
564
+ className: "block text-xs font-medium uppercase tracking-[0.06em] text-muted-foreground",
565
+ children: "Name"
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsx3(
569
+ "input",
570
+ {
571
+ id: NAME_INPUT_ID,
572
+ name: "name",
573
+ type: "text",
574
+ value: name,
575
+ onChange: (e) => setName(e.target.value),
576
+ placeholder: "My laptop",
577
+ autoComplete: "off",
578
+ "aria-invalid": errors.name ? true : void 0,
579
+ className: "w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
580
+ }
581
+ ),
582
+ errors.name && /* @__PURE__ */ jsx3("p", { className: "text-xs text-destructive", children: errors.name })
583
+ ] }),
584
+ /* @__PURE__ */ jsxs3("div", { className: "space-y-1.5", children: [
585
+ /* @__PURE__ */ jsx3(
586
+ "label",
587
+ {
588
+ htmlFor: KEY_INPUT_ID,
589
+ className: "block text-xs font-medium uppercase tracking-[0.06em] text-muted-foreground",
590
+ children: "Public key"
591
+ }
592
+ ),
593
+ /* @__PURE__ */ jsx3(
594
+ "textarea",
595
+ {
596
+ id: KEY_INPUT_ID,
597
+ name: "public-key",
598
+ value: publicKey,
599
+ onChange: (e) => setPublicKey(e.target.value),
600
+ placeholder: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...",
601
+ autoComplete: "off",
602
+ spellCheck: false,
603
+ "aria-invalid": errors.publicKey ? true : void 0,
604
+ className: "min-h-24 w-full resize-y rounded-md border border-border bg-card px-3 py-2 font-mono text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
605
+ }
606
+ ),
607
+ errors.publicKey && /* @__PURE__ */ jsx3("p", { className: "text-xs text-destructive", children: errors.publicKey })
608
+ ] }),
609
+ submitError && /* @__PURE__ */ jsx3("p", { role: "alert", className: "text-sm text-destructive", children: submitError }),
610
+ /* @__PURE__ */ jsx3("button", { type: "submit", className: "hidden", tabIndex: -1, "aria-hidden": "true", children: "Submit" })
611
+ ] }),
612
+ /* @__PURE__ */ jsxs3(DialogFooter, { children: [
613
+ /* @__PURE__ */ jsx3(
614
+ "button",
615
+ {
616
+ type: "button",
617
+ onClick: () => onOpenChange(false),
618
+ disabled: isSaving,
619
+ className: "rounded-md border border-border bg-card px-4 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors disabled:opacity-50",
620
+ children: "Cancel"
621
+ }
622
+ ),
623
+ /* @__PURE__ */ jsxs3(
624
+ "button",
625
+ {
626
+ type: "button",
627
+ onClick: handleSave,
628
+ disabled: isSaving,
629
+ className: "inline-flex items-center gap-2 rounded-md 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]",
630
+ children: [
631
+ isSaving && /* @__PURE__ */ jsx3(Loader2, { className: "h-4 w-4 animate-spin" }),
632
+ isSaving ? "Saving..." : "Add key"
633
+ ]
634
+ }
635
+ )
636
+ ] })
637
+ ] }) });
638
+ }
639
+
640
+ // src/pages/provisioning-wizard.tsx
641
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
478
642
  var VALID_DRIVERS = /* @__PURE__ */ new Set([
479
643
  "docker",
480
644
  "firecracker",
@@ -527,7 +691,7 @@ function resolveEnvironment(env) {
527
691
  id: env.id,
528
692
  name: templateName,
529
693
  description: env.description ?? "User template from snapshot",
530
- icon: /* @__PURE__ */ jsx3("span", { className: "text-[var(--surface-success-text)] text-2xl font-bold", children: "T" }),
694
+ icon: /* @__PURE__ */ jsx4("span", { className: "text-[var(--surface-success-text)] text-2xl font-bold", children: "T" }),
531
695
  color: "green"
532
696
  };
533
697
  }
@@ -540,7 +704,7 @@ function resolveEnvironment(env) {
540
704
  id: env.id,
541
705
  name,
542
706
  description: env.description ?? `${name} development environment`,
543
- icon: /* @__PURE__ */ jsx3("span", { className: `${textClass} text-2xl font-bold`, children: abbr }),
707
+ icon: /* @__PURE__ */ jsx4("span", { className: `${textClass} text-2xl font-bold`, children: abbr }),
544
708
  color
545
709
  };
546
710
  }
@@ -549,21 +713,21 @@ var defaultEnvironments = [
549
713
  id: "node",
550
714
  name: "Node.js",
551
715
  description: "v20.x LTS with optimized runtime for asynchronous event-driven agents.",
552
- icon: /* @__PURE__ */ jsx3("span", { className: "text-[var(--code-success)] text-2xl font-bold", children: "N" }),
716
+ icon: /* @__PURE__ */ jsx4("span", { className: "text-[var(--code-success)] text-2xl font-bold", children: "N" }),
553
717
  color: "green"
554
718
  },
555
719
  {
556
720
  id: "python",
557
721
  name: "Python",
558
722
  description: "v3.11 pre-installed with PyTorch and common data science libraries.",
559
- icon: /* @__PURE__ */ jsx3("span", { className: "text-sky-400 text-2xl font-bold", children: "Py" }),
723
+ icon: /* @__PURE__ */ jsx4("span", { className: "text-sky-400 text-2xl font-bold", children: "Py" }),
560
724
  color: "blue"
561
725
  },
562
726
  {
563
727
  id: "ubuntu",
564
728
  name: "Ubuntu",
565
729
  description: "Full 22.04 LTS terminal access for custom containerized workloads.",
566
- icon: /* @__PURE__ */ jsx3("span", { className: "text-orange-400 text-2xl font-bold", children: "U" }),
730
+ icon: /* @__PURE__ */ jsx4("span", { className: "text-orange-400 text-2xl font-bold", children: "U" }),
567
731
  color: "orange"
568
732
  }
569
733
  ];
@@ -634,47 +798,79 @@ function computeHourlyCost(cpu, ram, storage, rates) {
634
798
  }
635
799
  function SshAccessStep({ config }) {
636
800
  const keys = config.keys ?? [];
801
+ const canAddKey = typeof config.onCreateKey === "function";
802
+ const [isAddKeyOpen, setIsAddKeyOpen] = React3.useState(false);
637
803
  const inlineKeyCount = config.inlinePublicKeys.split(/\r?\n/).map((key) => key.trim()).filter(Boolean).length;
638
804
  const totalKeyCount = config.selectedKeyIds.length + inlineKeyCount;
639
- return /* @__PURE__ */ jsxs3("div", { className: "space-y-4", children: [
640
- /* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between gap-4", children: [
641
- /* @__PURE__ */ jsxs3("div", { children: [
642
- /* @__PURE__ */ jsx3("p", { className: "font-medium text-foreground text-sm", children: "SSH Access" }),
643
- /* @__PURE__ */ jsx3("p", { className: "mt-1 text-muted-foreground text-xs", children: "Select stored keys or paste public keys for authorized_keys." })
805
+ return /* @__PURE__ */ jsxs4("div", { className: "space-y-4", children: [
806
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-start justify-between gap-4", children: [
807
+ /* @__PURE__ */ jsxs4("div", { children: [
808
+ /* @__PURE__ */ jsx4("p", { className: "font-medium text-foreground text-sm", children: "SSH Access" }),
809
+ /* @__PURE__ */ jsx4("p", { className: "mt-1 text-muted-foreground text-xs", children: "Select stored keys or paste public keys for authorized_keys." })
644
810
  ] }),
645
- /* @__PURE__ */ jsxs3(Badge, { variant: "outline", children: [
646
- totalKeyCount,
647
- " key",
648
- totalKeyCount === 1 ? "" : "s"
811
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
812
+ canAddKey && /* @__PURE__ */ jsxs4(
813
+ Button,
814
+ {
815
+ type: "button",
816
+ variant: "outline",
817
+ size: "sm",
818
+ onClick: () => setIsAddKeyOpen(true),
819
+ children: [
820
+ /* @__PURE__ */ jsx4(Plus, { className: "h-3.5 w-3.5" }),
821
+ "Add SSH key"
822
+ ]
823
+ }
824
+ ),
825
+ /* @__PURE__ */ jsxs4(Badge, { variant: "outline", children: [
826
+ totalKeyCount,
827
+ " key",
828
+ totalKeyCount === 1 ? "" : "s"
829
+ ] })
649
830
  ] })
650
831
  ] }),
651
- keys.length > 0 && /* @__PURE__ */ jsx3("div", { className: "grid gap-2 sm:grid-cols-2", children: keys.map((key) => {
832
+ keys.length > 0 && /* @__PURE__ */ jsx4("div", { className: "grid gap-2 sm:grid-cols-2", children: keys.map((key) => {
652
833
  const selected = config.selectedKeyIds.includes(key.id);
653
- return /* @__PURE__ */ jsx3(
654
- Button,
834
+ return /* @__PURE__ */ jsx4(
835
+ "button",
655
836
  {
656
837
  type: "button",
657
- variant: selected ? "sandbox" : "outline",
658
- className: "h-auto justify-start p-3 text-left",
659
838
  "aria-pressed": selected,
660
839
  onClick: () => {
661
840
  config.onSelectedKeyIdsChange(
662
841
  selected ? config.selectedKeyIds.filter((id) => id !== key.id) : [...config.selectedKeyIds, key.id]
663
842
  );
664
843
  },
665
- children: /* @__PURE__ */ jsxs3("span", { className: "min-w-0", children: [
666
- /* @__PURE__ */ jsx3("span", { className: "block font-medium text-foreground", children: key.name }),
667
- /* @__PURE__ */ jsxs3("span", { className: "block truncate font-mono text-muted-foreground text-xs", children: [
668
- key.keyType,
669
- " \xB7 ",
670
- key.fingerprint
671
- ] })
844
+ className: cn(
845
+ "group p-3 text-left rounded-lg border transition-colors duration-200",
846
+ selected ? "bg-primary/5 border-primary ring-1 ring-primary/20" : "bg-card border-border hover:border-primary/30 active:scale-[0.99]"
847
+ ),
848
+ children: /* @__PURE__ */ jsxs4("div", { className: "flex items-start justify-between gap-2", children: [
849
+ /* @__PURE__ */ jsxs4("span", { className: "min-w-0", children: [
850
+ /* @__PURE__ */ jsx4("span", { className: "block font-medium text-sm text-foreground", children: key.name }),
851
+ /* @__PURE__ */ jsxs4("span", { className: "block truncate font-mono text-muted-foreground text-xs", children: [
852
+ key.keyType,
853
+ " \xB7 ",
854
+ key.fingerprint
855
+ ] })
856
+ ] }),
857
+ /* @__PURE__ */ jsx4(
858
+ "span",
859
+ {
860
+ "aria-hidden": "true",
861
+ className: cn(
862
+ "flex h-4 w-4 shrink-0 items-center justify-center rounded-[4px] border-2 transition-colors duration-200",
863
+ selected ? "border-primary bg-primary" : "border-border group-hover:border-primary/40"
864
+ ),
865
+ children: selected && /* @__PURE__ */ jsx4(Check, { className: "h-2.5 w-2.5 text-primary-foreground" })
866
+ }
867
+ )
672
868
  ] })
673
869
  },
674
870
  key.id
675
871
  );
676
872
  }) }),
677
- /* @__PURE__ */ jsx3(
873
+ /* @__PURE__ */ jsx4(
678
874
  Textarea,
679
875
  {
680
876
  className: "min-h-24 font-mono text-xs",
@@ -682,6 +878,18 @@ function SshAccessStep({ config }) {
682
878
  value: config.inlinePublicKeys,
683
879
  onChange: (event) => config.onInlinePublicKeysChange(event.target.value)
684
880
  }
881
+ ),
882
+ canAddKey && /* @__PURE__ */ jsx4(
883
+ AddSshKeyDialog,
884
+ {
885
+ open: isAddKeyOpen,
886
+ onOpenChange: setIsAddKeyOpen,
887
+ onCreateKey: config.onCreateKey,
888
+ onRefreshKeys: config.onRefreshKeys,
889
+ onCreatedKeyId: (id) => config.onSelectedKeyIdsChange(
890
+ config.selectedKeyIds.includes(id) ? config.selectedKeyIds : [...config.selectedKeyIds, id]
891
+ )
892
+ }
685
893
  )
686
894
  ] });
687
895
  }
@@ -691,10 +899,8 @@ function ProvisioningWizard({
691
899
  onSubmit,
692
900
  onBack,
693
901
  className,
694
- variant = "flat",
695
902
  defaultEnvironment,
696
903
  defaultConfig,
697
- skipToReview,
698
904
  onLoadStartupScripts,
699
905
  resourceLimits,
700
906
  sshAccess,
@@ -717,17 +923,17 @@ function ProvisioningWizard({
717
923
  const ramStep = alignSliderStep(RAM_MIN, ramMax, RAM_STEP);
718
924
  const storageStep = alignSliderStep(STORAGE_MIN, storageMax, STORAGE_STEP);
719
925
  const dc = defaultConfig;
720
- const [envList, setEnvList] = React2.useState(() => {
926
+ const [envList, setEnvList] = React3.useState(() => {
721
927
  if (environmentsProp) return environmentsProp;
722
928
  if (onLoadEnvironments) return [];
723
929
  return defaultEnvironments;
724
930
  });
725
- const [isLoadingEnvironments, setIsLoadingEnvironments] = React2.useState(
931
+ const [isLoadingEnvironments, setIsLoadingEnvironments] = React3.useState(
726
932
  () => !environmentsProp && !!onLoadEnvironments
727
933
  );
728
- const onLoadEnvironmentsRef = React2.useRef(onLoadEnvironments);
934
+ const onLoadEnvironmentsRef = React3.useRef(onLoadEnvironments);
729
935
  onLoadEnvironmentsRef.current = onLoadEnvironments;
730
- React2.useEffect(() => {
936
+ React3.useEffect(() => {
731
937
  let cancelled = false;
732
938
  if (onLoadEnvironmentsRef.current) {
733
939
  setIsLoadingEnvironments(true);
@@ -753,10 +959,10 @@ function ProvisioningWizard({
753
959
  }, [environmentsProp]);
754
960
  const environments = envList;
755
961
  const effectiveDefault = dc?.environment ?? defaultEnvironment;
756
- const [selectedEnv, setSelectedEnv] = React2.useState(
962
+ const [selectedEnv, setSelectedEnv] = React3.useState(
757
963
  effectiveDefault ?? environments[0]?.id ?? ""
758
964
  );
759
- React2.useEffect(() => {
965
+ React3.useEffect(() => {
760
966
  if (envList.length === 0) return;
761
967
  if (effectiveDefault && envList.some((e) => e.id === effectiveDefault)) {
762
968
  setSelectedEnv(effectiveDefault);
@@ -767,38 +973,38 @@ function ProvisioningWizard({
767
973
  return envList[0]?.id ?? "";
768
974
  });
769
975
  }, [envList, effectiveDefault]);
770
- const [cpuCores, setCpuCores] = React2.useState(
976
+ const [cpuCores, setCpuCores] = React3.useState(
771
977
  snapSliderValue(dc?.cpuCores ?? 4, CPU_MIN, cpuMax, cpuStep)
772
978
  );
773
- const [ramGB, setRamGB] = React2.useState(
979
+ const [ramGB, setRamGB] = React3.useState(
774
980
  snapSliderValue(dc?.ramGB ?? 16, RAM_MIN, ramMax, ramStep)
775
981
  );
776
- const [storageGB, setStorageGB] = React2.useState(
982
+ const [storageGB, setStorageGB] = React3.useState(
777
983
  snapSliderValue(dc?.storageGB ?? 128, STORAGE_MIN, storageMax, storageStep)
778
984
  );
779
- React2.useEffect(() => {
985
+ React3.useEffect(() => {
780
986
  setCpuCores((prev) => snapSliderValue(prev, CPU_MIN, cpuMax, cpuStep));
781
987
  setRamGB((prev) => snapSliderValue(prev, RAM_MIN, ramMax, ramStep));
782
988
  setStorageGB(
783
989
  (prev) => snapSliderValue(prev, STORAGE_MIN, storageMax, storageStep)
784
990
  );
785
991
  }, [cpuMax, ramMax, storageMax, cpuStep, ramStep, storageStep]);
786
- const [name, setName] = React2.useState(dc?.name ?? "");
787
- const [gitUrl, setGitUrl] = React2.useState(dc?.gitUrl ?? "");
788
- const [envVars, setEnvVars] = React2.useState(dc?.envVars ?? [{ key: "", value: "" }]);
789
- const [driver, setDriver] = React2.useState(dc?.driver ?? "docker");
790
- const [bare, setBare] = React2.useState(dc?.bare ?? false);
791
- const [startupScriptIds, setStartupScriptIds] = React2.useState(
992
+ const [name, setName] = React3.useState(dc?.name ?? "");
993
+ const [gitUrl, setGitUrl] = React3.useState(dc?.gitUrl ?? "");
994
+ const [envVars, setEnvVars] = React3.useState(dc?.envVars ?? [{ key: "", value: "" }]);
995
+ const [driver, setDriver] = React3.useState(dc?.driver ?? "docker");
996
+ const [bare, setBare] = React3.useState(dc?.bare ?? false);
997
+ const [startupScriptIds, setStartupScriptIds] = React3.useState(
792
998
  dc?.startupScriptIds ?? []
793
999
  );
794
- const [availableScripts, setAvailableScripts] = React2.useState([]);
795
- const [activePreset, setActivePreset] = React2.useState(null);
796
- const [pricingView, setPricingView] = React2.useState("hourly");
797
- const [showAdvanced, setShowAdvanced] = React2.useState(false);
798
- const [loadError, setLoadError] = React2.useState(null);
799
- const onLoadStartupScriptsRef = React2.useRef(onLoadStartupScripts);
1000
+ const [availableScripts, setAvailableScripts] = React3.useState([]);
1001
+ const [activePreset, setActivePreset] = React3.useState(null);
1002
+ const [pricingView, setPricingView] = React3.useState("hourly");
1003
+ const [showAdvanced, setShowAdvanced] = React3.useState(false);
1004
+ const [loadError, setLoadError] = React3.useState(null);
1005
+ const onLoadStartupScriptsRef = React3.useRef(onLoadStartupScripts);
800
1006
  onLoadStartupScriptsRef.current = onLoadStartupScripts;
801
- React2.useEffect(() => {
1007
+ React3.useEffect(() => {
802
1008
  let cancelled = false;
803
1009
  if (onLoadStartupScriptsRef.current) {
804
1010
  onLoadStartupScriptsRef.current().then((scripts) => {
@@ -814,14 +1020,8 @@ function ProvisioningWizard({
814
1020
  cancelled = true;
815
1021
  };
816
1022
  }, []);
817
- const isMultistep = variant === "multistep";
818
- const stepLabels = sshAccess ? ["Environment", "Resources", "Access"] : ["Environment", "Resources"];
819
- const finalStep = stepLabels.length;
820
- const [currentStep, setCurrentStep] = React2.useState(
821
- skipToReview && dc && isMultistep ? finalStep : 1
822
- );
823
- const [isDeploying, setIsDeploying] = React2.useState(false);
824
- const [deployError, setDeployError] = React2.useState(null);
1023
+ const [isDeploying, setIsDeploying] = React3.useState(false);
1024
+ const [deployError, setDeployError] = React3.useState(null);
825
1025
  const handleDeploy = async () => {
826
1026
  if (!onSubmit) return;
827
1027
  setIsDeploying(true);
@@ -872,9 +1072,9 @@ function ProvisioningWizard({
872
1072
  unlockLabel: unlockLabel ?? "Pro"
873
1073
  };
874
1074
  });
875
- const didInitPresetFromDcRef = React2.useRef(false);
876
- const lastLimitsRef = React2.useRef(null);
877
- React2.useEffect(() => {
1075
+ const didInitPresetFromDcRef = React3.useRef(false);
1076
+ const lastLimitsRef = React3.useRef(null);
1077
+ React3.useEffect(() => {
878
1078
  const limitsUnchanged = lastLimitsRef.current !== null && lastLimitsRef.current.cpu === cpuMax && lastLimitsRef.current.ram === ramMax && lastLimitsRef.current.storage === storageMax;
879
1079
  if (limitsUnchanged) return;
880
1080
  lastLimitsRef.current = { cpu: cpuMax, ram: ramMax, storage: storageMax };
@@ -912,9 +1112,9 @@ function ProvisioningWizard({
912
1112
  const pricingSuffix = pricingView === "hourly" ? "/ hour" : "/ sec";
913
1113
  const rateSuffix = pricingView === "hourly" ? "/h" : "/s";
914
1114
  const fmtRate = (v) => pricingView === "hourly" ? v.toFixed(2) : formatPerSecondValue(v);
915
- return /* @__PURE__ */ jsxs3("div", { className: cn("max-w-6xl mx-auto flex flex-col", className), children: [
916
- /* @__PURE__ */ jsxs3("div", { className: "mb-4 flex items-center gap-3 shrink-0", children: [
917
- onBack && /* @__PURE__ */ jsx3(
1115
+ return /* @__PURE__ */ jsxs4("div", { className: cn("max-w-6xl mx-auto flex flex-col", className), children: [
1116
+ /* @__PURE__ */ jsxs4("div", { className: "mb-4 flex items-center gap-3 shrink-0", children: [
1117
+ onBack && /* @__PURE__ */ jsx4(
918
1118
  Button,
919
1119
  {
920
1120
  type: "button",
@@ -922,109 +1122,43 @@ function ProvisioningWizard({
922
1122
  size: "icon",
923
1123
  onClick: onBack,
924
1124
  className: "h-9 w-9 shrink-0",
925
- children: /* @__PURE__ */ jsx3(ArrowLeft, { className: "h-4 w-4" })
1125
+ children: /* @__PURE__ */ jsx4(ArrowLeft, { className: "h-4 w-4" })
926
1126
  }
927
1127
  ),
928
- /* @__PURE__ */ jsxs3("div", { children: [
929
- /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: "Sandbox Provisioning" }),
930
- /* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-sm", children: "Select your stack, allocate resources, and deploy." })
1128
+ /* @__PURE__ */ jsxs4("div", { children: [
1129
+ /* @__PURE__ */ jsx4("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: "Sandbox Provisioning" }),
1130
+ /* @__PURE__ */ jsx4("p", { className: "text-muted-foreground text-sm", children: "Select your stack, allocate resources, and deploy." })
931
1131
  ] })
932
1132
  ] }),
933
- /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-12 gap-5 flex-1 min-h-0", children: [
934
- /* @__PURE__ */ jsxs3("div", { className: "col-span-12 xl:col-span-8 flex flex-col min-h-0", children: [
935
- isMultistep && /* @__PURE__ */ jsx3("div", { className: "flex items-center gap-2 mb-4 rounded-lg border border-border bg-card px-4 py-2 shadow-sm mx-auto max-w-2xl justify-between shrink-0", children: stepLabels.map((label, index) => {
936
- const s = index + 1;
937
- return /* @__PURE__ */ jsxs3("div", { className: "flex items-center", children: [
938
- /* @__PURE__ */ jsx3(
939
- "div",
940
- {
941
- className: cn(
942
- "h-6 w-6 rounded-full flex items-center justify-center font-semibold text-xs shrink-0 transition-colors duration-200",
943
- currentStep >= s ? "bg-primary text-primary-foreground" : "bg-muted border border-border text-muted-foreground"
944
- ),
945
- children: currentStep > s ? /* @__PURE__ */ jsx3(Check, { className: "h-3 w-3" }) : s
946
- }
947
- ),
948
- /* @__PURE__ */ jsx3(
949
- "span",
950
- {
951
- className: cn(
952
- "ml-2 font-medium text-sm hidden sm:inline transition-colors duration-200",
953
- currentStep === s ? "text-foreground" : currentStep > s ? "text-primary" : "text-muted-foreground"
954
- ),
955
- children: label
956
- }
957
- ),
958
- s < finalStep && /* @__PURE__ */ jsx3(
959
- "div",
960
- {
961
- className: cn(
962
- "w-4 sm:w-8 h-px mx-2 sm:mx-3 transition-colors duration-300",
963
- currentStep > s ? "bg-primary" : "bg-border"
964
- )
965
- }
966
- )
967
- ] }, s);
968
- }) }),
969
- dc && isMultistep && /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between rounded-lg border border-border bg-card px-4 py-2.5 shadow-sm shrink-0 mb-4", children: [
970
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-sm", children: [
971
- /* @__PURE__ */ jsx3(Info, { className: "h-4 w-4 text-primary shrink-0" }),
972
- /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: "Pre-configured from template." })
973
- ] }),
974
- /* @__PURE__ */ jsx3(
975
- Button,
976
- {
977
- type: "button",
978
- variant: "link",
979
- onClick: () => {
980
- setCurrentStep(1);
981
- setSelectedEnv(environments[0]?.id ?? "");
982
- setCpuCores(snapSliderValue(4, CPU_MIN, cpuMax, cpuStep));
983
- setRamGB(snapSliderValue(16, RAM_MIN, ramMax, ramStep));
984
- setStorageGB(
985
- snapSliderValue(128, STORAGE_MIN, storageMax, storageStep)
986
- );
987
- setName("");
988
- setGitUrl("");
989
- setEnvVars([{ key: "", value: "" }]);
990
- setDriver("docker");
991
- setBare(false);
992
- setStartupScriptIds([]);
993
- setActivePreset(null);
994
- setPricingView("hourly");
995
- },
996
- className: "h-auto p-0 text-xs",
997
- children: "Start from scratch"
998
- }
999
- )
1000
- ] }),
1001
- loadError && /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-3 flex items-center gap-2 shrink-0 mb-4", children: [
1002
- /* @__PURE__ */ jsx3(Info, { className: "h-4 w-4 text-destructive shrink-0" }),
1003
- /* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-destructive", children: loadError })
1133
+ /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-12 gap-5 flex-1 min-h-0", children: [
1134
+ /* @__PURE__ */ jsxs4("div", { className: "col-span-12 xl:col-span-8 flex flex-col min-h-0", children: [
1135
+ loadError && /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-3 flex items-center gap-2 shrink-0 mb-4", children: [
1136
+ /* @__PURE__ */ jsx4(Info, { className: "h-4 w-4 text-destructive shrink-0" }),
1137
+ /* @__PURE__ */ jsx4("p", { className: "text-sm font-medium text-destructive", children: loadError })
1004
1138
  ] }),
1005
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 overflow-y-auto min-h-0 space-y-4", children: [
1006
- (!isMultistep || currentStep === 1) && /* @__PURE__ */ jsx3(React2.Fragment, { children: /* @__PURE__ */ jsxs3("section", { className: SECTION_CARD_CLASS, children: [
1007
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 mb-4", children: [
1008
- /* @__PURE__ */ jsx3(Layers, { className: "h-4 w-4 text-primary shrink-0" }),
1009
- /* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Environment Selection" })
1139
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 overflow-y-auto min-h-0 space-y-4", children: [
1140
+ /* @__PURE__ */ jsxs4("section", { className: SECTION_CARD_CLASS, children: [
1141
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 mb-4", children: [
1142
+ /* @__PURE__ */ jsx4(Layers, { className: "h-4 w-4 text-primary shrink-0" }),
1143
+ /* @__PURE__ */ jsx4("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Environment Selection" })
1010
1144
  ] }),
1011
- /* @__PURE__ */ jsx3("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: isLoadingEnvironments && environments.length === 0 ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs3(
1145
+ /* @__PURE__ */ jsx4("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-3", children: isLoadingEnvironments && environments.length === 0 ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs4(
1012
1146
  "div",
1013
1147
  {
1014
1148
  className: "p-3.5 rounded-lg border border-border bg-card/50 animate-pulse",
1015
1149
  "aria-hidden": "true",
1016
1150
  children: [
1017
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-start mb-2.5", children: [
1018
- /* @__PURE__ */ jsx3("div", { className: "w-10 h-10 rounded-full bg-muted/60 border border-border" }),
1019
- /* @__PURE__ */ jsx3("div", { className: "w-4 h-4 rounded-full border-2 border-border" })
1151
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-start mb-2.5", children: [
1152
+ /* @__PURE__ */ jsx4("div", { className: "w-10 h-10 rounded-full bg-muted/60 border border-border" }),
1153
+ /* @__PURE__ */ jsx4("div", { className: "w-4 h-4 rounded-full border-2 border-border" })
1020
1154
  ] }),
1021
- /* @__PURE__ */ jsx3("div", { className: "h-3 w-1/3 rounded bg-muted/60 mb-2" }),
1022
- /* @__PURE__ */ jsx3("div", { className: "h-2.5 w-5/6 rounded bg-muted/50 mb-1.5" }),
1023
- /* @__PURE__ */ jsx3("div", { className: "h-2.5 w-2/3 rounded bg-muted/50" })
1155
+ /* @__PURE__ */ jsx4("div", { className: "h-3 w-1/3 rounded bg-muted/60 mb-2" }),
1156
+ /* @__PURE__ */ jsx4("div", { className: "h-2.5 w-5/6 rounded bg-muted/50 mb-1.5" }),
1157
+ /* @__PURE__ */ jsx4("div", { className: "h-2.5 w-2/3 rounded bg-muted/50" })
1024
1158
  ]
1025
1159
  },
1026
1160
  `env-skeleton-${i}`
1027
- )) : environments.map((env) => /* @__PURE__ */ jsxs3(
1161
+ )) : environments.map((env) => /* @__PURE__ */ jsxs4(
1028
1162
  "button",
1029
1163
  {
1030
1164
  type: "button",
@@ -1034,36 +1168,36 @@ function ProvisioningWizard({
1034
1168
  selectedEnv === env.id ? "bg-primary/5 border-primary ring-1 ring-primary/20" : "bg-card border-border hover:border-primary/30 active:scale-[0.99]"
1035
1169
  ),
1036
1170
  children: [
1037
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-start mb-2.5", children: [
1038
- /* @__PURE__ */ jsx3("div", { className: "w-10 h-10 rounded-full flex items-center justify-center bg-muted/50 border border-border", children: env.icon }),
1039
- /* @__PURE__ */ jsx3(
1171
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-start mb-2.5", children: [
1172
+ /* @__PURE__ */ jsx4("div", { className: "w-10 h-10 rounded-full flex items-center justify-center bg-muted/50 border border-border", children: env.icon }),
1173
+ /* @__PURE__ */ jsx4(
1040
1174
  "div",
1041
1175
  {
1042
1176
  className: cn(
1043
1177
  "w-4 h-4 rounded-full border-2 flex items-center justify-center transition-colors duration-200",
1044
1178
  selectedEnv === env.id ? "border-primary bg-primary" : "border-border group-hover:border-primary/40"
1045
1179
  ),
1046
- children: selectedEnv === env.id && /* @__PURE__ */ jsx3(Check, { className: "h-2.5 w-2.5 text-primary-foreground" })
1180
+ children: selectedEnv === env.id && /* @__PURE__ */ jsx4(Check, { className: "h-2.5 w-2.5 text-primary-foreground" })
1047
1181
  }
1048
1182
  )
1049
1183
  ] }),
1050
- /* @__PURE__ */ jsx3("h3", { className: "font-semibold text-sm mb-0.5 text-foreground", children: env.name }),
1051
- /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground leading-relaxed", children: env.description })
1184
+ /* @__PURE__ */ jsx4("h3", { className: "font-semibold text-sm mb-0.5 text-foreground", children: env.name }),
1185
+ /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground leading-relaxed", children: env.description })
1052
1186
  ]
1053
1187
  },
1054
1188
  env.id
1055
1189
  )) })
1056
- ] }) }),
1057
- (!isMultistep || currentStep === 2) && /* @__PURE__ */ jsx3(React2.Fragment, { children: /* @__PURE__ */ jsxs3("section", { className: SECTION_CARD_CLASS, children: [
1058
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 mb-4", children: [
1059
- /* @__PURE__ */ jsx3(Cpu, { className: "h-4 w-4 text-primary shrink-0" }),
1060
- /* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Resource Allocation" })
1190
+ ] }),
1191
+ /* @__PURE__ */ jsxs4("section", { className: SECTION_CARD_CLASS, children: [
1192
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 mb-4", children: [
1193
+ /* @__PURE__ */ jsx4(Cpu, { className: "h-4 w-4 text-primary shrink-0" }),
1194
+ /* @__PURE__ */ jsx4("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Resource Allocation" })
1061
1195
  ] }),
1062
- /* @__PURE__ */ jsxs3("div", { className: "mb-4", children: [
1063
- /* @__PURE__ */ jsx3("label", { className: cn(FIELD_LABEL_CLASS, "mb-2"), children: "Compute Presets" }),
1064
- /* @__PURE__ */ jsx3("div", { className: "grid grid-cols-3 gap-2", children: presets.map((p) => {
1196
+ /* @__PURE__ */ jsxs4("div", { className: "mb-4", children: [
1197
+ /* @__PURE__ */ jsx4("label", { className: cn(FIELD_LABEL_CLASS, "mb-2"), children: "Compute Presets" }),
1198
+ /* @__PURE__ */ jsx4("div", { className: "grid grid-cols-3 gap-2", children: presets.map((p) => {
1065
1199
  const active = activePreset === p.name && !p.locked;
1066
- return /* @__PURE__ */ jsxs3(
1200
+ return /* @__PURE__ */ jsxs4(
1067
1201
  "button",
1068
1202
  {
1069
1203
  type: "button",
@@ -1074,8 +1208,8 @@ function ProvisioningWizard({
1074
1208
  active ? "bg-primary/5 border-primary ring-1 ring-primary/20" : p.locked ? "bg-muted/30 border-border opacity-60 cursor-not-allowed" : "bg-card border-border hover:border-primary/30 active:scale-[0.99]"
1075
1209
  ),
1076
1210
  children: [
1077
- p.locked && /* @__PURE__ */ jsx3("div", { className: "absolute -top-1.5 -right-1.5 bg-primary text-primary-foreground text-[9px] font-semibold px-1.5 py-0.5 rounded-full uppercase tracking-wider", children: p.unlockLabel }),
1078
- /* @__PURE__ */ jsx3(
1211
+ p.locked && /* @__PURE__ */ jsx4("div", { className: "absolute -top-1.5 -right-1.5 bg-primary text-primary-foreground text-[9px] font-semibold px-1.5 py-0.5 rounded-full uppercase tracking-wider", children: p.unlockLabel }),
1212
+ /* @__PURE__ */ jsx4(
1079
1213
  "div",
1080
1214
  {
1081
1215
  className: cn(
@@ -1085,7 +1219,7 @@ function ProvisioningWizard({
1085
1219
  children: p.name
1086
1220
  }
1087
1221
  ),
1088
- /* @__PURE__ */ jsxs3("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: [
1222
+ /* @__PURE__ */ jsxs4("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: [
1089
1223
  p.cpu,
1090
1224
  " vCPU",
1091
1225
  p.cpu === 1 ? "" : "s",
@@ -1102,7 +1236,7 @@ function ProvisioningWizard({
1102
1236
  );
1103
1237
  }) })
1104
1238
  ] }),
1105
- /* @__PURE__ */ jsx3("div", { className: "space-y-4", children: [
1239
+ /* @__PURE__ */ jsx4("div", { className: "space-y-4", children: [
1106
1240
  {
1107
1241
  label: "Compute Cores (CPU)",
1108
1242
  value: cpuCores,
@@ -1133,12 +1267,12 @@ function ProvisioningWizard({
1133
1267
  ].map(
1134
1268
  ({ label, value, setter, min, max, step: s, unit }) => {
1135
1269
  const displayUnit = unit === "vCPU" ? `${value} vCPU${value === 1 ? "" : "s"}` : `${value}${unit}`;
1136
- return /* @__PURE__ */ jsxs3("div", { children: [
1137
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-end pb-1 mb-1.5", children: [
1138
- /* @__PURE__ */ jsx3("label", { className: FIELD_LABEL_CLASS, children: label }),
1139
- /* @__PURE__ */ jsx3("span", { className: "text-sm font-semibold text-foreground tabular-nums", children: displayUnit })
1270
+ return /* @__PURE__ */ jsxs4("div", { children: [
1271
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-end pb-1 mb-1.5", children: [
1272
+ /* @__PURE__ */ jsx4("label", { className: FIELD_LABEL_CLASS, children: label }),
1273
+ /* @__PURE__ */ jsx4("span", { className: "text-sm font-semibold text-foreground tabular-nums", children: displayUnit })
1140
1274
  ] }),
1141
- /* @__PURE__ */ jsx3(
1275
+ /* @__PURE__ */ jsx4(
1142
1276
  "input",
1143
1277
  {
1144
1278
  type: "range",
@@ -1153,12 +1287,12 @@ function ProvisioningWizard({
1153
1287
  className: "w-full h-1.5 rounded-full appearance-none cursor-pointer accent-primary [&::-webkit-slider-runnable-track]:bg-border [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:h-1.5 [&::-moz-range-track]:bg-border [&::-moz-range-track]:rounded-full [&::-moz-range-track]:h-1.5 [&::-webkit-slider-thumb]:bg-primary [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:shadow-sm [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-foreground"
1154
1288
  }
1155
1289
  ),
1156
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground/60 mt-1", children: [
1157
- /* @__PURE__ */ jsxs3("span", { children: [
1290
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground/60 mt-1", children: [
1291
+ /* @__PURE__ */ jsxs4("span", { children: [
1158
1292
  min,
1159
1293
  unit === "vCPU" ? min === 1 ? " vCPU" : " vCPUs" : unit
1160
1294
  ] }),
1161
- /* @__PURE__ */ jsxs3("span", { children: [
1295
+ /* @__PURE__ */ jsxs4("span", { children: [
1162
1296
  max,
1163
1297
  unit === "vCPU" ? max === 1 ? " vCPU" : " vCPUs" : unit
1164
1298
  ] })
@@ -1166,25 +1300,25 @@ function ProvisioningWizard({
1166
1300
  ] }, label);
1167
1301
  }
1168
1302
  ) })
1169
- ] }) }),
1170
- (!isMultistep || currentStep === 2) && /* @__PURE__ */ jsx3(React2.Fragment, { children: /* @__PURE__ */ jsx3("section", { className: SECTION_CARD_CLASS, children: /* @__PURE__ */ jsxs3("div", { children: [
1171
- /* @__PURE__ */ jsxs3(
1303
+ ] }),
1304
+ /* @__PURE__ */ jsx4("section", { className: SECTION_CARD_CLASS, children: /* @__PURE__ */ jsxs4("div", { children: [
1305
+ /* @__PURE__ */ jsxs4(
1172
1306
  "button",
1173
1307
  {
1174
1308
  type: "button",
1175
1309
  onClick: () => setShowAdvanced(!showAdvanced),
1176
1310
  className: "flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors text-sm font-medium focus:outline-none",
1177
1311
  children: [
1178
- /* @__PURE__ */ jsx3(Settings, { className: "w-4 h-4" }),
1312
+ /* @__PURE__ */ jsx4(Settings, { className: "w-4 h-4" }),
1179
1313
  showAdvanced ? "Hide Advanced Options" : "Show Advanced Options"
1180
1314
  ]
1181
1315
  }
1182
1316
  ),
1183
- showAdvanced && /* @__PURE__ */ jsxs3("div", { className: "mt-4 space-y-4", children: [
1184
- /* @__PURE__ */ jsxs3("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1185
- /* @__PURE__ */ jsxs3("div", { children: [
1186
- /* @__PURE__ */ jsx3("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Workspace Name" }),
1187
- /* @__PURE__ */ jsx3(
1317
+ showAdvanced && /* @__PURE__ */ jsxs4("div", { className: "mt-4 space-y-4", children: [
1318
+ /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1319
+ /* @__PURE__ */ jsxs4("div", { children: [
1320
+ /* @__PURE__ */ jsx4("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Workspace Name" }),
1321
+ /* @__PURE__ */ jsx4(
1188
1322
  Input,
1189
1323
  {
1190
1324
  type: "text",
@@ -1196,9 +1330,9 @@ function ProvisioningWizard({
1196
1330
  }
1197
1331
  )
1198
1332
  ] }),
1199
- /* @__PURE__ */ jsxs3("div", { children: [
1200
- /* @__PURE__ */ jsx3("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Virtualization Driver" }),
1201
- /* @__PURE__ */ jsxs3(
1333
+ /* @__PURE__ */ jsxs4("div", { children: [
1334
+ /* @__PURE__ */ jsx4("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Virtualization Driver" }),
1335
+ /* @__PURE__ */ jsxs4(
1202
1336
  "select",
1203
1337
  {
1204
1338
  value: driver,
@@ -1210,8 +1344,8 @@ function ProvisioningWizard({
1210
1344
  },
1211
1345
  className: "w-full bg-card border border-border rounded-lg h-9 px-3 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent appearance-none",
1212
1346
  children: [
1213
- /* @__PURE__ */ jsx3("option", { value: "docker", className: "bg-gray-900", children: "Docker container (Default)" }),
1214
- /* @__PURE__ */ jsx3(
1347
+ /* @__PURE__ */ jsx4("option", { value: "docker", className: "bg-gray-900", children: "Docker container (Default)" }),
1348
+ /* @__PURE__ */ jsx4(
1215
1349
  "option",
1216
1350
  {
1217
1351
  value: "firecracker",
@@ -1219,15 +1353,15 @@ function ProvisioningWizard({
1219
1353
  children: "Firecracker microVM (Secure)"
1220
1354
  }
1221
1355
  ),
1222
- /* @__PURE__ */ jsx3("option", { value: "tangle", className: "bg-gray-900", children: "Tangle Distributed Node" })
1356
+ /* @__PURE__ */ jsx4("option", { value: "tangle", className: "bg-gray-900", children: "Tangle Distributed Node" })
1223
1357
  ]
1224
1358
  }
1225
1359
  )
1226
1360
  ] })
1227
1361
  ] }),
1228
- /* @__PURE__ */ jsxs3("div", { children: [
1229
- /* @__PURE__ */ jsx3("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Git Repository URL" }),
1230
- /* @__PURE__ */ jsx3(
1362
+ /* @__PURE__ */ jsxs4("div", { children: [
1363
+ /* @__PURE__ */ jsx4("label", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Git Repository URL" }),
1364
+ /* @__PURE__ */ jsx4(
1231
1365
  Input,
1232
1366
  {
1233
1367
  type: "text",
@@ -1238,10 +1372,10 @@ function ProvisioningWizard({
1238
1372
  }
1239
1373
  )
1240
1374
  ] }),
1241
- /* @__PURE__ */ jsxs3("div", { children: [
1242
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center mb-1.5", children: [
1243
- /* @__PURE__ */ jsx3("label", { className: FIELD_LABEL_CLASS, children: "Environment Variables" }),
1244
- /* @__PURE__ */ jsxs3(
1375
+ /* @__PURE__ */ jsxs4("div", { children: [
1376
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-center mb-1.5", children: [
1377
+ /* @__PURE__ */ jsx4("label", { className: FIELD_LABEL_CLASS, children: "Environment Variables" }),
1378
+ /* @__PURE__ */ jsxs4(
1245
1379
  "button",
1246
1380
  {
1247
1381
  type: "button",
@@ -1251,15 +1385,15 @@ function ProvisioningWizard({
1251
1385
  ]),
1252
1386
  className: "flex items-center gap-1 text-xs text-primary hover:text-primary/70 transition-colors font-medium",
1253
1387
  children: [
1254
- /* @__PURE__ */ jsx3(Plus, { className: "h-3 w-3" }),
1388
+ /* @__PURE__ */ jsx4(Plus, { className: "h-3 w-3" }),
1255
1389
  " Add Var"
1256
1390
  ]
1257
1391
  }
1258
1392
  )
1259
1393
  ] }),
1260
- /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
1261
- envVars.map((env, i) => /* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
1262
- /* @__PURE__ */ jsx3(
1394
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
1395
+ envVars.map((env, i) => /* @__PURE__ */ jsxs4("div", { className: "flex gap-2", children: [
1396
+ /* @__PURE__ */ jsx4(
1263
1397
  Input,
1264
1398
  {
1265
1399
  type: "text",
@@ -1273,7 +1407,7 @@ function ProvisioningWizard({
1273
1407
  placeholder: "API_KEY"
1274
1408
  }
1275
1409
  ),
1276
- /* @__PURE__ */ jsx3(
1410
+ /* @__PURE__ */ jsx4(
1277
1411
  Input,
1278
1412
  {
1279
1413
  type: "password",
@@ -1287,7 +1421,7 @@ function ProvisioningWizard({
1287
1421
  placeholder: "sk-xxxxxxxxxxx"
1288
1422
  }
1289
1423
  ),
1290
- /* @__PURE__ */ jsx3(
1424
+ /* @__PURE__ */ jsx4(
1291
1425
  Button,
1292
1426
  {
1293
1427
  type: "button",
@@ -1297,25 +1431,25 @@ function ProvisioningWizard({
1297
1431
  envVars.filter((_, idx) => idx !== i)
1298
1432
  ),
1299
1433
  className: "h-9 w-9 shrink-0 text-destructive hover:bg-destructive/10 hover:border-destructive/30",
1300
- children: /* @__PURE__ */ jsx3(Trash2, { className: "h-4 w-4" })
1434
+ children: /* @__PURE__ */ jsx4(Trash2, { className: "h-4 w-4" })
1301
1435
  }
1302
1436
  )
1303
1437
  ] }, i)),
1304
- envVars.length === 0 && /* @__PURE__ */ jsx3("div", { className: "text-center p-3 border border-dashed border-border rounded-lg text-muted-foreground/60 text-xs italic", children: "No environment variables set" })
1438
+ envVars.length === 0 && /* @__PURE__ */ jsx4("div", { className: "text-center p-3 border border-dashed border-border rounded-lg text-muted-foreground/60 text-xs italic", children: "No environment variables set" })
1305
1439
  ] })
1306
1440
  ] }),
1307
- availableScripts.length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
1308
- /* @__PURE__ */ jsx3("div", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Startup Scripts" }),
1309
- /* @__PURE__ */ jsx3("div", { className: "space-y-2", children: availableScripts.filter((s) => s.enabled).map((script) => {
1441
+ availableScripts.length > 0 && /* @__PURE__ */ jsxs4("div", { children: [
1442
+ /* @__PURE__ */ jsx4("div", { className: cn(FIELD_LABEL_CLASS, "mb-1.5"), children: "Startup Scripts" }),
1443
+ /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: availableScripts.filter((s) => s.enabled).map((script) => {
1310
1444
  const selected = startupScriptIds.includes(
1311
1445
  script.id
1312
1446
  );
1313
- return /* @__PURE__ */ jsxs3(
1447
+ return /* @__PURE__ */ jsxs4(
1314
1448
  "label",
1315
1449
  {
1316
1450
  className: "flex items-start gap-3 cursor-pointer group rounded-lg border border-border p-3 transition-colors hover:border-primary/30",
1317
1451
  children: [
1318
- /* @__PURE__ */ jsx3(
1452
+ /* @__PURE__ */ jsx4(
1319
1453
  "input",
1320
1454
  {
1321
1455
  type: "checkbox",
@@ -1328,15 +1462,15 @@ function ProvisioningWizard({
1328
1462
  className: "mt-0.5 h-4 w-4 rounded border-border text-primary focus:ring-primary/30"
1329
1463
  }
1330
1464
  ),
1331
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
1332
- /* @__PURE__ */ jsx3("div", { className: "text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: script.name }),
1333
- script.description && /* @__PURE__ */ jsx3("div", { className: "text-xs text-muted-foreground mt-0.5", children: script.description }),
1334
- script.injectSecrets.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap gap-1 mt-1.5", children: script.injectSecrets.map((s) => /* @__PURE__ */ jsxs3(
1465
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 min-w-0", children: [
1466
+ /* @__PURE__ */ jsx4("div", { className: "text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: script.name }),
1467
+ script.description && /* @__PURE__ */ jsx4("div", { className: "text-xs text-muted-foreground mt-0.5", children: script.description }),
1468
+ script.injectSecrets.length > 0 && /* @__PURE__ */ jsx4("div", { className: "flex flex-wrap gap-1 mt-1.5", children: script.injectSecrets.map((s) => /* @__PURE__ */ jsxs4(
1335
1469
  "span",
1336
1470
  {
1337
1471
  className: "inline-flex items-center gap-0.5 rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground",
1338
1472
  children: [
1339
- /* @__PURE__ */ jsxs3(
1473
+ /* @__PURE__ */ jsxs4(
1340
1474
  "svg",
1341
1475
  {
1342
1476
  className: "h-2.5 w-2.5",
@@ -1345,7 +1479,7 @@ function ProvisioningWizard({
1345
1479
  stroke: "currentColor",
1346
1480
  strokeWidth: "2",
1347
1481
  children: [
1348
- /* @__PURE__ */ jsx3(
1482
+ /* @__PURE__ */ jsx4(
1349
1483
  "rect",
1350
1484
  {
1351
1485
  x: "3",
@@ -1356,7 +1490,7 @@ function ProvisioningWizard({
1356
1490
  ry: "2"
1357
1491
  }
1358
1492
  ),
1359
- /* @__PURE__ */ jsx3("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
1493
+ /* @__PURE__ */ jsx4("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
1360
1494
  ]
1361
1495
  }
1362
1496
  ),
@@ -1372,9 +1506,9 @@ function ProvisioningWizard({
1372
1506
  );
1373
1507
  }) })
1374
1508
  ] }),
1375
- /* @__PURE__ */ jsxs3("div", { className: "pt-3 border-t border-border flex items-start justify-between gap-3", children: [
1376
- /* @__PURE__ */ jsxs3("div", { children: [
1377
- /* @__PURE__ */ jsx3(
1509
+ /* @__PURE__ */ jsxs4("div", { className: "pt-3 border-t border-border flex items-start justify-between gap-3", children: [
1510
+ /* @__PURE__ */ jsxs4("div", { children: [
1511
+ /* @__PURE__ */ jsx4(
1378
1512
  "label",
1379
1513
  {
1380
1514
  htmlFor: "wizard-bare-mode",
@@ -1382,9 +1516,9 @@ function ProvisioningWizard({
1382
1516
  children: "Bare Mode"
1383
1517
  }
1384
1518
  ),
1385
- /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Start as a raw container without an embedded AI Agent backend." })
1519
+ /* @__PURE__ */ jsx4("p", { className: "text-xs text-muted-foreground mt-0.5", children: "Start as a raw container without an embedded AI Agent backend." })
1386
1520
  ] }),
1387
- /* @__PURE__ */ jsx3(
1521
+ /* @__PURE__ */ jsx4(
1388
1522
  Switch,
1389
1523
  {
1390
1524
  id: "wizard-bare-mode",
@@ -1395,28 +1529,28 @@ function ProvisioningWizard({
1395
1529
  )
1396
1530
  ] })
1397
1531
  ] })
1398
- ] }) }) }),
1399
- sshAccess && (!isMultistep || currentStep === 3) && /* @__PURE__ */ jsx3(React2.Fragment, { children: /* @__PURE__ */ jsxs3("section", { className: SECTION_CARD_CLASS, children: [
1400
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 mb-4", children: [
1401
- /* @__PURE__ */ jsx3(Settings, { className: "h-4 w-4 text-primary shrink-0" }),
1402
- /* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Access Configuration" })
1532
+ ] }) }),
1533
+ sshAccess && /* @__PURE__ */ jsxs4("section", { className: SECTION_CARD_CLASS, children: [
1534
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 mb-4", children: [
1535
+ /* @__PURE__ */ jsx4(Settings, { className: "h-4 w-4 text-primary shrink-0" }),
1536
+ /* @__PURE__ */ jsx4("h2", { className: "text-sm font-semibold uppercase tracking-[0.06em] text-muted-foreground", children: "Access Configuration" })
1403
1537
  ] }),
1404
- /* @__PURE__ */ jsx3(SshAccessStep, { config: sshAccess })
1405
- ] }) })
1538
+ /* @__PURE__ */ jsx4(SshAccessStep, { config: sshAccess })
1539
+ ] })
1406
1540
  ] })
1407
1541
  ] }),
1408
- /* @__PURE__ */ jsxs3("div", { className: "col-span-12 xl:col-span-4 sticky top-4 space-y-4", children: [
1409
- /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-border bg-card p-5 shadow-sm", children: [
1410
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center mb-3", children: [
1411
- /* @__PURE__ */ jsx3("span", { className: FIELD_LABEL_CLASS, children: "Run Cost" }),
1412
- /* @__PURE__ */ jsxs3(
1542
+ /* @__PURE__ */ jsxs4("div", { className: "col-span-12 xl:col-span-4 sticky top-4 space-y-4", children: [
1543
+ /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-border bg-card p-5 shadow-sm", children: [
1544
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between items-center mb-3", children: [
1545
+ /* @__PURE__ */ jsx4("span", { className: FIELD_LABEL_CLASS, children: "Run Cost" }),
1546
+ /* @__PURE__ */ jsxs4(
1413
1547
  "div",
1414
1548
  {
1415
1549
  role: "group",
1416
1550
  "aria-label": "Pricing view",
1417
1551
  className: "inline-flex items-center rounded-md border border-border bg-muted/50 p-0.5",
1418
1552
  children: [
1419
- /* @__PURE__ */ jsx3(
1553
+ /* @__PURE__ */ jsx4(
1420
1554
  "button",
1421
1555
  {
1422
1556
  type: "button",
@@ -1429,7 +1563,7 @@ function ProvisioningWizard({
1429
1563
  children: "Per Hour"
1430
1564
  }
1431
1565
  ),
1432
- /* @__PURE__ */ jsx3(
1566
+ /* @__PURE__ */ jsx4(
1433
1567
  "button",
1434
1568
  {
1435
1569
  type: "button",
@@ -1446,8 +1580,8 @@ function ProvisioningWizard({
1446
1580
  }
1447
1581
  )
1448
1582
  ] }),
1449
- /* @__PURE__ */ jsxs3("div", { className: "flex items-baseline gap-2 mb-4", children: [
1450
- /* @__PURE__ */ jsxs3(
1583
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-baseline gap-2 mb-4", children: [
1584
+ /* @__PURE__ */ jsxs4(
1451
1585
  "span",
1452
1586
  {
1453
1587
  className: cn(
@@ -1461,36 +1595,36 @@ function ProvisioningWizard({
1461
1595
  },
1462
1596
  pricingView
1463
1597
  ),
1464
- /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground text-sm", children: pricingSuffix })
1598
+ /* @__PURE__ */ jsx4("span", { className: "text-muted-foreground text-sm", children: pricingSuffix })
1465
1599
  ] }),
1466
- /* @__PURE__ */ jsxs3("div", { className: "space-y-2 rounded-md border border-border bg-muted/30 p-3", children: [
1467
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1468
- /* @__PURE__ */ jsx3("span", { children: "COMPUTE" }),
1469
- /* @__PURE__ */ jsxs3("span", { className: "text-foreground", children: [
1600
+ /* @__PURE__ */ jsxs4("div", { className: "space-y-2 rounded-md border border-border bg-muted/30 p-3", children: [
1601
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1602
+ /* @__PURE__ */ jsx4("span", { children: "COMPUTE" }),
1603
+ /* @__PURE__ */ jsxs4("span", { className: "text-foreground", children: [
1470
1604
  "$",
1471
1605
  fmtRate(hourlyCostBreakdown.compute),
1472
1606
  rateSuffix
1473
1607
  ] })
1474
1608
  ] }),
1475
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1476
- /* @__PURE__ */ jsx3("span", { children: "MEMORY" }),
1477
- /* @__PURE__ */ jsxs3("span", { className: "text-foreground/80", children: [
1609
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1610
+ /* @__PURE__ */ jsx4("span", { children: "MEMORY" }),
1611
+ /* @__PURE__ */ jsxs4("span", { className: "text-foreground/80", children: [
1478
1612
  "$",
1479
1613
  fmtRate(hourlyCostBreakdown.memory),
1480
1614
  rateSuffix
1481
1615
  ] })
1482
1616
  ] }),
1483
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1484
- /* @__PURE__ */ jsx3("span", { children: "STORAGE" }),
1485
- /* @__PURE__ */ jsxs3("span", { className: "text-foreground/80", children: [
1617
+ /* @__PURE__ */ jsxs4("div", { className: "flex justify-between text-xs font-mono tracking-wide text-muted-foreground", children: [
1618
+ /* @__PURE__ */ jsx4("span", { children: "STORAGE" }),
1619
+ /* @__PURE__ */ jsxs4("span", { className: "text-foreground/80", children: [
1486
1620
  "$",
1487
1621
  fmtRate(hourlyCostBreakdown.storage),
1488
1622
  rateSuffix
1489
1623
  ] })
1490
1624
  ] }),
1491
- hourlyCostBreakdown.floorApplies && /* @__PURE__ */ jsxs3("div", { className: "flex justify-between text-xs font-mono tracking-wide text-primary border-t border-border pt-2", children: [
1492
- /* @__PURE__ */ jsx3("span", { children: "MIN CHARGE" }),
1493
- /* @__PURE__ */ jsxs3("span", { children: [
1625
+ hourlyCostBreakdown.floorApplies && /* @__PURE__ */ jsxs4("div", { className: "flex justify-between text-xs font-mono tracking-wide text-primary border-t border-border pt-2", children: [
1626
+ /* @__PURE__ */ jsx4("span", { children: "MIN CHARGE" }),
1627
+ /* @__PURE__ */ jsxs4("span", { children: [
1494
1628
  "$",
1495
1629
  fmtRate(
1496
1630
  hourlyCostBreakdown.floor - hourlyCostBreakdown.lineSum
@@ -1500,54 +1634,19 @@ function ProvisioningWizard({
1500
1634
  ] })
1501
1635
  ] })
1502
1636
  ] }),
1503
- deployError && /* @__PURE__ */ jsxs3("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-3 flex items-center gap-2", children: [
1504
- /* @__PURE__ */ jsx3(Info, { className: "h-4 w-4 text-destructive shrink-0" }),
1505
- /* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-destructive", children: deployError })
1637
+ deployError && /* @__PURE__ */ jsxs4("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-3 flex items-center gap-2", children: [
1638
+ /* @__PURE__ */ jsx4(Info, { className: "h-4 w-4 text-destructive shrink-0" }),
1639
+ /* @__PURE__ */ jsx4("p", { className: "text-sm font-medium text-destructive", children: deployError })
1506
1640
  ] }),
1507
- /* @__PURE__ */ jsx3("div", { className: "space-y-2", children: isMultistep ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
1508
- currentStep < finalStep ? /* @__PURE__ */ jsxs3(
1509
- Button,
1510
- {
1511
- type: "button",
1512
- onClick: () => setCurrentStep((s) => s + 1),
1513
- className: "w-full",
1514
- children: [
1515
- "Continue to ",
1516
- stepLabels[currentStep]
1517
- ]
1518
- }
1519
- ) : /* @__PURE__ */ jsx3(
1520
- Button,
1521
- {
1522
- type: "button",
1523
- onClick: handleDeploy,
1524
- disabled: isDeploying || !selectedEnv,
1525
- className: "w-full",
1526
- children: isDeploying ? /* @__PURE__ */ jsxs3("span", { className: "flex items-center justify-center gap-2", children: [
1527
- /* @__PURE__ */ jsx3(Loader2, { className: "h-4 w-4 animate-spin" }),
1528
- "Deploying..."
1529
- ] }) : "Deploy Workspace"
1530
- }
1531
- ),
1532
- currentStep > 1 && /* @__PURE__ */ jsx3(
1533
- Button,
1534
- {
1535
- type: "button",
1536
- variant: "secondary",
1537
- onClick: () => setCurrentStep((s) => s - 1),
1538
- className: "w-full",
1539
- children: "Back"
1540
- }
1541
- )
1542
- ] }) : /* @__PURE__ */ jsx3(
1641
+ /* @__PURE__ */ jsx4("div", { className: "space-y-2", children: /* @__PURE__ */ jsx4(
1543
1642
  Button,
1544
1643
  {
1545
1644
  type: "button",
1546
1645
  onClick: handleDeploy,
1547
1646
  disabled: isDeploying || !selectedEnv,
1548
1647
  className: "w-full",
1549
- children: isDeploying ? /* @__PURE__ */ jsxs3("span", { className: "flex items-center justify-center gap-2", children: [
1550
- /* @__PURE__ */ jsx3(Loader2, { className: "h-4 w-4 animate-spin" }),
1648
+ children: isDeploying ? /* @__PURE__ */ jsxs4("span", { className: "flex items-center justify-center gap-2", children: [
1649
+ /* @__PURE__ */ jsx4(Loader22, { className: "h-4 w-4 animate-spin" }),
1551
1650
  "Spinning up environment..."
1552
1651
  ] }) : "Deploy Workspace"
1553
1652
  }
@@ -1558,10 +1657,10 @@ function ProvisioningWizard({
1558
1657
  }
1559
1658
 
1560
1659
  // src/pages/pricing-page.tsx
1561
- import * as React3 from "react";
1660
+ import * as React4 from "react";
1562
1661
  import { Skeleton as Skeleton2, SkeletonCard as SkeletonCard2 } from "@tangle-network/ui/primitives";
1563
1662
  import { ChevronDown } from "lucide-react";
1564
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1663
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1565
1664
  async function fetchTiersFromApi(apiBasePath) {
1566
1665
  const res = await fetch(`${apiBasePath}/v1/billing/tiers`);
1567
1666
  if (!res.ok) throw new Error("Failed to fetch pricing tiers");
@@ -1593,14 +1692,14 @@ function StandalonePricingPage({
1593
1692
  eyebrow,
1594
1693
  className
1595
1694
  }) {
1596
- const [state, setState] = React3.useState({
1695
+ const [state, setState] = React4.useState({
1597
1696
  tiers: initialTiers || [],
1598
1697
  loading: !initialTiers,
1599
1698
  error: null,
1600
1699
  billingPeriod: "monthly",
1601
1700
  selectingTier: false
1602
1701
  });
1603
- const loadTiers = React3.useCallback(async () => {
1702
+ const loadTiers = React4.useCallback(async () => {
1604
1703
  setState((prev) => ({ ...prev, loading: true, error: null }));
1605
1704
  try {
1606
1705
  const tiers = fetchTiers ? await fetchTiers() : await fetchTiersFromApi(apiBasePath);
@@ -1613,12 +1712,12 @@ function StandalonePricingPage({
1613
1712
  }));
1614
1713
  }
1615
1714
  }, [apiBasePath, fetchTiers]);
1616
- React3.useEffect(() => {
1715
+ React4.useEffect(() => {
1617
1716
  if (!initialTiers) {
1618
1717
  loadTiers();
1619
1718
  }
1620
1719
  }, [initialTiers, loadTiers]);
1621
- const handleSelectTier = React3.useCallback(
1720
+ const handleSelectTier = React4.useCallback(
1622
1721
  async (tierId) => {
1623
1722
  if (onSelectTier) {
1624
1723
  onSelectTier(tierId, state.billingPeriod);
@@ -1645,25 +1744,25 @@ function StandalonePricingPage({
1645
1744
  },
1646
1745
  [apiBasePath, state.billingPeriod, onSelectTier]
1647
1746
  );
1648
- return /* @__PURE__ */ jsxs4("div", { className: cn("mx-auto max-w-6xl px-6 py-16 space-y-16", className), children: [
1649
- /* @__PURE__ */ jsxs4("div", { className: "space-y-4 text-center", children: [
1650
- eyebrow && /* @__PURE__ */ jsx4("span", { className: "text-xs font-bold uppercase tracking-widest text-[var(--brand-emerald,#10B981)]", children: eyebrow }),
1651
- /* @__PURE__ */ jsx4("h1", { className: "text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl font-display", children: title }),
1652
- /* @__PURE__ */ jsx4("p", { className: "mx-auto max-w-2xl text-lg text-muted-foreground", children: subtitle })
1747
+ return /* @__PURE__ */ jsxs5("div", { className: cn("mx-auto max-w-6xl px-6 py-16 space-y-16", className), children: [
1748
+ /* @__PURE__ */ jsxs5("div", { className: "space-y-4 text-center", children: [
1749
+ eyebrow && /* @__PURE__ */ jsx5("span", { className: "text-xs font-bold uppercase tracking-widest text-[var(--brand-emerald,#10B981)]", children: eyebrow }),
1750
+ /* @__PURE__ */ jsx5("h1", { className: "text-4xl font-extrabold tracking-tight text-foreground sm:text-5xl font-display", children: title }),
1751
+ /* @__PURE__ */ jsx5("p", { className: "mx-auto max-w-2xl text-lg text-muted-foreground", children: subtitle })
1653
1752
  ] }),
1654
- state.loading ? /* @__PURE__ */ jsxs4("div", { className: "space-y-8", children: [
1655
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-center gap-4", children: [
1656
- /* @__PURE__ */ jsx4(Skeleton2, { className: "h-10 w-24" }),
1657
- /* @__PURE__ */ jsx4(Skeleton2, { className: "h-10 w-24" })
1753
+ state.loading ? /* @__PURE__ */ jsxs5("div", { className: "space-y-8", children: [
1754
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-4", children: [
1755
+ /* @__PURE__ */ jsx5(Skeleton2, { className: "h-10 w-24" }),
1756
+ /* @__PURE__ */ jsx5(Skeleton2, { className: "h-10 w-24" })
1658
1757
  ] }),
1659
- /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-3", children: [
1660
- /* @__PURE__ */ jsx4(SkeletonCard2, { className: "h-[500px]" }),
1661
- /* @__PURE__ */ jsx4(SkeletonCard2, { className: "h-[500px]" }),
1662
- /* @__PURE__ */ jsx4(SkeletonCard2, { className: "h-[500px]" })
1758
+ /* @__PURE__ */ jsxs5("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-3", children: [
1759
+ /* @__PURE__ */ jsx5(SkeletonCard2, { className: "h-[500px]" }),
1760
+ /* @__PURE__ */ jsx5(SkeletonCard2, { className: "h-[500px]" }),
1761
+ /* @__PURE__ */ jsx5(SkeletonCard2, { className: "h-[500px]" })
1663
1762
  ] })
1664
- ] }) : state.error ? /* @__PURE__ */ jsxs4("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: [
1665
- /* @__PURE__ */ jsx4("p", { className: "text-destructive text-sm font-medium", children: state.error }),
1666
- /* @__PURE__ */ jsx4(
1763
+ ] }) : state.error ? /* @__PURE__ */ jsxs5("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: [
1764
+ /* @__PURE__ */ jsx5("p", { className: "text-destructive text-sm font-medium", children: state.error }),
1765
+ /* @__PURE__ */ jsx5(
1667
1766
  "button",
1668
1767
  {
1669
1768
  type: "button",
@@ -1672,7 +1771,7 @@ function StandalonePricingPage({
1672
1771
  children: "Try Again"
1673
1772
  }
1674
1773
  )
1675
- ] }) : /* @__PURE__ */ jsx4(
1774
+ ] }) : /* @__PURE__ */ jsx5(
1676
1775
  PricingPage,
1677
1776
  {
1678
1777
  tiers: state.tiers,
@@ -1683,14 +1782,14 @@ function StandalonePricingPage({
1683
1782
  loading: state.selectingTier
1684
1783
  }
1685
1784
  ),
1686
- /* @__PURE__ */ jsxs4("div", { className: "mx-auto max-w-2xl space-y-4 border-t border-border pt-12", children: [
1687
- /* @__PURE__ */ jsx4("h2", { className: "text-center text-xl font-bold text-foreground mb-6", children: "Frequently Asked Questions" }),
1688
- FAQ.map(({ q, a }) => /* @__PURE__ */ jsxs4("details", { className: "group rounded-xl border border-border bg-card overflow-hidden", children: [
1689
- /* @__PURE__ */ jsxs4("summary", { className: "flex cursor-pointer items-center justify-between px-6 py-4 font-medium text-foreground text-sm", children: [
1785
+ /* @__PURE__ */ jsxs5("div", { className: "mx-auto max-w-2xl space-y-4 border-t border-border pt-12", children: [
1786
+ /* @__PURE__ */ jsx5("h2", { className: "text-center text-xl font-bold text-foreground mb-6", children: "Frequently Asked Questions" }),
1787
+ FAQ.map(({ q, a }) => /* @__PURE__ */ jsxs5("details", { className: "group rounded-xl border border-border bg-card overflow-hidden", children: [
1788
+ /* @__PURE__ */ jsxs5("summary", { className: "flex cursor-pointer items-center justify-between px-6 py-4 font-medium text-foreground text-sm", children: [
1690
1789
  q,
1691
- /* @__PURE__ */ jsx4(ChevronDown, { className: "h-4 w-4 text-muted-foreground transition-transform group-open:rotate-180" })
1790
+ /* @__PURE__ */ jsx5(ChevronDown, { className: "h-4 w-4 text-muted-foreground transition-transform group-open:rotate-180" })
1692
1791
  ] }),
1693
- /* @__PURE__ */ jsx4("div", { className: "px-6 pb-4", children: /* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground leading-relaxed", children: a }) })
1792
+ /* @__PURE__ */ jsx5("div", { className: "px-6 pb-4", children: /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground leading-relaxed", children: a }) })
1694
1793
  ] }, q))
1695
1794
  ] })
1696
1795
  ] });
@@ -1702,27 +1801,27 @@ import {
1702
1801
  ChevronRight,
1703
1802
  Copy,
1704
1803
  Edit2,
1705
- Loader2 as Loader22,
1804
+ Loader2 as Loader23,
1706
1805
  Plus as Plus2,
1707
1806
  Search,
1708
1807
  Settings2,
1709
1808
  Trash2 as Trash22
1710
1809
  } from "lucide-react";
1711
- import * as React4 from "react";
1810
+ import * as React5 from "react";
1712
1811
  import { Button as Button2 } from "@tangle-network/ui/primitives";
1713
1812
  import { Badge as Badge2 } from "@tangle-network/ui/primitives";
1714
1813
  import { Card } from "@tangle-network/ui/primitives";
1715
1814
  import {
1716
- Dialog,
1717
- DialogContent,
1718
- DialogDescription,
1719
- DialogFooter,
1720
- DialogHeader,
1721
- DialogTitle
1815
+ Dialog as Dialog2,
1816
+ DialogContent as DialogContent2,
1817
+ DialogDescription as DialogDescription2,
1818
+ DialogFooter as DialogFooter2,
1819
+ DialogHeader as DialogHeader2,
1820
+ DialogTitle as DialogTitle2
1722
1821
  } from "@tangle-network/ui/primitives";
1723
1822
  import { EmptyState } from "@tangle-network/ui/primitives";
1724
1823
  import { Input as Input2 } from "@tangle-network/ui/primitives";
1725
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1824
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1726
1825
  var TIER_LIMITS = {
1727
1826
  free: 3,
1728
1827
  starter: 10,
@@ -1736,24 +1835,24 @@ function ProfilesPage({
1736
1835
  onCompareClick,
1737
1836
  title = "Profiles"
1738
1837
  }) {
1739
- const [builtinProfiles, setBuiltinProfiles] = React4.useState([]);
1740
- const [customProfiles, setCustomProfiles] = React4.useState([]);
1741
- const [loading, setLoading] = React4.useState(true);
1742
- const [error, setError] = React4.useState(null);
1743
- const [searchQuery, setSearchQuery] = React4.useState("");
1744
- const [createDialogOpen, setCreateDialogOpen] = React4.useState(false);
1745
- const [editingProfile, setEditingProfile] = React4.useState(
1838
+ const [builtinProfiles, setBuiltinProfiles] = React5.useState([]);
1839
+ const [customProfiles, setCustomProfiles] = React5.useState([]);
1840
+ const [loading, setLoading] = React5.useState(true);
1841
+ const [error, setError] = React5.useState(null);
1842
+ const [searchQuery, setSearchQuery] = React5.useState("");
1843
+ const [createDialogOpen, setCreateDialogOpen] = React5.useState(false);
1844
+ const [editingProfile, setEditingProfile] = React5.useState(
1746
1845
  null
1747
1846
  );
1748
- const [deletingProfile, setDeletingProfile] = React4.useState(
1847
+ const [deletingProfile, setDeletingProfile] = React5.useState(
1749
1848
  null
1750
1849
  );
1751
- const [detailProfile, setDetailProfile] = React4.useState(
1850
+ const [detailProfile, setDetailProfile] = React5.useState(
1752
1851
  null
1753
1852
  );
1754
1853
  const profileLimit = maxProfiles ?? TIER_LIMITS[tier] ?? 3;
1755
1854
  const canCreateMore = customProfiles.length < profileLimit;
1756
- const loadProfiles = React4.useCallback(async () => {
1855
+ const loadProfiles = React5.useCallback(async () => {
1757
1856
  try {
1758
1857
  setLoading(true);
1759
1858
  setError(null);
@@ -1766,7 +1865,7 @@ function ProfilesPage({
1766
1865
  setLoading(false);
1767
1866
  }
1768
1867
  }, [apiClient]);
1769
- React4.useEffect(() => {
1868
+ React5.useEffect(() => {
1770
1869
  loadProfiles();
1771
1870
  }, [loadProfiles]);
1772
1871
  const filteredBuiltin = builtinProfiles.filter(
@@ -1775,14 +1874,14 @@ function ProfilesPage({
1775
1874
  const filteredCustom = customProfiles.filter(
1776
1875
  (p) => p.name.toLowerCase().includes(searchQuery.toLowerCase()) || p.description?.toLowerCase().includes(searchQuery.toLowerCase())
1777
1876
  );
1778
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-6", children: [
1779
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
1780
- /* @__PURE__ */ jsxs5("div", { children: [
1781
- /* @__PURE__ */ jsx5("h1", { className: "font-semibold text-2xl", children: title }),
1782
- /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: "Customize agent behavior with system prompts, models, and instructions" })
1877
+ return /* @__PURE__ */ jsxs6("div", { className: "space-y-6", children: [
1878
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
1879
+ /* @__PURE__ */ jsxs6("div", { children: [
1880
+ /* @__PURE__ */ jsx6("h1", { className: "font-semibold text-2xl", children: title }),
1881
+ /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground", children: "Customize agent behavior with system prompts, models, and instructions" })
1783
1882
  ] }),
1784
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
1785
- onCompareClick && customProfiles.length >= 2 && /* @__PURE__ */ jsx5(
1883
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
1884
+ onCompareClick && customProfiles.length >= 2 && /* @__PURE__ */ jsx6(
1786
1885
  Button2,
1787
1886
  {
1788
1887
  variant: "outline",
@@ -1790,30 +1889,30 @@ function ProfilesPage({
1790
1889
  children: "Compare Profiles"
1791
1890
  }
1792
1891
  ),
1793
- /* @__PURE__ */ jsxs5(
1892
+ /* @__PURE__ */ jsxs6(
1794
1893
  Button2,
1795
1894
  {
1796
1895
  onClick: () => setCreateDialogOpen(true),
1797
1896
  disabled: !canCreateMore,
1798
1897
  children: [
1799
- /* @__PURE__ */ jsx5(Plus2, { className: "mr-2 h-4 w-4" }),
1898
+ /* @__PURE__ */ jsx6(Plus2, { className: "mr-2 h-4 w-4" }),
1800
1899
  "Create Profile"
1801
1900
  ]
1802
1901
  }
1803
1902
  )
1804
1903
  ] })
1805
1904
  ] }),
1806
- !canCreateMore && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] p-3 text-sm text-[var(--surface-warning-text)]", children: [
1807
- /* @__PURE__ */ jsx5(AlertCircle, { className: "h-4 w-4" }),
1808
- /* @__PURE__ */ jsxs5("span", { children: [
1905
+ !canCreateMore && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] p-3 text-sm text-[var(--surface-warning-text)]", children: [
1906
+ /* @__PURE__ */ jsx6(AlertCircle, { className: "h-4 w-4" }),
1907
+ /* @__PURE__ */ jsxs6("span", { children: [
1809
1908
  "You've reached your profile limit (",
1810
1909
  profileLimit,
1811
1910
  " profiles). Upgrade your plan to create more."
1812
1911
  ] })
1813
1912
  ] }),
1814
- /* @__PURE__ */ jsxs5("div", { className: "relative max-w-md", children: [
1815
- /* @__PURE__ */ jsx5(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
1816
- /* @__PURE__ */ jsx5(
1913
+ /* @__PURE__ */ jsxs6("div", { className: "relative max-w-md", children: [
1914
+ /* @__PURE__ */ jsx6(Search, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
1915
+ /* @__PURE__ */ jsx6(
1817
1916
  Input2,
1818
1917
  {
1819
1918
  placeholder: "Search profiles...",
@@ -1823,33 +1922,33 @@ function ProfilesPage({
1823
1922
  }
1824
1923
  )
1825
1924
  ] }),
1826
- error && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
1827
- /* @__PURE__ */ jsx5(AlertCircle, { className: "h-4 w-4" }),
1828
- /* @__PURE__ */ jsx5("span", { children: error }),
1829
- /* @__PURE__ */ jsx5(Button2, { variant: "ghost", size: "sm", onClick: loadProfiles, children: "Retry" })
1925
+ error && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
1926
+ /* @__PURE__ */ jsx6(AlertCircle, { className: "h-4 w-4" }),
1927
+ /* @__PURE__ */ jsx6("span", { children: error }),
1928
+ /* @__PURE__ */ jsx6(Button2, { variant: "ghost", size: "sm", onClick: loadProfiles, children: "Retry" })
1830
1929
  ] }),
1831
- loading && /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx5(Loader22, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }),
1832
- !loading && /* @__PURE__ */ jsxs5("div", { className: "space-y-8", children: [
1833
- /* @__PURE__ */ jsxs5("section", { children: [
1834
- /* @__PURE__ */ jsx5("div", { className: "mb-3 flex items-center justify-between", children: /* @__PURE__ */ jsxs5("h2", { className: "font-medium text-lg", children: [
1930
+ loading && /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx6(Loader23, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }),
1931
+ !loading && /* @__PURE__ */ jsxs6("div", { className: "space-y-8", children: [
1932
+ /* @__PURE__ */ jsxs6("section", { children: [
1933
+ /* @__PURE__ */ jsx6("div", { className: "mb-3 flex items-center justify-between", children: /* @__PURE__ */ jsxs6("h2", { className: "font-medium text-lg", children: [
1835
1934
  "Your Profiles (",
1836
1935
  customProfiles.length,
1837
1936
  "/",
1838
1937
  profileLimit === Number.POSITIVE_INFINITY ? "inf" : profileLimit,
1839
1938
  ")"
1840
1939
  ] }) }),
1841
- filteredCustom.length === 0 ? /* @__PURE__ */ jsx5(
1940
+ filteredCustom.length === 0 ? /* @__PURE__ */ jsx6(
1842
1941
  EmptyState,
1843
1942
  {
1844
- icon: /* @__PURE__ */ jsx5(Settings2, { className: "h-8 w-8" }),
1943
+ icon: /* @__PURE__ */ jsx6(Settings2, { className: "h-8 w-8" }),
1845
1944
  title: "No custom profiles yet",
1846
1945
  description: "Create a profile to customize agent behavior",
1847
- action: canCreateMore ? /* @__PURE__ */ jsxs5(Button2, { onClick: () => setCreateDialogOpen(true), children: [
1848
- /* @__PURE__ */ jsx5(Plus2, { className: "mr-2 h-4 w-4" }),
1946
+ action: canCreateMore ? /* @__PURE__ */ jsxs6(Button2, { onClick: () => setCreateDialogOpen(true), children: [
1947
+ /* @__PURE__ */ jsx6(Plus2, { className: "mr-2 h-4 w-4" }),
1849
1948
  "Create Profile"
1850
1949
  ] }) : void 0
1851
1950
  }
1852
- ) : /* @__PURE__ */ jsx5("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: filteredCustom.map((profile) => /* @__PURE__ */ jsx5(
1951
+ ) : /* @__PURE__ */ jsx6("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: filteredCustom.map((profile) => /* @__PURE__ */ jsx6(
1853
1952
  ProfileCard,
1854
1953
  {
1855
1954
  profile,
@@ -1860,13 +1959,13 @@ function ProfilesPage({
1860
1959
  profile.id
1861
1960
  )) })
1862
1961
  ] }),
1863
- /* @__PURE__ */ jsxs5("section", { children: [
1864
- /* @__PURE__ */ jsx5("div", { className: "mb-3 flex items-center justify-between", children: /* @__PURE__ */ jsxs5("h2", { className: "font-medium text-lg", children: [
1962
+ /* @__PURE__ */ jsxs6("section", { children: [
1963
+ /* @__PURE__ */ jsx6("div", { className: "mb-3 flex items-center justify-between", children: /* @__PURE__ */ jsxs6("h2", { className: "font-medium text-lg", children: [
1865
1964
  "Built-in Profiles (",
1866
1965
  builtinProfiles.length,
1867
1966
  ")"
1868
1967
  ] }) }),
1869
- filteredBuiltin.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-sm", children: "No matching built-in profiles" }) : /* @__PURE__ */ jsx5("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: filteredBuiltin.map((profile) => /* @__PURE__ */ jsx5(
1968
+ filteredBuiltin.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground text-sm", children: "No matching built-in profiles" }) : /* @__PURE__ */ jsx6("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: filteredBuiltin.map((profile) => /* @__PURE__ */ jsx6(
1870
1969
  ProfileCard,
1871
1970
  {
1872
1971
  profile,
@@ -1877,7 +1976,7 @@ function ProfilesPage({
1877
1976
  )) })
1878
1977
  ] })
1879
1978
  ] }),
1880
- /* @__PURE__ */ jsx5(
1979
+ /* @__PURE__ */ jsx6(
1881
1980
  ProfileFormDialog,
1882
1981
  {
1883
1982
  open: createDialogOpen || !!editingProfile,
@@ -1895,7 +1994,7 @@ function ProfilesPage({
1895
1994
  }
1896
1995
  }
1897
1996
  ),
1898
- /* @__PURE__ */ jsx5(
1997
+ /* @__PURE__ */ jsx6(
1899
1998
  DeleteProfileDialog,
1900
1999
  {
1901
2000
  profile: deletingProfile,
@@ -1907,7 +2006,7 @@ function ProfilesPage({
1907
2006
  }
1908
2007
  }
1909
2008
  ),
1910
- /* @__PURE__ */ jsx5(
2009
+ /* @__PURE__ */ jsx6(
1911
2010
  ProfileDetailDialog,
1912
2011
  {
1913
2012
  profile: detailProfile,
@@ -1936,61 +2035,61 @@ function ProfileCard({
1936
2035
  onDelete,
1937
2036
  isBuiltin
1938
2037
  }) {
1939
- return /* @__PURE__ */ jsxs5(
2038
+ return /* @__PURE__ */ jsxs6(
1940
2039
  Card,
1941
2040
  {
1942
2041
  className: "cursor-pointer p-4 transition-colors hover:border-border/80",
1943
2042
  onClick: onView,
1944
2043
  children: [
1945
- /* @__PURE__ */ jsxs5("div", { className: "flex items-start justify-between", children: [
1946
- /* @__PURE__ */ jsxs5("div", { className: "flex-1", children: [
1947
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
1948
- /* @__PURE__ */ jsx5("h3", { className: "font-medium", children: profile.name }),
1949
- isBuiltin && /* @__PURE__ */ jsx5(Badge2, { variant: "secondary", className: "border-0 text-xs", children: "Built-in" }),
1950
- profile.is_public && !isBuiltin && /* @__PURE__ */ jsx5(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Public" })
2044
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-start justify-between", children: [
2045
+ /* @__PURE__ */ jsxs6("div", { className: "flex-1", children: [
2046
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
2047
+ /* @__PURE__ */ jsx6("h3", { className: "font-medium", children: profile.name }),
2048
+ isBuiltin && /* @__PURE__ */ jsx6(Badge2, { variant: "secondary", className: "border-0 text-xs", children: "Built-in" }),
2049
+ profile.is_public && !isBuiltin && /* @__PURE__ */ jsx6(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Public" })
1951
2050
  ] }),
1952
- profile.description && /* @__PURE__ */ jsx5("p", { className: "mt-1 line-clamp-2 text-muted-foreground text-sm", children: profile.description })
2051
+ profile.description && /* @__PURE__ */ jsx6("p", { className: "mt-1 line-clamp-2 text-muted-foreground text-sm", children: profile.description })
1953
2052
  ] }),
1954
- !isBuiltin && /* @__PURE__ */ jsxs5("div", { className: "flex gap-1", onClick: (e) => e.stopPropagation(), children: [
1955
- onEdit && /* @__PURE__ */ jsx5(
2053
+ !isBuiltin && /* @__PURE__ */ jsxs6("div", { className: "flex gap-1", onClick: (e) => e.stopPropagation(), children: [
2054
+ onEdit && /* @__PURE__ */ jsx6(
1956
2055
  Button2,
1957
2056
  {
1958
2057
  variant: "ghost",
1959
2058
  size: "icon",
1960
2059
  onClick: onEdit,
1961
2060
  "aria-label": "Edit profile",
1962
- children: /* @__PURE__ */ jsx5(Edit2, { className: "h-4 w-4" })
2061
+ children: /* @__PURE__ */ jsx6(Edit2, { className: "h-4 w-4" })
1963
2062
  }
1964
2063
  ),
1965
- onDelete && /* @__PURE__ */ jsx5(
2064
+ onDelete && /* @__PURE__ */ jsx6(
1966
2065
  Button2,
1967
2066
  {
1968
2067
  variant: "ghost",
1969
2068
  size: "icon",
1970
2069
  onClick: onDelete,
1971
2070
  "aria-label": "Delete profile",
1972
- children: /* @__PURE__ */ jsx5(Trash22, { className: "h-4 w-4 text-[var(--surface-danger-text)]" })
2071
+ children: /* @__PURE__ */ jsx6(Trash22, { className: "h-4 w-4 text-[var(--surface-danger-text)]" })
1973
2072
  }
1974
2073
  )
1975
2074
  ] })
1976
2075
  ] }),
1977
- /* @__PURE__ */ jsxs5("div", { className: "mt-3 flex flex-wrap gap-2", children: [
1978
- profile.extends && /* @__PURE__ */ jsxs5(Badge2, { variant: "outline", className: "text-xs", children: [
2076
+ /* @__PURE__ */ jsxs6("div", { className: "mt-3 flex flex-wrap gap-2", children: [
2077
+ profile.extends && /* @__PURE__ */ jsxs6(Badge2, { variant: "outline", className: "text-xs", children: [
1979
2078
  "extends ",
1980
2079
  profile.extends
1981
2080
  ] }),
1982
- profile.model && /* @__PURE__ */ jsx5(Badge2, { variant: "outline", className: "text-xs", children: profile.model.split("/").pop() })
2081
+ profile.model && /* @__PURE__ */ jsx6(Badge2, { variant: "outline", className: "text-xs", children: profile.model.split("/").pop() })
1983
2082
  ] }),
1984
- profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs5("div", { className: "mt-3 flex gap-4 border-border border-t pt-3 text-muted-foreground text-xs", children: [
1985
- /* @__PURE__ */ jsxs5("span", { children: [
2083
+ profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs6("div", { className: "mt-3 flex gap-4 border-border border-t pt-3 text-muted-foreground text-xs", children: [
2084
+ /* @__PURE__ */ jsxs6("span", { children: [
1986
2085
  profile.metrics.total_runs,
1987
2086
  " runs"
1988
2087
  ] }),
1989
- /* @__PURE__ */ jsxs5("span", { children: [
2088
+ /* @__PURE__ */ jsxs6("span", { children: [
1990
2089
  profile.metrics.success_rate.toFixed(0),
1991
2090
  "% success"
1992
2091
  ] }),
1993
- /* @__PURE__ */ jsxs5("span", { children: [
2092
+ /* @__PURE__ */ jsxs6("span", { children: [
1994
2093
  "~",
1995
2094
  (profile.metrics.avg_duration_ms / 1e3).toFixed(1),
1996
2095
  "s avg"
@@ -2009,7 +2108,7 @@ function ProfileFormDialog({
2009
2108
  onSuccess
2010
2109
  }) {
2011
2110
  const isEditing = !!profile?.id;
2012
- const [formData, setFormData] = React4.useState({
2111
+ const [formData, setFormData] = React5.useState({
2013
2112
  name: "",
2014
2113
  description: "",
2015
2114
  extends: "",
@@ -2019,9 +2118,9 @@ function ProfileFormDialog({
2019
2118
  tags: [],
2020
2119
  is_public: false
2021
2120
  });
2022
- const [saving, setSaving] = React4.useState(false);
2023
- const [error, setError] = React4.useState(null);
2024
- React4.useEffect(() => {
2121
+ const [saving, setSaving] = React5.useState(false);
2122
+ const [error, setError] = React5.useState(null);
2123
+ React5.useEffect(() => {
2025
2124
  if (profile) {
2026
2125
  setFormData({
2027
2126
  name: profile.name,
@@ -2077,19 +2176,19 @@ function ProfileFormDialog({
2077
2176
  setSaving(false);
2078
2177
  }
2079
2178
  };
2080
- return /* @__PURE__ */ jsx5(Dialog, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-w-2xl", children: [
2081
- /* @__PURE__ */ jsxs5(DialogHeader, { children: [
2082
- /* @__PURE__ */ jsx5(DialogTitle, { children: isEditing ? "Edit Profile" : "Create Profile" }),
2083
- /* @__PURE__ */ jsx5(DialogDescription, { children: isEditing ? "Update your custom profile configuration" : "Create a new profile to customize agent behavior" })
2179
+ return /* @__PURE__ */ jsx6(Dialog2, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs6(DialogContent2, { className: "max-w-2xl", children: [
2180
+ /* @__PURE__ */ jsxs6(DialogHeader2, { children: [
2181
+ /* @__PURE__ */ jsx6(DialogTitle2, { children: isEditing ? "Edit Profile" : "Create Profile" }),
2182
+ /* @__PURE__ */ jsx6(DialogDescription2, { children: isEditing ? "Update your custom profile configuration" : "Create a new profile to customize agent behavior" })
2084
2183
  ] }),
2085
- /* @__PURE__ */ jsxs5("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2086
- error && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
2087
- /* @__PURE__ */ jsx5(AlertCircle, { className: "h-4 w-4" }),
2088
- /* @__PURE__ */ jsx5("span", { children: error })
2184
+ /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2185
+ error && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
2186
+ /* @__PURE__ */ jsx6(AlertCircle, { className: "h-4 w-4" }),
2187
+ /* @__PURE__ */ jsx6("span", { children: error })
2089
2188
  ] }),
2090
- /* @__PURE__ */ jsxs5("div", { children: [
2091
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "Name *" }),
2092
- /* @__PURE__ */ jsx5(
2189
+ /* @__PURE__ */ jsxs6("div", { children: [
2190
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "Name *" }),
2191
+ /* @__PURE__ */ jsx6(
2093
2192
  Input2,
2094
2193
  {
2095
2194
  value: formData.name,
@@ -2101,9 +2200,9 @@ function ProfileFormDialog({
2101
2200
  }
2102
2201
  )
2103
2202
  ] }),
2104
- /* @__PURE__ */ jsxs5("div", { children: [
2105
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "Description" }),
2106
- /* @__PURE__ */ jsx5(
2203
+ /* @__PURE__ */ jsxs6("div", { children: [
2204
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "Description" }),
2205
+ /* @__PURE__ */ jsx6(
2107
2206
  Input2,
2108
2207
  {
2109
2208
  value: formData.description,
@@ -2112,17 +2211,17 @@ function ProfileFormDialog({
2112
2211
  }
2113
2212
  )
2114
2213
  ] }),
2115
- /* @__PURE__ */ jsxs5("div", { children: [
2116
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "Extends (base profile)" }),
2117
- /* @__PURE__ */ jsxs5(
2214
+ /* @__PURE__ */ jsxs6("div", { children: [
2215
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "Extends (base profile)" }),
2216
+ /* @__PURE__ */ jsxs6(
2118
2217
  "select",
2119
2218
  {
2120
2219
  value: formData.extends,
2121
2220
  onChange: (e) => setFormData((d) => ({ ...d, extends: e.target.value })),
2122
2221
  className: "w-full rounded-md border border-border bg-background px-3 py-2 text-sm",
2123
2222
  children: [
2124
- /* @__PURE__ */ jsx5("option", { value: "", children: "None (start from scratch)" }),
2125
- builtinProfiles.map((p) => /* @__PURE__ */ jsxs5("option", { value: p.name, children: [
2223
+ /* @__PURE__ */ jsx6("option", { value: "", children: "None (start from scratch)" }),
2224
+ builtinProfiles.map((p) => /* @__PURE__ */ jsxs6("option", { value: p.name, children: [
2126
2225
  p.name,
2127
2226
  " - ",
2128
2227
  p.description ?? "Built-in profile"
@@ -2131,9 +2230,9 @@ function ProfileFormDialog({
2131
2230
  }
2132
2231
  )
2133
2232
  ] }),
2134
- /* @__PURE__ */ jsxs5("div", { children: [
2135
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "Model" }),
2136
- /* @__PURE__ */ jsx5(
2233
+ /* @__PURE__ */ jsxs6("div", { children: [
2234
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "Model" }),
2235
+ /* @__PURE__ */ jsx6(
2137
2236
  Input2,
2138
2237
  {
2139
2238
  value: formData.model,
@@ -2141,11 +2240,11 @@ function ProfileFormDialog({
2141
2240
  placeholder: "anthropic/claude-sonnet-4"
2142
2241
  }
2143
2242
  ),
2144
- /* @__PURE__ */ jsx5("p", { className: "mt-1 text-muted-foreground text-xs", children: "Format: provider/model-id (e.g., anthropic/claude-sonnet-4)" })
2243
+ /* @__PURE__ */ jsx6("p", { className: "mt-1 text-muted-foreground text-xs", children: "Format: provider/model-id (e.g., anthropic/claude-sonnet-4)" })
2145
2244
  ] }),
2146
- /* @__PURE__ */ jsxs5("div", { children: [
2147
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "System Prompt" }),
2148
- /* @__PURE__ */ jsx5(
2245
+ /* @__PURE__ */ jsxs6("div", { children: [
2246
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "System Prompt" }),
2247
+ /* @__PURE__ */ jsx6(
2149
2248
  "textarea",
2150
2249
  {
2151
2250
  value: formData.system_prompt,
@@ -2156,9 +2255,9 @@ function ProfileFormDialog({
2156
2255
  }
2157
2256
  )
2158
2257
  ] }),
2159
- /* @__PURE__ */ jsxs5("div", { children: [
2160
- /* @__PURE__ */ jsx5("label", { className: "mb-1 block font-medium text-sm", children: "Tags" }),
2161
- /* @__PURE__ */ jsx5(
2258
+ /* @__PURE__ */ jsxs6("div", { children: [
2259
+ /* @__PURE__ */ jsx6("label", { className: "mb-1 block font-medium text-sm", children: "Tags" }),
2260
+ /* @__PURE__ */ jsx6(
2162
2261
  Input2,
2163
2262
  {
2164
2263
  value: formData.tags?.join(", "),
@@ -2169,10 +2268,10 @@ function ProfileFormDialog({
2169
2268
  placeholder: "trading, aggressive, experimental"
2170
2269
  }
2171
2270
  ),
2172
- /* @__PURE__ */ jsx5("p", { className: "mt-1 text-muted-foreground text-xs", children: "Comma-separated tags for organization" })
2271
+ /* @__PURE__ */ jsx6("p", { className: "mt-1 text-muted-foreground text-xs", children: "Comma-separated tags for organization" })
2173
2272
  ] }),
2174
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
2175
- /* @__PURE__ */ jsx5(
2273
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
2274
+ /* @__PURE__ */ jsx6(
2176
2275
  "input",
2177
2276
  {
2178
2277
  type: "checkbox",
@@ -2182,12 +2281,12 @@ function ProfileFormDialog({
2182
2281
  className: "rounded border-border"
2183
2282
  }
2184
2283
  ),
2185
- /* @__PURE__ */ jsx5("label", { htmlFor: "is_public", className: "text-sm", children: "Make this profile public (visible to other users)" })
2284
+ /* @__PURE__ */ jsx6("label", { htmlFor: "is_public", className: "text-sm", children: "Make this profile public (visible to other users)" })
2186
2285
  ] }),
2187
- /* @__PURE__ */ jsxs5(DialogFooter, { children: [
2188
- /* @__PURE__ */ jsx5(Button2, { type: "button", variant: "outline", onClick: onClose, children: "Cancel" }),
2189
- /* @__PURE__ */ jsxs5(Button2, { type: "submit", disabled: saving || !formData.name, children: [
2190
- saving && /* @__PURE__ */ jsx5(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
2286
+ /* @__PURE__ */ jsxs6(DialogFooter2, { children: [
2287
+ /* @__PURE__ */ jsx6(Button2, { type: "button", variant: "outline", onClick: onClose, children: "Cancel" }),
2288
+ /* @__PURE__ */ jsxs6(Button2, { type: "submit", disabled: saving || !formData.name, children: [
2289
+ saving && /* @__PURE__ */ jsx6(Loader23, { className: "mr-2 h-4 w-4 animate-spin" }),
2191
2290
  isEditing ? "Save Changes" : "Create Profile"
2192
2291
  ] })
2193
2292
  ] })
@@ -2200,8 +2299,8 @@ function DeleteProfileDialog({
2200
2299
  apiClient,
2201
2300
  onSuccess
2202
2301
  }) {
2203
- const [deleting, setDeleting] = React4.useState(false);
2204
- const [error, setError] = React4.useState(null);
2302
+ const [deleting, setDeleting] = React5.useState(false);
2303
+ const [error, setError] = React5.useState(null);
2205
2304
  const handleDelete = async () => {
2206
2305
  if (!profile) return;
2207
2306
  setError(null);
@@ -2215,34 +2314,34 @@ function DeleteProfileDialog({
2215
2314
  setDeleting(false);
2216
2315
  }
2217
2316
  };
2218
- return /* @__PURE__ */ jsx5(Dialog, { open: !!profile, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs5(DialogContent, { children: [
2219
- /* @__PURE__ */ jsxs5(DialogHeader, { children: [
2220
- /* @__PURE__ */ jsx5(DialogTitle, { children: "Delete Profile" }),
2221
- /* @__PURE__ */ jsxs5(DialogDescription, { children: [
2317
+ return /* @__PURE__ */ jsx6(Dialog2, { open: !!profile, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs6(DialogContent2, { children: [
2318
+ /* @__PURE__ */ jsxs6(DialogHeader2, { children: [
2319
+ /* @__PURE__ */ jsx6(DialogTitle2, { children: "Delete Profile" }),
2320
+ /* @__PURE__ */ jsxs6(DialogDescription2, { children: [
2222
2321
  'Are you sure you want to delete "',
2223
2322
  profile?.name,
2224
2323
  '"? This action cannot be undone.'
2225
2324
  ] })
2226
2325
  ] }),
2227
- error && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
2228
- /* @__PURE__ */ jsx5(AlertCircle, { className: "h-4 w-4" }),
2229
- /* @__PURE__ */ jsx5("span", { children: error })
2326
+ error && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] p-3 text-[var(--surface-danger-text)] text-sm", children: [
2327
+ /* @__PURE__ */ jsx6(AlertCircle, { className: "h-4 w-4" }),
2328
+ /* @__PURE__ */ jsx6("span", { children: error })
2230
2329
  ] }),
2231
- profile?.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] p-3 text-sm text-[var(--surface-warning-text)]", children: [
2330
+ profile?.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] p-3 text-sm text-[var(--surface-warning-text)]", children: [
2232
2331
  "This profile has ",
2233
2332
  profile.metrics.total_runs,
2234
2333
  " recorded runs. Deleting it will lose all performance metrics."
2235
2334
  ] }),
2236
- /* @__PURE__ */ jsxs5(DialogFooter, { children: [
2237
- /* @__PURE__ */ jsx5(Button2, { variant: "outline", onClick: onClose, children: "Cancel" }),
2238
- /* @__PURE__ */ jsxs5(
2335
+ /* @__PURE__ */ jsxs6(DialogFooter2, { children: [
2336
+ /* @__PURE__ */ jsx6(Button2, { variant: "outline", onClick: onClose, children: "Cancel" }),
2337
+ /* @__PURE__ */ jsxs6(
2239
2338
  Button2,
2240
2339
  {
2241
2340
  variant: "destructive",
2242
2341
  onClick: handleDelete,
2243
2342
  disabled: deleting,
2244
2343
  children: [
2245
- deleting && /* @__PURE__ */ jsx5(Loader22, { className: "mr-2 h-4 w-4 animate-spin" }),
2344
+ deleting && /* @__PURE__ */ jsx6(Loader23, { className: "mr-2 h-4 w-4 animate-spin" }),
2246
2345
  "Delete Profile"
2247
2346
  ]
2248
2347
  }
@@ -2257,35 +2356,35 @@ function ProfileDetailDialog({
2257
2356
  onDuplicate
2258
2357
  }) {
2259
2358
  if (!profile) return null;
2260
- return /* @__PURE__ */ jsx5(Dialog, { open: !!profile, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs5(DialogContent, { className: "max-w-2xl", children: [
2261
- /* @__PURE__ */ jsxs5(DialogHeader, { children: [
2262
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
2263
- /* @__PURE__ */ jsx5(DialogTitle, { children: profile.name }),
2264
- profile.is_builtin && /* @__PURE__ */ jsx5(Badge2, { variant: "secondary", className: "border-0", children: "Built-in" }),
2265
- profile.is_public && !profile.is_builtin && /* @__PURE__ */ jsx5(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)]", children: "Public" })
2359
+ return /* @__PURE__ */ jsx6(Dialog2, { open: !!profile, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs6(DialogContent2, { className: "max-w-2xl", children: [
2360
+ /* @__PURE__ */ jsxs6(DialogHeader2, { children: [
2361
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
2362
+ /* @__PURE__ */ jsx6(DialogTitle2, { children: profile.name }),
2363
+ profile.is_builtin && /* @__PURE__ */ jsx6(Badge2, { variant: "secondary", className: "border-0", children: "Built-in" }),
2364
+ profile.is_public && !profile.is_builtin && /* @__PURE__ */ jsx6(Badge2, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)]", children: "Public" })
2266
2365
  ] }),
2267
- profile.description && /* @__PURE__ */ jsx5(DialogDescription, { children: profile.description })
2366
+ profile.description && /* @__PURE__ */ jsx6(DialogDescription2, { children: profile.description })
2268
2367
  ] }),
2269
- /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
2270
- /* @__PURE__ */ jsxs5("div", { className: "grid gap-4 sm:grid-cols-2", children: [
2271
- profile.extends && /* @__PURE__ */ jsxs5("div", { children: [
2272
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "Extends" }),
2273
- /* @__PURE__ */ jsx5("p", { className: "text-sm", children: profile.extends })
2368
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
2369
+ /* @__PURE__ */ jsxs6("div", { className: "grid gap-4 sm:grid-cols-2", children: [
2370
+ profile.extends && /* @__PURE__ */ jsxs6("div", { children: [
2371
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "Extends" }),
2372
+ /* @__PURE__ */ jsx6("p", { className: "text-sm", children: profile.extends })
2274
2373
  ] }),
2275
- profile.model && /* @__PURE__ */ jsxs5("div", { children: [
2276
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "Model" }),
2277
- /* @__PURE__ */ jsx5("p", { className: "text-sm", children: profile.model })
2374
+ profile.model && /* @__PURE__ */ jsxs6("div", { children: [
2375
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "Model" }),
2376
+ /* @__PURE__ */ jsx6("p", { className: "text-sm", children: profile.model })
2278
2377
  ] })
2279
2378
  ] }),
2280
- profile.tags && profile.tags.length > 0 && /* @__PURE__ */ jsxs5("div", { children: [
2281
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "Tags" }),
2282
- /* @__PURE__ */ jsx5("div", { className: "mt-1 flex flex-wrap gap-1", children: profile.tags.map((tag) => /* @__PURE__ */ jsx5(Badge2, { variant: "outline", className: "text-xs", children: tag }, tag)) })
2379
+ profile.tags && profile.tags.length > 0 && /* @__PURE__ */ jsxs6("div", { children: [
2380
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "Tags" }),
2381
+ /* @__PURE__ */ jsx6("div", { className: "mt-1 flex flex-wrap gap-1", children: profile.tags.map((tag) => /* @__PURE__ */ jsx6(Badge2, { variant: "outline", className: "text-xs", children: tag }, tag)) })
2283
2382
  ] }),
2284
- profile.system_prompt && /* @__PURE__ */ jsxs5("div", { children: [
2285
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "System Prompt" }),
2286
- /* @__PURE__ */ jsxs5("div", { className: "relative mt-1", children: [
2287
- /* @__PURE__ */ jsx5("pre", { className: "max-h-48 overflow-auto rounded-lg bg-muted p-3 font-mono text-sm", children: profile.system_prompt }),
2288
- /* @__PURE__ */ jsx5(
2383
+ profile.system_prompt && /* @__PURE__ */ jsxs6("div", { children: [
2384
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "System Prompt" }),
2385
+ /* @__PURE__ */ jsxs6("div", { className: "relative mt-1", children: [
2386
+ /* @__PURE__ */ jsx6("pre", { className: "max-h-48 overflow-auto rounded-lg bg-muted p-3 font-mono text-sm", children: profile.system_prompt }),
2387
+ /* @__PURE__ */ jsx6(
2289
2388
  Button2,
2290
2389
  {
2291
2390
  variant: "ghost",
@@ -2293,54 +2392,54 @@ function ProfileDetailDialog({
2293
2392
  className: "absolute top-2 right-2",
2294
2393
  onClick: () => navigator.clipboard.writeText(profile.system_prompt),
2295
2394
  "aria-label": "Copy system prompt",
2296
- children: /* @__PURE__ */ jsx5(Copy, { className: "h-4 w-4" })
2395
+ children: /* @__PURE__ */ jsx6(Copy, { className: "h-4 w-4" })
2297
2396
  }
2298
2397
  )
2299
2398
  ] })
2300
2399
  ] }),
2301
- profile.instructions && profile.instructions.length > 0 && /* @__PURE__ */ jsxs5("div", { children: [
2302
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "Instructions" }),
2303
- /* @__PURE__ */ jsx5("ul", { className: "mt-1 space-y-1", children: profile.instructions.map((inst, i) => /* @__PURE__ */ jsxs5("li", { className: "flex items-start gap-2 text-sm", children: [
2304
- /* @__PURE__ */ jsx5(ChevronRight, { className: "mt-0.5 h-4 w-4 text-muted-foreground" }),
2400
+ profile.instructions && profile.instructions.length > 0 && /* @__PURE__ */ jsxs6("div", { children: [
2401
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "Instructions" }),
2402
+ /* @__PURE__ */ jsx6("ul", { className: "mt-1 space-y-1", children: profile.instructions.map((inst, i) => /* @__PURE__ */ jsxs6("li", { className: "flex items-start gap-2 text-sm", children: [
2403
+ /* @__PURE__ */ jsx6(ChevronRight, { className: "mt-0.5 h-4 w-4 text-muted-foreground" }),
2305
2404
  inst
2306
2405
  ] }, i)) })
2307
2406
  ] }),
2308
- profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-border p-4", children: [
2309
- /* @__PURE__ */ jsx5("label", { className: "font-medium text-muted-foreground text-xs", children: "Performance Metrics" }),
2310
- /* @__PURE__ */ jsxs5("div", { className: "mt-2 grid grid-cols-2 gap-4 sm:grid-cols-4", children: [
2311
- /* @__PURE__ */ jsxs5("div", { children: [
2312
- /* @__PURE__ */ jsx5("p", { className: "font-medium text-2xl", children: profile.metrics.total_runs }),
2313
- /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-xs", children: "Total Runs" })
2407
+ profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border p-4", children: [
2408
+ /* @__PURE__ */ jsx6("label", { className: "font-medium text-muted-foreground text-xs", children: "Performance Metrics" }),
2409
+ /* @__PURE__ */ jsxs6("div", { className: "mt-2 grid grid-cols-2 gap-4 sm:grid-cols-4", children: [
2410
+ /* @__PURE__ */ jsxs6("div", { children: [
2411
+ /* @__PURE__ */ jsx6("p", { className: "font-medium text-2xl", children: profile.metrics.total_runs }),
2412
+ /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground text-xs", children: "Total Runs" })
2314
2413
  ] }),
2315
- /* @__PURE__ */ jsxs5("div", { children: [
2316
- /* @__PURE__ */ jsxs5("p", { className: "font-medium text-2xl", children: [
2414
+ /* @__PURE__ */ jsxs6("div", { children: [
2415
+ /* @__PURE__ */ jsxs6("p", { className: "font-medium text-2xl", children: [
2317
2416
  profile.metrics.success_rate.toFixed(0),
2318
2417
  "%"
2319
2418
  ] }),
2320
- /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-xs", children: "Success Rate" })
2419
+ /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground text-xs", children: "Success Rate" })
2321
2420
  ] }),
2322
- /* @__PURE__ */ jsxs5("div", { children: [
2323
- /* @__PURE__ */ jsxs5("p", { className: "font-medium text-2xl", children: [
2421
+ /* @__PURE__ */ jsxs6("div", { children: [
2422
+ /* @__PURE__ */ jsxs6("p", { className: "font-medium text-2xl", children: [
2324
2423
  (profile.metrics.avg_duration_ms / 1e3).toFixed(1),
2325
2424
  "s"
2326
2425
  ] }),
2327
- /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-xs", children: "Avg Duration" })
2426
+ /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground text-xs", children: "Avg Duration" })
2328
2427
  ] }),
2329
- profile.metrics.avg_tokens_used && /* @__PURE__ */ jsxs5("div", { children: [
2330
- /* @__PURE__ */ jsx5("p", { className: "font-medium text-2xl", children: profile.metrics.avg_tokens_used.toLocaleString() }),
2331
- /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-xs", children: "Avg Tokens" })
2428
+ profile.metrics.avg_tokens_used && /* @__PURE__ */ jsxs6("div", { children: [
2429
+ /* @__PURE__ */ jsx6("p", { className: "font-medium text-2xl", children: profile.metrics.avg_tokens_used.toLocaleString() }),
2430
+ /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground text-xs", children: "Avg Tokens" })
2332
2431
  ] })
2333
2432
  ] })
2334
2433
  ] })
2335
2434
  ] }),
2336
- /* @__PURE__ */ jsxs5(DialogFooter, { children: [
2337
- /* @__PURE__ */ jsx5(Button2, { variant: "outline", onClick: onClose, children: "Close" }),
2338
- onDuplicate && /* @__PURE__ */ jsxs5(Button2, { variant: "outline", onClick: onDuplicate, children: [
2339
- /* @__PURE__ */ jsx5(Copy, { className: "mr-2 h-4 w-4" }),
2435
+ /* @__PURE__ */ jsxs6(DialogFooter2, { children: [
2436
+ /* @__PURE__ */ jsx6(Button2, { variant: "outline", onClick: onClose, children: "Close" }),
2437
+ onDuplicate && /* @__PURE__ */ jsxs6(Button2, { variant: "outline", onClick: onDuplicate, children: [
2438
+ /* @__PURE__ */ jsx6(Copy, { className: "mr-2 h-4 w-4" }),
2340
2439
  "Duplicate"
2341
2440
  ] }),
2342
- onEdit && /* @__PURE__ */ jsxs5(Button2, { onClick: onEdit, children: [
2343
- /* @__PURE__ */ jsx5(Edit2, { className: "mr-2 h-4 w-4" }),
2441
+ onEdit && /* @__PURE__ */ jsxs6(Button2, { onClick: onEdit, children: [
2442
+ /* @__PURE__ */ jsx6(Edit2, { className: "mr-2 h-4 w-4" }),
2344
2443
  "Edit"
2345
2444
  ] })
2346
2445
  ] })
@@ -2348,33 +2447,104 @@ function ProfileDetailDialog({
2348
2447
  }
2349
2448
 
2350
2449
  // src/pages/secrets-page.tsx
2351
- import * as React5 from "react";
2352
- import { Lock, Plus as Plus3, Trash2 as Trash23, Eye, EyeOff, AlertCircle as AlertCircle2, Key, Shield, CheckCircle, Users, ArrowRight } from "lucide-react";
2450
+ import * as React6 from "react";
2451
+ import { Lock, Plus as Plus3, Trash2 as Trash23, Eye, EyeOff, AlertCircle as AlertCircle2, Key, Shield, CheckCircle, Users, ArrowRight, Upload } from "lucide-react";
2353
2452
  import {
2354
- Dialog as Dialog2,
2355
- DialogContent as DialogContent2,
2356
- DialogDescription as DialogDescription2,
2357
- DialogFooter as DialogFooter2,
2358
- DialogHeader as DialogHeader2,
2359
- DialogTitle as DialogTitle2
2453
+ Dialog as Dialog3,
2454
+ DialogContent as DialogContent3,
2455
+ DialogDescription as DialogDescription3,
2456
+ DialogFooter as DialogFooter3,
2457
+ DialogHeader as DialogHeader3,
2458
+ DialogTitle as DialogTitle3
2360
2459
  } from "@tangle-network/ui/primitives";
2361
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
2460
+
2461
+ // src/pages/env-importer.ts
2462
+ var NORMALIZE_RE = /[^A-Z0-9_]/g;
2463
+ function normalizeKey(rawKey) {
2464
+ return rawKey.toUpperCase().replace(NORMALIZE_RE, "_");
2465
+ }
2466
+ function stripMatchingQuotes(value) {
2467
+ if (value.length >= 2) {
2468
+ const quote = value[0];
2469
+ if ((quote === '"' || quote === "'") && value[value.length - 1] === quote) {
2470
+ const inner = value.slice(1, -1);
2471
+ if (!inner.includes(quote)) {
2472
+ return inner;
2473
+ }
2474
+ }
2475
+ }
2476
+ return value;
2477
+ }
2478
+ function parseEnvText(text) {
2479
+ const rows = [];
2480
+ const errors = [];
2481
+ const lines = text.split(/\r?\n/);
2482
+ for (let i = 0; i < lines.length; i++) {
2483
+ const lineNumber = i + 1;
2484
+ const rawLine = lines[i];
2485
+ const trimmed = rawLine.trim();
2486
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
2487
+ let rest = trimmed;
2488
+ const exportMatch = /^export\s+/.exec(rest);
2489
+ if (exportMatch) rest = rest.slice(exportMatch[0].length);
2490
+ const eqIdx = rest.indexOf("=");
2491
+ if (eqIdx === -1) {
2492
+ errors.push({ lineNumber, message: "Missing '=' separator", rawLine });
2493
+ continue;
2494
+ }
2495
+ const rawKey = rest.slice(0, eqIdx).trim();
2496
+ const rawValue = rest.slice(eqIdx + 1).trim();
2497
+ if (rawKey === "") {
2498
+ errors.push({ lineNumber, message: "Missing key before '='", rawLine });
2499
+ continue;
2500
+ }
2501
+ const key = normalizeKey(rawKey);
2502
+ if (!/[A-Z0-9]/.test(key)) {
2503
+ errors.push({
2504
+ lineNumber,
2505
+ message: "Key has no valid characters (letters or digits)",
2506
+ rawLine
2507
+ });
2508
+ continue;
2509
+ }
2510
+ rows.push({
2511
+ key,
2512
+ rawKey,
2513
+ value: stripMatchingQuotes(rawValue),
2514
+ lineNumber
2515
+ });
2516
+ }
2517
+ return { rows, errors };
2518
+ }
2519
+
2520
+ // src/pages/secrets-page.tsx
2521
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
2522
+ var MAX_IMPORT_FILE_BYTES = 256 * 1024;
2362
2523
  function SecretsPage({ apiClient, className, teamSecretsHint }) {
2363
- const [secrets, setSecrets] = React5.useState([]);
2364
- const [loading, setLoading] = React5.useState(true);
2365
- const [error, setError] = React5.useState(null);
2366
- const [isCreateOpen, setIsCreateOpen] = React5.useState(false);
2367
- const [newName, setNewName] = React5.useState("");
2368
- const [newValue, setNewValue] = React5.useState("");
2369
- const [showValue, setShowValue] = React5.useState(false);
2370
- const [isCreating, setIsCreating] = React5.useState(false);
2371
- const [createError, setCreateError] = React5.useState(null);
2372
- const [deleteTarget, setDeleteTarget] = React5.useState(null);
2373
- const [isDeleting, setIsDeleting] = React5.useState(false);
2374
- const apiRef = React5.useRef(apiClient);
2524
+ const [secrets, setSecrets] = React6.useState([]);
2525
+ const [loading, setLoading] = React6.useState(true);
2526
+ const [error, setError] = React6.useState(null);
2527
+ const [isCreateOpen, setIsCreateOpen] = React6.useState(false);
2528
+ const [newName, setNewName] = React6.useState("");
2529
+ const [newValue, setNewValue] = React6.useState("");
2530
+ const [showValue, setShowValue] = React6.useState(false);
2531
+ const [isCreating, setIsCreating] = React6.useState(false);
2532
+ const [createError, setCreateError] = React6.useState(null);
2533
+ const [deleteTarget, setDeleteTarget] = React6.useState(null);
2534
+ const [isDeleting, setIsDeleting] = React6.useState(false);
2535
+ const [isImportOpen, setIsImportOpen] = React6.useState(false);
2536
+ const [importText, setImportText] = React6.useState("");
2537
+ const [importResult, setImportResult] = React6.useState(null);
2538
+ const [rowStatus, setRowStatus] = React6.useState([]);
2539
+ const [rowMessages, setRowMessages] = React6.useState([]);
2540
+ const [isImportSaving, setIsImportSaving] = React6.useState(false);
2541
+ const [showImportValues, setShowImportValues] = React6.useState(false);
2542
+ const [importFileError, setImportFileError] = React6.useState(null);
2543
+ const fileInputRef = React6.useRef(null);
2544
+ const apiRef = React6.useRef(apiClient);
2375
2545
  apiRef.current = apiClient;
2376
- const loadGenRef = React5.useRef(0);
2377
- const loadSecrets = React5.useCallback(async (showSpinner = true) => {
2546
+ const loadGenRef = React6.useRef(0);
2547
+ const loadSecrets = React6.useCallback(async (showSpinner = true) => {
2378
2548
  const gen = ++loadGenRef.current;
2379
2549
  try {
2380
2550
  if (showSpinner) setLoading(true);
@@ -2389,7 +2559,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2389
2559
  if (gen === loadGenRef.current) setLoading(false);
2390
2560
  }
2391
2561
  }, []);
2392
- React5.useEffect(() => {
2562
+ React6.useEffect(() => {
2393
2563
  loadSecrets();
2394
2564
  }, [loadSecrets]);
2395
2565
  const handleCreate = async () => {
@@ -2421,6 +2591,100 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2421
2591
  setIsDeleting(false);
2422
2592
  }
2423
2593
  };
2594
+ const resetImportState = () => {
2595
+ setImportText("");
2596
+ setImportResult(null);
2597
+ setRowStatus([]);
2598
+ setRowMessages([]);
2599
+ setShowImportValues(false);
2600
+ setImportFileError(null);
2601
+ if (fileInputRef.current) fileInputRef.current.value = "";
2602
+ };
2603
+ const runParse = (text) => {
2604
+ const result = parseEnvText(text);
2605
+ setImportResult(result);
2606
+ setRowStatus(new Array(result.rows.length).fill("idle"));
2607
+ setRowMessages(new Array(result.rows.length).fill(""));
2608
+ };
2609
+ const handleParse = () => {
2610
+ runParse(importText);
2611
+ };
2612
+ const handleImportFile = async (file) => {
2613
+ if (!file) return;
2614
+ setImportFileError(null);
2615
+ if (file.size > MAX_IMPORT_FILE_BYTES) {
2616
+ setImportFileError(`File is too large (${Math.round(file.size / 1024)} KiB). Limit is ${MAX_IMPORT_FILE_BYTES / 1024} KiB.`);
2617
+ if (fileInputRef.current) fileInputRef.current.value = "";
2618
+ return;
2619
+ }
2620
+ const text = await file.text();
2621
+ setImportText(text);
2622
+ runParse(text);
2623
+ };
2624
+ const updateRowKey = (index, next) => {
2625
+ setImportResult((prev) => {
2626
+ if (!prev) return prev;
2627
+ const rows = prev.rows.slice();
2628
+ rows[index] = { ...rows[index], key: next.toUpperCase().replace(/[^A-Z0-9_]/g, "_") };
2629
+ return { ...prev, rows };
2630
+ });
2631
+ };
2632
+ const updateRowValue = (index, next) => {
2633
+ setImportResult((prev) => {
2634
+ if (!prev) return prev;
2635
+ const rows = prev.rows.slice();
2636
+ rows[index] = { ...rows[index], value: next };
2637
+ return { ...prev, rows };
2638
+ });
2639
+ };
2640
+ const removeImportRow = (index) => {
2641
+ setImportResult((prev) => {
2642
+ if (!prev) return prev;
2643
+ const rows = prev.rows.slice();
2644
+ rows.splice(index, 1);
2645
+ return { ...prev, rows };
2646
+ });
2647
+ setRowStatus((prev) => {
2648
+ const next = prev.slice();
2649
+ next.splice(index, 1);
2650
+ return next;
2651
+ });
2652
+ setRowMessages((prev) => {
2653
+ const next = prev.slice();
2654
+ next.splice(index, 1);
2655
+ return next;
2656
+ });
2657
+ };
2658
+ const importRows = importResult?.rows ?? [];
2659
+ const hasImportErrors = !!(importResult && importResult.errors.length > 0);
2660
+ const importSaveDisabled = isImportSaving || importRows.length === 0 || hasImportErrors || importRows.some((r) => !r.key || !/[A-Z0-9]/.test(r.key) || !r.value.trim());
2661
+ const handleImportSave = async () => {
2662
+ if (!importResult || importSaveDisabled) return;
2663
+ const rows = importResult.rows;
2664
+ setIsImportSaving(true);
2665
+ const statuses = new Array(rows.length).fill("idle");
2666
+ const messages = new Array(rows.length).fill("");
2667
+ try {
2668
+ for (let i = 0; i < rows.length; i++) {
2669
+ try {
2670
+ await apiRef.current.createSecret(rows[i].key, rows[i].value);
2671
+ statuses[i] = "success";
2672
+ } catch (err) {
2673
+ statuses[i] = "error";
2674
+ messages[i] = err instanceof Error ? err.message : "Failed to create secret";
2675
+ }
2676
+ }
2677
+ setRowStatus(statuses);
2678
+ setRowMessages(messages);
2679
+ await loadSecrets(false);
2680
+ if (statuses.every((s) => s === "success")) {
2681
+ setIsImportOpen(false);
2682
+ resetImportState();
2683
+ }
2684
+ } finally {
2685
+ setIsImportSaving(false);
2686
+ }
2687
+ };
2424
2688
  const formatDate = (dateStr) => {
2425
2689
  try {
2426
2690
  const ts = /^\d+$/.test(dateStr) ? Number(dateStr) : dateStr;
@@ -2431,36 +2695,50 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2431
2695
  return dateStr;
2432
2696
  }
2433
2697
  };
2434
- return /* @__PURE__ */ jsxs6("div", { className: cn("mx-auto w-full max-w-7xl space-y-8", className), children: [
2435
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-4 md:flex-row md:items-end md:justify-between", children: [
2436
- /* @__PURE__ */ jsxs6("div", { children: [
2437
- /* @__PURE__ */ jsx6("h1", { className: "font-display text-3xl font-extrabold tracking-tight text-foreground", children: "Environment Secrets" }),
2438
- /* @__PURE__ */ jsx6("p", { className: "mt-1 text-sm text-muted-foreground", children: "Secrets are securely stored and automatically exposed as environment variables across all your sandboxes." })
2698
+ return /* @__PURE__ */ jsxs7("div", { className: cn("mx-auto w-full max-w-7xl space-y-8", className), children: [
2699
+ /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-4 md:flex-row md:items-end md:justify-between", children: [
2700
+ /* @__PURE__ */ jsxs7("div", { children: [
2701
+ /* @__PURE__ */ jsx7("h1", { className: "font-display text-3xl font-extrabold tracking-tight text-foreground", children: "Environment Secrets" }),
2702
+ /* @__PURE__ */ jsx7("p", { className: "mt-1 text-sm text-muted-foreground", children: "Secrets are securely stored and automatically exposed as environment variables across all your sandboxes." })
2439
2703
  ] }),
2440
- /* @__PURE__ */ jsxs6(
2441
- "button",
2442
- {
2443
- type: "button",
2444
- onClick: () => setIsCreateOpen(true),
2445
- className: "inline-flex items-center gap-2 rounded-lg bg-[var(--btn-primary-bg)] border border-[var(--border-accent,transparent)] px-5 py-2.5 text-sm font-semibold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors active:scale-[0.97]",
2446
- children: [
2447
- /* @__PURE__ */ jsx6(Plus3, { className: "h-4 w-4" }),
2448
- "New Secret"
2449
- ]
2450
- }
2451
- )
2704
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
2705
+ /* @__PURE__ */ jsxs7(
2706
+ "button",
2707
+ {
2708
+ type: "button",
2709
+ onClick: () => setIsImportOpen(true),
2710
+ className: "inline-flex items-center gap-2 rounded-lg border border-border bg-card px-4 py-2.5 text-sm font-semibold text-foreground hover:bg-muted transition-colors active:scale-[0.97]",
2711
+ children: [
2712
+ /* @__PURE__ */ jsx7(Upload, { className: "h-4 w-4" }),
2713
+ "Import .env"
2714
+ ]
2715
+ }
2716
+ ),
2717
+ /* @__PURE__ */ jsxs7(
2718
+ "button",
2719
+ {
2720
+ type: "button",
2721
+ onClick: () => setIsCreateOpen(true),
2722
+ className: "inline-flex items-center gap-2 rounded-lg bg-[var(--btn-primary-bg)] border border-[var(--border-accent,transparent)] px-5 py-2.5 text-sm font-semibold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors active:scale-[0.97]",
2723
+ children: [
2724
+ /* @__PURE__ */ jsx7(Plus3, { className: "h-4 w-4" }),
2725
+ "New Secret"
2726
+ ]
2727
+ }
2728
+ )
2729
+ ] })
2452
2730
  ] }),
2453
- teamSecretsHint && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-[var(--accent-surface-soft)]/40 px-4 py-3", children: [
2454
- /* @__PURE__ */ jsx6(Users, { className: "h-5 w-5 shrink-0 text-[var(--accent-text)]", "aria-hidden": "true" }),
2455
- /* @__PURE__ */ jsxs6("div", { className: "flex-1 text-sm", children: [
2456
- /* @__PURE__ */ jsx6("p", { className: "font-semibold text-foreground", children: "Setting up secrets for a team?" }),
2457
- /* @__PURE__ */ jsxs6("p", { className: "mt-0.5 text-muted-foreground text-xs", children: [
2731
+ teamSecretsHint && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-[var(--accent-surface-soft)]/40 px-4 py-3", children: [
2732
+ /* @__PURE__ */ jsx7(Users, { className: "h-5 w-5 shrink-0 text-[var(--accent-text)]", "aria-hidden": "true" }),
2733
+ /* @__PURE__ */ jsxs7("div", { className: "flex-1 text-sm", children: [
2734
+ /* @__PURE__ */ jsx7("p", { className: "font-semibold text-foreground", children: "Setting up secrets for a team?" }),
2735
+ /* @__PURE__ */ jsxs7("p", { className: "mt-0.5 text-muted-foreground text-xs", children: [
2458
2736
  "Secrets here are ",
2459
- /* @__PURE__ */ jsx6("strong", { children: "personal" }),
2737
+ /* @__PURE__ */ jsx7("strong", { children: "personal" }),
2460
2738
  " \u2014 only available in sandboxes you create. To share credentials with teammates, configure them on the team page instead."
2461
2739
  ] })
2462
2740
  ] }),
2463
- /* @__PURE__ */ jsxs6(
2741
+ /* @__PURE__ */ jsxs7(
2464
2742
  "button",
2465
2743
  {
2466
2744
  type: "button",
@@ -2468,24 +2746,24 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2468
2746
  className: "inline-flex shrink-0 items-center gap-1 rounded-md border border-border bg-card px-3 py-1.5 text-xs font-semibold text-foreground hover:bg-muted transition-colors",
2469
2747
  children: [
2470
2748
  teamSecretsHint.label ?? "Manage team secrets",
2471
- /* @__PURE__ */ jsx6(ArrowRight, { className: "h-3 w-3", "aria-hidden": "true" })
2749
+ /* @__PURE__ */ jsx7(ArrowRight, { className: "h-3 w-3", "aria-hidden": "true" })
2472
2750
  ]
2473
2751
  }
2474
2752
  )
2475
2753
  ] }),
2476
- /* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-4", children: [
2477
- /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
2478
- /* @__PURE__ */ jsx6("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Total Active Secrets" }),
2479
- /* @__PURE__ */ jsx6("div", { className: "mt-2 flex items-baseline gap-2", children: /* @__PURE__ */ jsx6("span", { className: "font-display text-2xl font-extrabold text-foreground", children: secrets.length }) })
2754
+ /* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-4", children: [
2755
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
2756
+ /* @__PURE__ */ jsx7("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Total Active Secrets" }),
2757
+ /* @__PURE__ */ jsx7("div", { className: "mt-2 flex items-baseline gap-2", children: /* @__PURE__ */ jsx7("span", { className: "font-display text-2xl font-extrabold text-foreground", children: secrets.length }) })
2480
2758
  ] }),
2481
- /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
2482
- /* @__PURE__ */ jsx6("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Status" }),
2483
- /* @__PURE__ */ jsxs6("div", { className: "mt-2 flex items-center gap-2", children: [
2484
- /* @__PURE__ */ jsx6(CheckCircle, { className: "h-4 w-4 text-[var(--surface-success-text,#047857)]" }),
2485
- /* @__PURE__ */ jsx6("span", { className: "text-sm font-semibold text-[var(--surface-success-text,#047857)]", children: "Encrypted" })
2759
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
2760
+ /* @__PURE__ */ jsx7("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Status" }),
2761
+ /* @__PURE__ */ jsxs7("div", { className: "mt-2 flex items-center gap-2", children: [
2762
+ /* @__PURE__ */ jsx7(CheckCircle, { className: "h-4 w-4 text-[var(--surface-success-text,#047857)]" }),
2763
+ /* @__PURE__ */ jsx7("span", { className: "text-sm font-semibold text-[var(--surface-success-text,#047857)]", children: "Encrypted" })
2486
2764
  ] })
2487
2765
  ] }),
2488
- /* @__PURE__ */ jsx6(
2766
+ /* @__PURE__ */ jsx7(
2489
2767
  InfoPanel,
2490
2768
  {
2491
2769
  className: "md:col-span-2",
@@ -2495,11 +2773,11 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2495
2773
  }
2496
2774
  )
2497
2775
  ] }),
2498
- error && /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 flex items-center gap-3", children: [
2499
- /* @__PURE__ */ jsx6(AlertCircle2, { className: "h-5 w-5 text-destructive shrink-0" }),
2500
- /* @__PURE__ */ jsx6("p", { className: "text-destructive text-sm font-medium", children: error })
2776
+ error && /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 flex items-center gap-3", children: [
2777
+ /* @__PURE__ */ jsx7(AlertCircle2, { className: "h-5 w-5 text-destructive shrink-0" }),
2778
+ /* @__PURE__ */ jsx7("p", { className: "text-destructive text-sm font-medium", children: error })
2501
2779
  ] }),
2502
- /* @__PURE__ */ jsx6(Dialog2, { open: isCreateOpen, onOpenChange: (open) => {
2780
+ /* @__PURE__ */ jsx7(Dialog3, { open: isCreateOpen, onOpenChange: (open) => {
2503
2781
  if (!open) {
2504
2782
  setIsCreateOpen(false);
2505
2783
  setNewName("");
@@ -2507,12 +2785,12 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2507
2785
  setCreateError(null);
2508
2786
  setShowValue(false);
2509
2787
  }
2510
- }, children: /* @__PURE__ */ jsxs6(DialogContent2, { className: "max-w-md", children: [
2511
- /* @__PURE__ */ jsxs6(DialogHeader2, { children: [
2512
- /* @__PURE__ */ jsx6(DialogTitle2, { children: "Create Secret" }),
2513
- /* @__PURE__ */ jsx6(DialogDescription2, { children: "Secrets are automatically exposed as environment variables across all your new sandboxes." })
2788
+ }, children: /* @__PURE__ */ jsxs7(DialogContent3, { className: "max-w-md", children: [
2789
+ /* @__PURE__ */ jsxs7(DialogHeader3, { children: [
2790
+ /* @__PURE__ */ jsx7(DialogTitle3, { children: "Create Secret" }),
2791
+ /* @__PURE__ */ jsx7(DialogDescription3, { children: "Secrets are automatically exposed as environment variables across all your new sandboxes." })
2514
2792
  ] }),
2515
- /* @__PURE__ */ jsxs6(
2793
+ /* @__PURE__ */ jsxs7(
2516
2794
  "form",
2517
2795
  {
2518
2796
  onSubmit: (e) => {
@@ -2521,9 +2799,9 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2521
2799
  },
2522
2800
  className: "space-y-4",
2523
2801
  children: [
2524
- /* @__PURE__ */ jsxs6("div", { children: [
2525
- /* @__PURE__ */ jsx6("label", { htmlFor: "secret-name", className: "block text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Name" }),
2526
- /* @__PURE__ */ jsx6(
2802
+ /* @__PURE__ */ jsxs7("div", { children: [
2803
+ /* @__PURE__ */ jsx7("label", { htmlFor: "secret-name", className: "block text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Name" }),
2804
+ /* @__PURE__ */ jsx7(
2527
2805
  "input",
2528
2806
  {
2529
2807
  id: "secret-name",
@@ -2537,10 +2815,10 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2537
2815
  }
2538
2816
  )
2539
2817
  ] }),
2540
- /* @__PURE__ */ jsxs6("div", { children: [
2541
- /* @__PURE__ */ jsx6("label", { htmlFor: "secret-value", className: "block text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Value" }),
2542
- /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
2543
- /* @__PURE__ */ jsx6(
2818
+ /* @__PURE__ */ jsxs7("div", { children: [
2819
+ /* @__PURE__ */ jsx7("label", { htmlFor: "secret-value", className: "block text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Value" }),
2820
+ /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
2821
+ /* @__PURE__ */ jsx7(
2544
2822
  "input",
2545
2823
  {
2546
2824
  id: "secret-value",
@@ -2553,26 +2831,26 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2553
2831
  className: "w-full rounded-md border border-border bg-card px-3 py-2.5 pr-10 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
2554
2832
  }
2555
2833
  ),
2556
- /* @__PURE__ */ jsx6(
2834
+ /* @__PURE__ */ jsx7(
2557
2835
  "button",
2558
2836
  {
2559
2837
  type: "button",
2560
2838
  onClick: () => setShowValue(!showValue),
2561
2839
  className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 text-muted-foreground hover:text-foreground",
2562
2840
  "aria-label": showValue ? "Hide value" : "Show value",
2563
- children: showValue ? /* @__PURE__ */ jsx6(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(Eye, { className: "h-4 w-4" })
2841
+ children: showValue ? /* @__PURE__ */ jsx7(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(Eye, { className: "h-4 w-4" })
2564
2842
  }
2565
2843
  )
2566
2844
  ] }),
2567
- /* @__PURE__ */ jsx6("p", { className: "mt-1.5 text-xs text-muted-foreground", children: "This value cannot be retrieved after creation." })
2845
+ /* @__PURE__ */ jsx7("p", { className: "mt-1.5 text-xs text-muted-foreground", children: "This value cannot be retrieved after creation." })
2568
2846
  ] }),
2569
- /* @__PURE__ */ jsx6("button", { type: "submit", className: "hidden", tabIndex: -1, "aria-hidden": "true", children: "Submit" })
2847
+ /* @__PURE__ */ jsx7("button", { type: "submit", className: "hidden", tabIndex: -1, "aria-hidden": "true", children: "Submit" })
2570
2848
  ]
2571
2849
  }
2572
2850
  ),
2573
- createError && /* @__PURE__ */ jsx6("p", { className: "mt-3 text-sm text-destructive", children: createError }),
2574
- /* @__PURE__ */ jsxs6(DialogFooter2, { children: [
2575
- /* @__PURE__ */ jsx6(
2851
+ createError && /* @__PURE__ */ jsx7("p", { className: "mt-3 text-sm text-destructive", children: createError }),
2852
+ /* @__PURE__ */ jsxs7(DialogFooter3, { children: [
2853
+ /* @__PURE__ */ jsx7(
2576
2854
  "button",
2577
2855
  {
2578
2856
  type: "button",
@@ -2586,7 +2864,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2586
2864
  children: "Cancel"
2587
2865
  }
2588
2866
  ),
2589
- /* @__PURE__ */ jsx6(
2867
+ /* @__PURE__ */ jsx7(
2590
2868
  "button",
2591
2869
  {
2592
2870
  type: "button",
@@ -2598,19 +2876,204 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2598
2876
  )
2599
2877
  ] })
2600
2878
  ] }) }),
2601
- /* @__PURE__ */ jsx6(Dialog2, { open: !!deleteTarget, onOpenChange: (open) => {
2879
+ /* @__PURE__ */ jsx7(Dialog3, { open: isImportOpen, onOpenChange: (open) => {
2880
+ if (!open && !isImportSaving) {
2881
+ setIsImportOpen(false);
2882
+ resetImportState();
2883
+ }
2884
+ }, children: /* @__PURE__ */ jsxs7(DialogContent3, { className: "max-w-2xl", children: [
2885
+ /* @__PURE__ */ jsxs7(DialogHeader3, { children: [
2886
+ /* @__PURE__ */ jsx7(DialogTitle3, { children: "Import Secrets" }),
2887
+ /* @__PURE__ */ jsxs7(DialogDescription3, { children: [
2888
+ "Upload a ",
2889
+ /* @__PURE__ */ jsx7("span", { className: "font-mono", children: ".env" }),
2890
+ " file or paste key-value pairs. Review and edit each row before saving."
2891
+ ] })
2892
+ ] }),
2893
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-4", children: [
2894
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
2895
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
2896
+ /* @__PURE__ */ jsx7(
2897
+ "input",
2898
+ {
2899
+ ref: fileInputRef,
2900
+ type: "file",
2901
+ accept: ".env,.txt,text/plain",
2902
+ "aria-label": "Upload .env file",
2903
+ className: "hidden",
2904
+ onChange: (e) => handleImportFile(e.target.files?.[0] ?? null)
2905
+ }
2906
+ ),
2907
+ /* @__PURE__ */ jsxs7(
2908
+ "button",
2909
+ {
2910
+ type: "button",
2911
+ onClick: () => fileInputRef.current?.click(),
2912
+ className: "inline-flex items-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs font-semibold text-foreground hover:bg-muted transition-colors",
2913
+ children: [
2914
+ /* @__PURE__ */ jsx7(Upload, { className: "h-3.5 w-3.5" }),
2915
+ "Choose .env file"
2916
+ ]
2917
+ }
2918
+ ),
2919
+ /* @__PURE__ */ jsx7(
2920
+ "button",
2921
+ {
2922
+ type: "button",
2923
+ onClick: handleParse,
2924
+ disabled: !importText.trim(),
2925
+ className: "rounded-md bg-[var(--btn-primary-bg)] px-3 py-2 text-xs font-bold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors disabled:opacity-50",
2926
+ children: "Parse"
2927
+ }
2928
+ )
2929
+ ] }),
2930
+ /* @__PURE__ */ jsx7(
2931
+ "textarea",
2932
+ {
2933
+ "aria-label": "Paste .env contents",
2934
+ placeholder: "Paste .env contents, e.g.\nAPI_KEY=abc123\n# comment\nexport DB_URL=postgres://localhost",
2935
+ value: importText,
2936
+ onChange: (e) => setImportText(e.target.value),
2937
+ rows: 6,
2938
+ spellCheck: false,
2939
+ className: "w-full rounded-md border border-border bg-card px-3 py-2 font-mono text-xs text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
2940
+ }
2941
+ ),
2942
+ /* @__PURE__ */ jsxs7("p", { className: "text-[11px] text-muted-foreground", children: [
2943
+ "Lines starting with ",
2944
+ /* @__PURE__ */ jsx7("span", { className: "font-mono", children: "#" }),
2945
+ " are comments. Text after ",
2946
+ /* @__PURE__ */ jsx7("span", { className: "font-mono", children: "#" }),
2947
+ " inside a value is preserved."
2948
+ ] }),
2949
+ importFileError && /* @__PURE__ */ jsx7("p", { className: "text-xs text-destructive", role: "alert", children: importFileError })
2950
+ ] }),
2951
+ importResult && importResult.errors.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "rounded-md border border-destructive/30 bg-destructive/10 p-3", children: [
2952
+ /* @__PURE__ */ jsxs7("p", { className: "mb-1 text-xs font-bold uppercase tracking-widest text-destructive", children: [
2953
+ importResult.errors.length,
2954
+ " line",
2955
+ importResult.errors.length !== 1 ? "s" : "",
2956
+ " could not be parsed"
2957
+ ] }),
2958
+ /* @__PURE__ */ jsx7("ul", { className: "space-y-1", children: importResult.errors.map((err) => /* @__PURE__ */ jsxs7("li", { className: "text-xs text-destructive", role: "alert", children: [
2959
+ "Line ",
2960
+ err.lineNumber,
2961
+ ": ",
2962
+ err.message
2963
+ ] }, err.lineNumber)) })
2964
+ ] }),
2965
+ importResult && importResult.rows.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
2966
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
2967
+ /* @__PURE__ */ jsxs7("p", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: [
2968
+ importResult.rows.length,
2969
+ " secret",
2970
+ importResult.rows.length !== 1 ? "s" : "",
2971
+ " ready"
2972
+ ] }),
2973
+ /* @__PURE__ */ jsxs7(
2974
+ "button",
2975
+ {
2976
+ type: "button",
2977
+ onClick: () => setShowImportValues((s) => !s),
2978
+ className: "inline-flex items-center gap-1 text-xs font-semibold text-muted-foreground hover:text-foreground",
2979
+ children: [
2980
+ showImportValues ? /* @__PURE__ */ jsx7(EyeOff, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx7(Eye, { className: "h-3.5 w-3.5" }),
2981
+ showImportValues ? "Hide values" : "Show values"
2982
+ ]
2983
+ }
2984
+ )
2985
+ ] }),
2986
+ /* @__PURE__ */ jsx7("div", { className: "max-h-64 space-y-2 overflow-y-auto", children: importResult.rows.map((row, index) => {
2987
+ const status = rowStatus[index];
2988
+ const message = rowMessages[index];
2989
+ return /* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-2 rounded-md border border-border bg-muted/30 p-2", children: [
2990
+ /* @__PURE__ */ jsx7(
2991
+ "input",
2992
+ {
2993
+ type: "text",
2994
+ "aria-label": `Import row ${index + 1} key`,
2995
+ value: row.key,
2996
+ onChange: (e) => updateRowKey(index, e.target.value),
2997
+ disabled: isImportSaving,
2998
+ className: "w-2/5 rounded border border-border bg-card px-2 py-1.5 font-mono text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:opacity-60"
2999
+ }
3000
+ ),
3001
+ /* @__PURE__ */ jsx7(
3002
+ "input",
3003
+ {
3004
+ type: showImportValues ? "text" : "password",
3005
+ "aria-label": `Import row ${index + 1} value`,
3006
+ value: row.value,
3007
+ onChange: (e) => updateRowValue(index, e.target.value),
3008
+ disabled: isImportSaving,
3009
+ className: "w-2/5 rounded border border-border bg-card px-2 py-1.5 font-mono text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:opacity-60"
3010
+ }
3011
+ ),
3012
+ /* @__PURE__ */ jsxs7("div", { className: "flex w-1/5 flex-col items-end gap-1", children: [
3013
+ status === "success" && /* @__PURE__ */ jsxs7("span", { className: "inline-flex items-center gap-1 text-xs font-semibold text-[var(--surface-success-text,#047857)]", children: [
3014
+ /* @__PURE__ */ jsx7(CheckCircle, { className: "h-3.5 w-3.5" }),
3015
+ " Saved"
3016
+ ] }),
3017
+ status === "error" && /* @__PURE__ */ jsx7("span", { className: "text-right text-xs font-semibold text-destructive", title: message, children: message || "Failed" }),
3018
+ /* @__PURE__ */ jsxs7(
3019
+ "button",
3020
+ {
3021
+ type: "button",
3022
+ onClick: () => removeImportRow(index),
3023
+ disabled: isImportSaving,
3024
+ "aria-label": `Remove import row ${index + 1}`,
3025
+ className: "inline-flex items-center gap-1 text-xs font-semibold text-muted-foreground hover:text-destructive disabled:opacity-50 disabled:pointer-events-none",
3026
+ children: [
3027
+ /* @__PURE__ */ jsx7(Trash23, { className: "h-3.5 w-3.5" }),
3028
+ " Remove"
3029
+ ]
3030
+ }
3031
+ )
3032
+ ] })
3033
+ ] }, `${row.lineNumber}-${index}`);
3034
+ }) })
3035
+ ] }),
3036
+ importResult && importResult.rows.length === 0 && importResult.errors.length === 0 && /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground", children: "No secrets found. Add at least one KEY=value line." })
3037
+ ] }),
3038
+ /* @__PURE__ */ jsxs7(DialogFooter3, { children: [
3039
+ /* @__PURE__ */ jsx7(
3040
+ "button",
3041
+ {
3042
+ type: "button",
3043
+ onClick: () => {
3044
+ setIsImportOpen(false);
3045
+ resetImportState();
3046
+ },
3047
+ disabled: isImportSaving,
3048
+ className: "rounded-md border border-border bg-card px-4 py-2 text-sm font-medium text-foreground hover:bg-muted transition-colors disabled:opacity-50 disabled:pointer-events-none",
3049
+ children: "Cancel"
3050
+ }
3051
+ ),
3052
+ /* @__PURE__ */ jsx7(
3053
+ "button",
3054
+ {
3055
+ type: "button",
3056
+ onClick: handleImportSave,
3057
+ disabled: importSaveDisabled,
3058
+ className: "rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-bold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors disabled:opacity-50 active:scale-[0.97]",
3059
+ children: isImportSaving ? "Importing..." : importRows.length > 0 ? `Import ${importRows.length} secret${importRows.length === 1 ? "" : "s"}` : "Import secrets"
3060
+ }
3061
+ )
3062
+ ] })
3063
+ ] }) }),
3064
+ /* @__PURE__ */ jsx7(Dialog3, { open: !!deleteTarget, onOpenChange: (open) => {
2602
3065
  if (!open) setDeleteTarget(null);
2603
- }, children: /* @__PURE__ */ jsxs6(DialogContent2, { className: "max-w-sm", children: [
2604
- /* @__PURE__ */ jsxs6(DialogHeader2, { children: [
2605
- /* @__PURE__ */ jsx6(DialogTitle2, { children: "Delete Secret?" }),
2606
- /* @__PURE__ */ jsxs6(DialogDescription2, { children: [
3066
+ }, children: /* @__PURE__ */ jsxs7(DialogContent3, { className: "max-w-sm", children: [
3067
+ /* @__PURE__ */ jsxs7(DialogHeader3, { children: [
3068
+ /* @__PURE__ */ jsx7(DialogTitle3, { children: "Delete Secret?" }),
3069
+ /* @__PURE__ */ jsxs7(DialogDescription3, { children: [
2607
3070
  "This will permanently delete ",
2608
- /* @__PURE__ */ jsx6("span", { className: "font-mono font-bold text-foreground", children: deleteTarget }),
3071
+ /* @__PURE__ */ jsx7("span", { className: "font-mono font-bold text-foreground", children: deleteTarget }),
2609
3072
  ". Sandboxes using this secret will lose access to it."
2610
3073
  ] })
2611
3074
  ] }),
2612
- /* @__PURE__ */ jsxs6(DialogFooter2, { children: [
2613
- /* @__PURE__ */ jsx6(
3075
+ /* @__PURE__ */ jsxs7(DialogFooter3, { children: [
3076
+ /* @__PURE__ */ jsx7(
2614
3077
  "button",
2615
3078
  {
2616
3079
  type: "button",
@@ -2619,7 +3082,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2619
3082
  children: "Cancel"
2620
3083
  }
2621
3084
  ),
2622
- /* @__PURE__ */ jsx6(
3085
+ /* @__PURE__ */ jsx7(
2623
3086
  "button",
2624
3087
  {
2625
3088
  type: "button",
@@ -2631,20 +3094,20 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2631
3094
  )
2632
3095
  ] })
2633
3096
  ] }) }),
2634
- /* @__PURE__ */ jsxs6("div", { className: "overflow-hidden rounded-lg border border-border bg-card shadow-[var(--shadow-card)]", children: [
2635
- /* @__PURE__ */ jsxs6("div", { className: "border-b border-border px-6 py-4 flex items-center justify-between", children: [
2636
- /* @__PURE__ */ jsx6("div", { className: "flex gap-6", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "text-xs font-bold uppercase tracking-widest text-foreground border-b-2 border-foreground pb-1", children: "All Secrets" }) }),
2637
- /* @__PURE__ */ jsxs6("span", { className: "text-xs text-muted-foreground font-mono", children: [
3097
+ /* @__PURE__ */ jsxs7("div", { className: "overflow-hidden rounded-lg border border-border bg-card shadow-[var(--shadow-card)]", children: [
3098
+ /* @__PURE__ */ jsxs7("div", { className: "border-b border-border px-6 py-4 flex items-center justify-between", children: [
3099
+ /* @__PURE__ */ jsx7("div", { className: "flex gap-6", children: /* @__PURE__ */ jsx7("button", { type: "button", className: "text-xs font-bold uppercase tracking-widest text-foreground border-b-2 border-foreground pb-1", children: "All Secrets" }) }),
3100
+ /* @__PURE__ */ jsxs7("span", { className: "text-xs text-muted-foreground font-mono", children: [
2638
3101
  secrets.length,
2639
3102
  " secret",
2640
3103
  secrets.length !== 1 ? "s" : ""
2641
3104
  ] })
2642
3105
  ] }),
2643
- loading ? /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx6("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent" }) }) : secrets.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
2644
- /* @__PURE__ */ jsx6(Lock, { className: "h-10 w-10 text-muted-foreground mb-4" }),
2645
- /* @__PURE__ */ jsx6("h3", { className: "text-lg font-semibold text-foreground", children: "No secrets yet" }),
2646
- /* @__PURE__ */ jsx6("p", { className: "mt-1 text-sm text-muted-foreground max-w-sm", children: "Create a secret to inject into your sandboxes." }),
2647
- /* @__PURE__ */ jsxs6(
3106
+ loading ? /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx7("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent" }) }) : secrets.length === 0 ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
3107
+ /* @__PURE__ */ jsx7(Lock, { className: "h-10 w-10 text-muted-foreground mb-4" }),
3108
+ /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-foreground", children: "No secrets yet" }),
3109
+ /* @__PURE__ */ jsx7("p", { className: "mt-1 text-sm text-muted-foreground max-w-sm", children: "Create a secret to inject into your sandboxes." }),
3110
+ /* @__PURE__ */ jsxs7(
2648
3111
  "button",
2649
3112
  {
2650
3113
  type: "button",
@@ -2652,52 +3115,52 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2652
3115
  "aria-label": "Create your first secret",
2653
3116
  className: "mt-6 inline-flex items-center gap-2 rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-semibold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors active:scale-[0.97]",
2654
3117
  children: [
2655
- /* @__PURE__ */ jsx6(Plus3, { className: "h-4 w-4" }),
3118
+ /* @__PURE__ */ jsx7(Plus3, { className: "h-4 w-4" }),
2656
3119
  "New Secret"
2657
3120
  ]
2658
3121
  }
2659
3122
  )
2660
- ] }) : /* @__PURE__ */ jsxs6("table", { className: "w-full text-left border-collapse", children: [
2661
- /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { className: "bg-muted/30 border-b border-border", children: [
2662
- /* @__PURE__ */ jsx6("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Secret Name" }),
2663
- /* @__PURE__ */ jsx6("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Encrypted Value" }),
2664
- /* @__PURE__ */ jsx6("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground text-right", children: "Created" }),
2665
- /* @__PURE__ */ jsx6("th", { className: "px-6 py-4 w-12" })
3123
+ ] }) : /* @__PURE__ */ jsxs7("table", { className: "w-full text-left border-collapse", children: [
3124
+ /* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs7("tr", { className: "bg-muted/30 border-b border-border", children: [
3125
+ /* @__PURE__ */ jsx7("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Secret Name" }),
3126
+ /* @__PURE__ */ jsx7("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Encrypted Value" }),
3127
+ /* @__PURE__ */ jsx7("th", { className: "px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground text-right", children: "Created" }),
3128
+ /* @__PURE__ */ jsx7("th", { className: "px-6 py-4 w-12" })
2666
3129
  ] }) }),
2667
- /* @__PURE__ */ jsx6("tbody", { className: "divide-y divide-border", children: secrets.map((secret) => /* @__PURE__ */ jsxs6("tr", { className: "hover:bg-muted/20 transition-colors", children: [
2668
- /* @__PURE__ */ jsx6("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
2669
- /* @__PURE__ */ jsx6(Key, { className: "h-4 w-4 text-muted-foreground" }),
2670
- /* @__PURE__ */ jsx6("span", { className: "text-sm font-bold font-mono text-foreground", children: secret.name })
3130
+ /* @__PURE__ */ jsx7("tbody", { className: "divide-y divide-border", children: secrets.map((secret) => /* @__PURE__ */ jsxs7("tr", { className: "hover:bg-muted/20 transition-colors", children: [
3131
+ /* @__PURE__ */ jsx7("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
3132
+ /* @__PURE__ */ jsx7(Key, { className: "h-4 w-4 text-muted-foreground" }),
3133
+ /* @__PURE__ */ jsx7("span", { className: "text-sm font-bold font-mono text-foreground", children: secret.name })
2671
3134
  ] }) }),
2672
- /* @__PURE__ */ jsx6("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsx6("code", { className: "text-xs font-mono text-muted-foreground bg-muted px-2 py-1 rounded", children: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }) }),
2673
- /* @__PURE__ */ jsx6("td", { className: "px-6 py-4 text-right", children: /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: formatDate(secret.createdAt) }) }),
2674
- /* @__PURE__ */ jsx6("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsx6(
3135
+ /* @__PURE__ */ jsx7("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsx7("code", { className: "text-xs font-mono text-muted-foreground bg-muted px-2 py-1 rounded", children: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" }) }),
3136
+ /* @__PURE__ */ jsx7("td", { className: "px-6 py-4 text-right", children: /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: formatDate(secret.createdAt) }) }),
3137
+ /* @__PURE__ */ jsx7("td", { className: "px-6 py-4", children: /* @__PURE__ */ jsx7(
2675
3138
  "button",
2676
3139
  {
2677
3140
  type: "button",
2678
3141
  onClick: () => setDeleteTarget(secret.name),
2679
3142
  className: "p-1.5 rounded-md text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors",
2680
3143
  "aria-label": `Delete ${secret.name}`,
2681
- children: /* @__PURE__ */ jsx6(Trash23, { className: "h-4 w-4" })
3144
+ children: /* @__PURE__ */ jsx7(Trash23, { className: "h-4 w-4" })
2682
3145
  }
2683
3146
  ) })
2684
3147
  ] }, secret.name)) })
2685
3148
  ] })
2686
3149
  ] }),
2687
- /* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
2688
- /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
2689
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 mb-3", children: [
2690
- /* @__PURE__ */ jsx6("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx6(Shield, { className: "h-5 w-5" }) }),
2691
- /* @__PURE__ */ jsx6("h3", { className: "text-sm font-bold text-foreground", children: "Encryption Standard" })
3150
+ /* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
3151
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
3152
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3 mb-3", children: [
3153
+ /* @__PURE__ */ jsx7("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx7(Shield, { className: "h-5 w-5" }) }),
3154
+ /* @__PURE__ */ jsx7("h3", { className: "text-sm font-bold text-foreground", children: "Encryption Standard" })
2692
3155
  ] }),
2693
- /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground leading-relaxed", children: "Your secrets are encrypted using AES-256-GCM at rest and TLS 1.3 in transit. Hardware Security Modules manage all root keys." })
3156
+ /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground leading-relaxed", children: "Your secrets are encrypted using AES-256-GCM at rest and TLS 1.3 in transit. Hardware Security Modules manage all root keys." })
2694
3157
  ] }),
2695
- /* @__PURE__ */ jsxs6("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
2696
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 mb-3", children: [
2697
- /* @__PURE__ */ jsx6("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx6(Lock, { className: "h-5 w-5" }) }),
2698
- /* @__PURE__ */ jsx6("h3", { className: "text-sm font-bold text-foreground", children: "Access Policy" })
3158
+ /* @__PURE__ */ jsxs7("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
3159
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3 mb-3", children: [
3160
+ /* @__PURE__ */ jsx7("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx7(Lock, { className: "h-5 w-5" }) }),
3161
+ /* @__PURE__ */ jsx7("h3", { className: "text-sm font-bold text-foreground", children: "Access Policy" })
2699
3162
  ] }),
2700
- /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground leading-relaxed", children: "Secrets are injected at sandbox creation time and are never exposed in logs, API responses, or container metadata." })
3163
+ /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground leading-relaxed", children: "Secrets are injected at sandbox creation time and are never exposed in logs, API responses, or container metadata." })
2701
3164
  ] })
2702
3165
  ] })
2703
3166
  ] });
@@ -2706,18 +3169,18 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
2706
3169
  // src/pages/templates-page.tsx
2707
3170
  import { Layers as Layers2 } from "lucide-react";
2708
3171
  import { Skeleton as Skeleton3 } from "@tangle-network/ui/primitives";
2709
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
3172
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
2710
3173
  function TemplatesPage({ templates, loading = false, onUseTemplate, className }) {
2711
- return /* @__PURE__ */ jsxs7("div", { className: cn("space-y-8", className), children: [
2712
- /* @__PURE__ */ jsxs7("div", { children: [
2713
- /* @__PURE__ */ jsx7("h1", { className: "font-bold text-3xl text-foreground", children: "Templates" }),
2714
- /* @__PURE__ */ jsx7("p", { className: "mt-1 text-muted-foreground", children: "Pre-configured environments to get started quickly" })
3174
+ return /* @__PURE__ */ jsxs8("div", { className: cn("space-y-8", className), children: [
3175
+ /* @__PURE__ */ jsxs8("div", { children: [
3176
+ /* @__PURE__ */ jsx8("h1", { className: "font-bold text-3xl text-foreground", children: "Templates" }),
3177
+ /* @__PURE__ */ jsx8("p", { className: "mt-1 text-muted-foreground", children: "Pre-configured environments to get started quickly" })
2715
3178
  ] }),
2716
- loading || !templates ? /* @__PURE__ */ jsx7("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx7(Skeleton3, { className: "h-56 rounded-2xl" }, i)) }) : templates.length === 0 ? /* @__PURE__ */ jsxs7("div", { className: "rounded-2xl border border-border bg-card p-16 text-center", children: [
2717
- /* @__PURE__ */ jsx7(Layers2, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }),
2718
- /* @__PURE__ */ jsx7("p", { className: "text-sm font-medium text-foreground mb-1", children: "No templates available" }),
2719
- /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: "Check back later for pre-configured environments." })
2720
- ] }) : /* @__PURE__ */ jsx7("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: templates.map((template) => /* @__PURE__ */ jsx7(
3179
+ loading || !templates ? /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx8(Skeleton3, { className: "h-56 rounded-2xl" }, i)) }) : templates.length === 0 ? /* @__PURE__ */ jsxs8("div", { className: "rounded-2xl border border-border bg-card p-16 text-center", children: [
3180
+ /* @__PURE__ */ jsx8(Layers2, { className: "mx-auto mb-3 h-10 w-10 text-muted-foreground" }),
3181
+ /* @__PURE__ */ jsx8("p", { className: "text-sm font-medium text-foreground mb-1", children: "No templates available" }),
3182
+ /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: "Check back later for pre-configured environments." })
3183
+ ] }) : /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3", children: templates.map((template) => /* @__PURE__ */ jsx8(
2721
3184
  TemplateCard,
2722
3185
  {
2723
3186
  template,
@@ -2729,7 +3192,7 @@ function TemplatesPage({ templates, loading = false, onUseTemplate, className })
2729
3192
  }
2730
3193
 
2731
3194
  // src/pages/startup-scripts-page.tsx
2732
- import * as React6 from "react";
3195
+ import * as React7 from "react";
2733
3196
  import {
2734
3197
  Play,
2735
3198
  Plus as Plus4,
@@ -2750,14 +3213,14 @@ import {
2750
3213
  Layers as Layers3
2751
3214
  } from "lucide-react";
2752
3215
  import {
2753
- Dialog as Dialog3,
2754
- DialogContent as DialogContent3,
2755
- DialogDescription as DialogDescription3,
2756
- DialogFooter as DialogFooter3,
2757
- DialogHeader as DialogHeader3,
2758
- DialogTitle as DialogTitle3
3216
+ Dialog as Dialog4,
3217
+ DialogContent as DialogContent4,
3218
+ DialogDescription as DialogDescription4,
3219
+ DialogFooter as DialogFooter4,
3220
+ DialogHeader as DialogHeader4,
3221
+ DialogTitle as DialogTitle4
2759
3222
  } from "@tangle-network/ui/primitives";
2760
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
3223
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2761
3224
  var SCRIPT_TYPE_META = {
2762
3225
  bash: {
2763
3226
  label: "Bash",
@@ -2926,26 +3389,26 @@ function makeDefaultFormData(scriptType = "bash") {
2926
3389
  };
2927
3390
  }
2928
3391
  function StartupScriptsPage({ apiClient, className }) {
2929
- const [scripts, setScripts] = React6.useState([]);
2930
- const [secrets, setSecrets] = React6.useState([]);
2931
- const [environments, setEnvironments] = React6.useState([]);
2932
- const [loading, setLoading] = React6.useState(true);
2933
- const [error, setError] = React6.useState(null);
2934
- const [isDialogOpen, setIsDialogOpen] = React6.useState(false);
2935
- const [dialogStep, setDialogStep] = React6.useState("picker");
2936
- const [transitionDir, setTransitionDir] = React6.useState("forward");
2937
- const [stepKey, setStepKey] = React6.useState(0);
2938
- const [editingScript, setEditingScript] = React6.useState(null);
2939
- const [formData, setFormData] = React6.useState(makeDefaultFormData());
2940
- const [isSaving, setIsSaving] = React6.useState(false);
2941
- const [formError, setFormError] = React6.useState(null);
2942
- const [showConditions, setShowConditions] = React6.useState(false);
2943
- const [deleteTarget, setDeleteTarget] = React6.useState(null);
2944
- const [isDeleting, setIsDeleting] = React6.useState(false);
2945
- const apiRef = React6.useRef(apiClient);
3392
+ const [scripts, setScripts] = React7.useState([]);
3393
+ const [secrets, setSecrets] = React7.useState([]);
3394
+ const [environments, setEnvironments] = React7.useState([]);
3395
+ const [loading, setLoading] = React7.useState(true);
3396
+ const [error, setError] = React7.useState(null);
3397
+ const [isDialogOpen, setIsDialogOpen] = React7.useState(false);
3398
+ const [dialogStep, setDialogStep] = React7.useState("picker");
3399
+ const [transitionDir, setTransitionDir] = React7.useState("forward");
3400
+ const [stepKey, setStepKey] = React7.useState(0);
3401
+ const [editingScript, setEditingScript] = React7.useState(null);
3402
+ const [formData, setFormData] = React7.useState(makeDefaultFormData());
3403
+ const [isSaving, setIsSaving] = React7.useState(false);
3404
+ const [formError, setFormError] = React7.useState(null);
3405
+ const [showConditions, setShowConditions] = React7.useState(false);
3406
+ const [deleteTarget, setDeleteTarget] = React7.useState(null);
3407
+ const [isDeleting, setIsDeleting] = React7.useState(false);
3408
+ const apiRef = React7.useRef(apiClient);
2946
3409
  apiRef.current = apiClient;
2947
- const loadGenRef = React6.useRef(0);
2948
- const loadData = React6.useCallback(async (showSpinner = true) => {
3410
+ const loadGenRef = React7.useRef(0);
3411
+ const loadData = React7.useCallback(async (showSpinner = true) => {
2949
3412
  const gen = ++loadGenRef.current;
2950
3413
  try {
2951
3414
  if (showSpinner) setLoading(true);
@@ -2966,7 +3429,7 @@ function StartupScriptsPage({ apiClient, className }) {
2966
3429
  if (gen === loadGenRef.current) setLoading(false);
2967
3430
  }
2968
3431
  }, []);
2969
- React6.useEffect(() => {
3432
+ React7.useEffect(() => {
2970
3433
  loadData();
2971
3434
  }, [loadData]);
2972
3435
  const openCreate = () => {
@@ -3079,41 +3542,41 @@ function StartupScriptsPage({ apiClient, className }) {
3079
3542
  }));
3080
3543
  };
3081
3544
  const activeCount = scripts.filter((s) => s.enabled).length;
3082
- return /* @__PURE__ */ jsxs8("div", { className: cn("mx-auto w-full max-w-7xl space-y-6", className), children: [
3083
- /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-4 md:flex-row md:items-end md:justify-between", children: [
3084
- /* @__PURE__ */ jsxs8("div", { children: [
3085
- /* @__PURE__ */ jsx8("h1", { className: "font-display text-3xl font-extrabold tracking-tight text-foreground", children: "Startup Scripts" }),
3086
- /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-muted-foreground", children: "Define scripts that run automatically when your sandboxes start. Scripts can access your encrypted secrets." })
3545
+ return /* @__PURE__ */ jsxs9("div", { className: cn("mx-auto w-full max-w-7xl space-y-6", className), children: [
3546
+ /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-4 md:flex-row md:items-end md:justify-between", children: [
3547
+ /* @__PURE__ */ jsxs9("div", { children: [
3548
+ /* @__PURE__ */ jsx9("h1", { className: "font-display text-3xl font-extrabold tracking-tight text-foreground", children: "Startup Scripts" }),
3549
+ /* @__PURE__ */ jsx9("p", { className: "mt-1 text-sm text-muted-foreground", children: "Define scripts that run automatically when your sandboxes start. Scripts can access your encrypted secrets." })
3087
3550
  ] }),
3088
- /* @__PURE__ */ jsxs8(
3551
+ /* @__PURE__ */ jsxs9(
3089
3552
  "button",
3090
3553
  {
3091
3554
  type: "button",
3092
3555
  onClick: openCreate,
3093
3556
  className: "inline-flex items-center gap-2 rounded-lg bg-[var(--btn-primary-bg)] px-4 py-2.5 text-sm font-bold text-[var(--btn-primary-text)] shadow-sm transition-colors hover:bg-[var(--btn-primary-hover)]",
3094
3557
  children: [
3095
- /* @__PURE__ */ jsx8(Plus4, { className: "h-4 w-4" }),
3558
+ /* @__PURE__ */ jsx9(Plus4, { className: "h-4 w-4" }),
3096
3559
  "New Script"
3097
3560
  ]
3098
3561
  }
3099
3562
  )
3100
3563
  ] }),
3101
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-4", children: [
3102
- /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
3103
- /* @__PURE__ */ jsx8("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Total Scripts" }),
3104
- /* @__PURE__ */ jsx8("div", { className: "mt-2 flex items-baseline gap-2", children: /* @__PURE__ */ jsx8("span", { className: "font-display text-2xl font-extrabold text-foreground", children: scripts.length }) })
3564
+ /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-4", children: [
3565
+ /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
3566
+ /* @__PURE__ */ jsx9("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Total Scripts" }),
3567
+ /* @__PURE__ */ jsx9("div", { className: "mt-2 flex items-baseline gap-2", children: /* @__PURE__ */ jsx9("span", { className: "font-display text-2xl font-extrabold text-foreground", children: scripts.length }) })
3105
3568
  ] }),
3106
- /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
3107
- /* @__PURE__ */ jsx8("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Active" }),
3108
- /* @__PURE__ */ jsxs8("div", { className: "mt-2 flex items-baseline gap-2", children: [
3109
- /* @__PURE__ */ jsx8("span", { className: "font-display text-2xl font-extrabold text-foreground", children: activeCount }),
3110
- /* @__PURE__ */ jsxs8("span", { className: "text-xs text-muted-foreground", children: [
3569
+ /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
3570
+ /* @__PURE__ */ jsx9("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Active" }),
3571
+ /* @__PURE__ */ jsxs9("div", { className: "mt-2 flex items-baseline gap-2", children: [
3572
+ /* @__PURE__ */ jsx9("span", { className: "font-display text-2xl font-extrabold text-foreground", children: activeCount }),
3573
+ /* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground", children: [
3111
3574
  "of ",
3112
3575
  scripts.length
3113
3576
  ] })
3114
3577
  ] })
3115
3578
  ] }),
3116
- /* @__PURE__ */ jsx8(
3579
+ /* @__PURE__ */ jsx9(
3117
3580
  InfoPanel,
3118
3581
  {
3119
3582
  className: "md:col-span-2",
@@ -3123,12 +3586,12 @@ function StartupScriptsPage({ apiClient, className }) {
3123
3586
  }
3124
3587
  )
3125
3588
  ] }),
3126
- error && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 rounded-lg border border-destructive/30 bg-destructive/10 p-4", children: [
3127
- /* @__PURE__ */ jsx8(AlertCircle3, { className: "h-5 w-5 shrink-0 text-destructive" }),
3128
- /* @__PURE__ */ jsx8("p", { className: "text-sm font-medium text-destructive", children: error })
3589
+ error && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 rounded-lg border border-destructive/30 bg-destructive/10 p-4", children: [
3590
+ /* @__PURE__ */ jsx9(AlertCircle3, { className: "h-5 w-5 shrink-0 text-destructive" }),
3591
+ /* @__PURE__ */ jsx9("p", { className: "text-sm font-medium text-destructive", children: error })
3129
3592
  ] }),
3130
- /* @__PURE__ */ jsx8(Dialog3, { open: isDialogOpen, onOpenChange: setIsDialogOpen, children: /* @__PURE__ */ jsxs8(DialogContent3, { className: "max-w-2xl max-h-[90vh] overflow-y-auto", children: [
3131
- dialogStep === "picker" && /* @__PURE__ */ jsxs8(
3593
+ /* @__PURE__ */ jsx9(Dialog4, { open: isDialogOpen, onOpenChange: setIsDialogOpen, children: /* @__PURE__ */ jsxs9(DialogContent4, { className: "max-w-2xl max-h-[90vh] overflow-y-auto", children: [
3594
+ dialogStep === "picker" && /* @__PURE__ */ jsxs9(
3132
3595
  "div",
3133
3596
  {
3134
3597
  className: cn(
@@ -3136,14 +3599,14 @@ function StartupScriptsPage({ apiClient, className }) {
3136
3599
  transitionDir === "back" ? "slide-in-from-left-4" : "slide-in-from-right-4"
3137
3600
  ),
3138
3601
  children: [
3139
- /* @__PURE__ */ jsxs8(DialogHeader3, { children: [
3140
- /* @__PURE__ */ jsx8(DialogTitle3, { children: "New Startup Script" }),
3141
- /* @__PURE__ */ jsx8(DialogDescription3, { children: "Start from a template or create a blank script." })
3602
+ /* @__PURE__ */ jsxs9(DialogHeader4, { children: [
3603
+ /* @__PURE__ */ jsx9(DialogTitle4, { children: "New Startup Script" }),
3604
+ /* @__PURE__ */ jsx9(DialogDescription4, { children: "Start from a template or create a blank script." })
3142
3605
  ] }),
3143
- /* @__PURE__ */ jsxs8("div", { className: "space-y-4 py-2", children: [
3144
- /* @__PURE__ */ jsxs8("div", { children: [
3145
- /* @__PURE__ */ jsx8("p", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Blank Script" }),
3146
- /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-2", children: Object.entries(SCRIPT_TYPE_META).map(([type, meta]) => /* @__PURE__ */ jsx8(
3606
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-4 py-2", children: [
3607
+ /* @__PURE__ */ jsxs9("div", { children: [
3608
+ /* @__PURE__ */ jsx9("p", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Blank Script" }),
3609
+ /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-2", children: Object.entries(SCRIPT_TYPE_META).map(([type, meta]) => /* @__PURE__ */ jsx9(
3147
3610
  "button",
3148
3611
  {
3149
3612
  type: "button",
@@ -3154,24 +3617,24 @@ function StartupScriptsPage({ apiClient, className }) {
3154
3617
  type
3155
3618
  )) })
3156
3619
  ] }),
3157
- /* @__PURE__ */ jsxs8("div", { children: [
3158
- /* @__PURE__ */ jsx8("p", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Templates" }),
3159
- /* @__PURE__ */ jsx8("div", { className: "space-y-2", children: SCRIPT_TEMPLATES.map((tmpl) => /* @__PURE__ */ jsxs8(
3620
+ /* @__PURE__ */ jsxs9("div", { children: [
3621
+ /* @__PURE__ */ jsx9("p", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Templates" }),
3622
+ /* @__PURE__ */ jsx9("div", { className: "space-y-2", children: SCRIPT_TEMPLATES.map((tmpl) => /* @__PURE__ */ jsxs9(
3160
3623
  "button",
3161
3624
  {
3162
3625
  type: "button",
3163
3626
  onClick: () => openFromTemplate(tmpl),
3164
3627
  className: "w-full text-left rounded-lg border border-border bg-card p-4 hover:border-primary/30 hover:bg-muted/30 transition-colors group",
3165
3628
  children: [
3166
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between", children: [
3167
- /* @__PURE__ */ jsxs8("div", { children: [
3168
- /* @__PURE__ */ jsx8("h4", { className: "text-sm font-bold text-foreground group-hover:text-primary transition-colors", children: tmpl.name }),
3169
- /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-xs text-muted-foreground", children: tmpl.description })
3629
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
3630
+ /* @__PURE__ */ jsxs9("div", { children: [
3631
+ /* @__PURE__ */ jsx9("h4", { className: "text-sm font-bold text-foreground group-hover:text-primary transition-colors", children: tmpl.name }),
3632
+ /* @__PURE__ */ jsx9("p", { className: "mt-0.5 text-xs text-muted-foreground", children: tmpl.description })
3170
3633
  ] }),
3171
- /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: SCRIPT_TYPE_META[tmpl.scriptType].label })
3634
+ /* @__PURE__ */ jsx9("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: SCRIPT_TYPE_META[tmpl.scriptType].label })
3172
3635
  ] }),
3173
- tmpl.injectSecrets.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-2 flex flex-wrap gap-1", children: tmpl.injectSecrets.map((s) => /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-0.5 rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground", children: [
3174
- /* @__PURE__ */ jsx8(Lock2, { className: "h-2.5 w-2.5" }),
3636
+ tmpl.injectSecrets.length > 0 && /* @__PURE__ */ jsx9("div", { className: "mt-2 flex flex-wrap gap-1", children: tmpl.injectSecrets.map((s) => /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-0.5 rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground", children: [
3637
+ /* @__PURE__ */ jsx9(Lock2, { className: "h-2.5 w-2.5" }),
3175
3638
  s
3176
3639
  ] }, s)) })
3177
3640
  ]
@@ -3184,7 +3647,7 @@ function StartupScriptsPage({ apiClient, className }) {
3184
3647
  },
3185
3648
  `picker-${stepKey}`
3186
3649
  ),
3187
- dialogStep === "form" && /* @__PURE__ */ jsxs8(
3650
+ dialogStep === "form" && /* @__PURE__ */ jsxs9(
3188
3651
  "div",
3189
3652
  {
3190
3653
  className: cn(
@@ -3192,14 +3655,14 @@ function StartupScriptsPage({ apiClient, className }) {
3192
3655
  transitionDir === "forward" ? "slide-in-from-right-4" : "slide-in-from-left-4"
3193
3656
  ),
3194
3657
  children: [
3195
- /* @__PURE__ */ jsxs8(DialogHeader3, { children: [
3196
- /* @__PURE__ */ jsx8(DialogTitle3, { children: editingScript ? "Edit Script" : "Create Startup Script" }),
3197
- /* @__PURE__ */ jsx8(DialogDescription3, { children: editingScript ? "Modify your startup script configuration." : "Define a shell script that runs when sandboxes start. Scripts execute before the AI agent." })
3658
+ /* @__PURE__ */ jsxs9(DialogHeader4, { children: [
3659
+ /* @__PURE__ */ jsx9(DialogTitle4, { children: editingScript ? "Edit Script" : "Create Startup Script" }),
3660
+ /* @__PURE__ */ jsx9(DialogDescription4, { children: editingScript ? "Modify your startup script configuration." : "Define a shell script that runs when sandboxes start. Scripts execute before the AI agent." })
3198
3661
  ] }),
3199
- /* @__PURE__ */ jsxs8("div", { className: "space-y-5 py-2", children: [
3200
- /* @__PURE__ */ jsxs8("div", { children: [
3201
- /* @__PURE__ */ jsx8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Name" }),
3202
- /* @__PURE__ */ jsx8(
3662
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-5 py-2", children: [
3663
+ /* @__PURE__ */ jsxs9("div", { children: [
3664
+ /* @__PURE__ */ jsx9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Name" }),
3665
+ /* @__PURE__ */ jsx9(
3203
3666
  "input",
3204
3667
  {
3205
3668
  type: "text",
@@ -3211,9 +3674,9 @@ function StartupScriptsPage({ apiClient, className }) {
3211
3674
  }
3212
3675
  )
3213
3676
  ] }),
3214
- /* @__PURE__ */ jsxs8("div", { children: [
3215
- /* @__PURE__ */ jsx8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Description" }),
3216
- /* @__PURE__ */ jsx8(
3677
+ /* @__PURE__ */ jsxs9("div", { children: [
3678
+ /* @__PURE__ */ jsx9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Description" }),
3679
+ /* @__PURE__ */ jsx9(
3217
3680
  "input",
3218
3681
  {
3219
3682
  type: "text",
@@ -3225,9 +3688,9 @@ function StartupScriptsPage({ apiClient, className }) {
3225
3688
  }
3226
3689
  )
3227
3690
  ] }),
3228
- /* @__PURE__ */ jsxs8("div", { children: [
3229
- /* @__PURE__ */ jsx8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Language" }),
3230
- /* @__PURE__ */ jsx8("div", { className: "mt-1.5 flex flex-wrap gap-2", children: Object.entries(SCRIPT_TYPE_META).map(([type, meta]) => /* @__PURE__ */ jsx8(
3691
+ /* @__PURE__ */ jsxs9("div", { children: [
3692
+ /* @__PURE__ */ jsx9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Language" }),
3693
+ /* @__PURE__ */ jsx9("div", { className: "mt-1.5 flex flex-wrap gap-2", children: Object.entries(SCRIPT_TYPE_META).map(([type, meta]) => /* @__PURE__ */ jsx9(
3231
3694
  "button",
3232
3695
  {
3233
3696
  type: "button",
@@ -3249,9 +3712,9 @@ function StartupScriptsPage({ apiClient, className }) {
3249
3712
  type
3250
3713
  )) })
3251
3714
  ] }),
3252
- /* @__PURE__ */ jsxs8("div", { children: [
3253
- /* @__PURE__ */ jsx8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Script" }),
3254
- /* @__PURE__ */ jsx8(
3715
+ /* @__PURE__ */ jsxs9("div", { children: [
3716
+ /* @__PURE__ */ jsx9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Script" }),
3717
+ /* @__PURE__ */ jsx9(
3255
3718
  "textarea",
3256
3719
  {
3257
3720
  value: formData.content,
@@ -3261,19 +3724,19 @@ function StartupScriptsPage({ apiClient, className }) {
3261
3724
  className: "mt-1.5 w-full rounded-lg border border-border bg-[var(--depth-1,hsl(var(--muted)))] px-4 py-3 font-mono text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/30 resize-y"
3262
3725
  }
3263
3726
  ),
3264
- /* @__PURE__ */ jsxs8("p", { className: "mt-1 text-xs text-muted-foreground", children: [
3727
+ /* @__PURE__ */ jsxs9("p", { className: "mt-1 text-xs text-muted-foreground", children: [
3265
3728
  SCRIPT_TYPE_META[formData.scriptType].label,
3266
3729
  " script. Injected secrets are available as environment variables (e.g. ",
3267
- /* @__PURE__ */ jsx8("code", { className: "text-primary", children: "$GITHUB_TOKEN" }),
3730
+ /* @__PURE__ */ jsx9("code", { className: "text-primary", children: "$GITHUB_TOKEN" }),
3268
3731
  ")."
3269
3732
  ] })
3270
3733
  ] }),
3271
- secrets.length > 0 && /* @__PURE__ */ jsxs8("div", { children: [
3272
- /* @__PURE__ */ jsx8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Inject Secrets" }),
3273
- /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Select secrets to make available as environment variables." }),
3274
- /* @__PURE__ */ jsx8("div", { className: "mt-2 flex flex-wrap gap-2", children: secrets.map((secret) => {
3734
+ secrets.length > 0 && /* @__PURE__ */ jsxs9("div", { children: [
3735
+ /* @__PURE__ */ jsx9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Inject Secrets" }),
3736
+ /* @__PURE__ */ jsx9("p", { className: "mt-0.5 text-xs text-muted-foreground", children: "Select secrets to make available as environment variables." }),
3737
+ /* @__PURE__ */ jsx9("div", { className: "mt-2 flex flex-wrap gap-2", children: secrets.map((secret) => {
3275
3738
  const selected = formData.injectSecrets.includes(secret.name);
3276
- return /* @__PURE__ */ jsxs8(
3739
+ return /* @__PURE__ */ jsxs9(
3277
3740
  "button",
3278
3741
  {
3279
3742
  type: "button",
@@ -3283,7 +3746,7 @@ function StartupScriptsPage({ apiClient, className }) {
3283
3746
  selected ? "bg-primary/10 border-primary/30 text-primary" : "bg-muted border-border text-muted-foreground hover:border-primary/20"
3284
3747
  ),
3285
3748
  children: [
3286
- /* @__PURE__ */ jsx8(Lock2, { className: "h-3 w-3" }),
3749
+ /* @__PURE__ */ jsx9(Lock2, { className: "h-3 w-3" }),
3287
3750
  secret.name
3288
3751
  ]
3289
3752
  },
@@ -3291,29 +3754,29 @@ function StartupScriptsPage({ apiClient, className }) {
3291
3754
  );
3292
3755
  }) })
3293
3756
  ] }),
3294
- /* @__PURE__ */ jsxs8("div", { children: [
3295
- /* @__PURE__ */ jsxs8(
3757
+ /* @__PURE__ */ jsxs9("div", { children: [
3758
+ /* @__PURE__ */ jsxs9(
3296
3759
  "button",
3297
3760
  {
3298
3761
  type: "button",
3299
3762
  onClick: () => setShowConditions(!showConditions),
3300
3763
  className: "flex items-center gap-2 text-xs font-bold uppercase tracking-widest text-muted-foreground hover:text-foreground transition-colors",
3301
3764
  children: [
3302
- showConditions ? /* @__PURE__ */ jsx8(ChevronUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx8(ChevronDown2, { className: "h-3.5 w-3.5" }),
3765
+ showConditions ? /* @__PURE__ */ jsx9(ChevronUp, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx9(ChevronDown2, { className: "h-3.5 w-3.5" }),
3303
3766
  "Conditions & Execution"
3304
3767
  ]
3305
3768
  }
3306
3769
  ),
3307
- showConditions && /* @__PURE__ */ jsxs8("div", { className: "mt-3 space-y-4 rounded-lg border border-border bg-muted/30 p-4", children: [
3308
- /* @__PURE__ */ jsxs8("div", { children: [
3309
- /* @__PURE__ */ jsxs8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3310
- /* @__PURE__ */ jsx8(Layers3, { className: "h-3.5 w-3.5" }),
3770
+ showConditions && /* @__PURE__ */ jsxs9("div", { className: "mt-3 space-y-4 rounded-lg border border-border bg-muted/30 p-4", children: [
3771
+ /* @__PURE__ */ jsxs9("div", { children: [
3772
+ /* @__PURE__ */ jsxs9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3773
+ /* @__PURE__ */ jsx9(Layers3, { className: "h-3.5 w-3.5" }),
3311
3774
  "Environments"
3312
3775
  ] }),
3313
- /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-xs text-muted-foreground", children: environments.length > 0 ? "Only run for these environments. Leave empty to run for all." : "No templates configured. Script will run for all environments." }),
3314
- environments.length > 0 && /* @__PURE__ */ jsx8("div", { className: "mt-2 flex flex-wrap gap-2", children: environments.map((env) => {
3776
+ /* @__PURE__ */ jsx9("p", { className: "mt-0.5 text-xs text-muted-foreground", children: environments.length > 0 ? "Only run for these environments. Leave empty to run for all." : "No templates configured. Script will run for all environments." }),
3777
+ environments.length > 0 && /* @__PURE__ */ jsx9("div", { className: "mt-2 flex flex-wrap gap-2", children: environments.map((env) => {
3315
3778
  const selected = formData.environments.includes(env.id);
3316
- return /* @__PURE__ */ jsx8(
3779
+ return /* @__PURE__ */ jsx9(
3317
3780
  "button",
3318
3781
  {
3319
3782
  type: "button",
@@ -3328,13 +3791,13 @@ function StartupScriptsPage({ apiClient, className }) {
3328
3791
  );
3329
3792
  }) })
3330
3793
  ] }),
3331
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-2 gap-4", children: [
3332
- /* @__PURE__ */ jsxs8("div", { children: [
3333
- /* @__PURE__ */ jsxs8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3334
- /* @__PURE__ */ jsx8(Cpu2, { className: "h-3.5 w-3.5" }),
3794
+ /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-2 gap-4", children: [
3795
+ /* @__PURE__ */ jsxs9("div", { children: [
3796
+ /* @__PURE__ */ jsxs9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3797
+ /* @__PURE__ */ jsx9(Cpu2, { className: "h-3.5 w-3.5" }),
3335
3798
  "Min CPU Cores"
3336
3799
  ] }),
3337
- /* @__PURE__ */ jsx8(
3800
+ /* @__PURE__ */ jsx9(
3338
3801
  "input",
3339
3802
  {
3340
3803
  type: "number",
@@ -3350,12 +3813,12 @@ function StartupScriptsPage({ apiClient, className }) {
3350
3813
  }
3351
3814
  )
3352
3815
  ] }),
3353
- /* @__PURE__ */ jsxs8("div", { children: [
3354
- /* @__PURE__ */ jsxs8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3355
- /* @__PURE__ */ jsx8(MemoryStick, { className: "h-3.5 w-3.5" }),
3816
+ /* @__PURE__ */ jsxs9("div", { children: [
3817
+ /* @__PURE__ */ jsxs9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3818
+ /* @__PURE__ */ jsx9(MemoryStick, { className: "h-3.5 w-3.5" }),
3356
3819
  "Min RAM (GB)"
3357
3820
  ] }),
3358
- /* @__PURE__ */ jsx8(
3821
+ /* @__PURE__ */ jsx9(
3359
3822
  "input",
3360
3823
  {
3361
3824
  type: "number",
@@ -3372,13 +3835,13 @@ function StartupScriptsPage({ apiClient, className }) {
3372
3835
  )
3373
3836
  ] })
3374
3837
  ] }),
3375
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-2 gap-4", children: [
3376
- /* @__PURE__ */ jsxs8("div", { children: [
3377
- /* @__PURE__ */ jsxs8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3378
- /* @__PURE__ */ jsx8(GripVertical, { className: "h-3.5 w-3.5" }),
3838
+ /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-2 gap-4", children: [
3839
+ /* @__PURE__ */ jsxs9("div", { children: [
3840
+ /* @__PURE__ */ jsxs9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3841
+ /* @__PURE__ */ jsx9(GripVertical, { className: "h-3.5 w-3.5" }),
3379
3842
  "Run Order"
3380
3843
  ] }),
3381
- /* @__PURE__ */ jsx8(
3844
+ /* @__PURE__ */ jsx9(
3382
3845
  "input",
3383
3846
  {
3384
3847
  type: "number",
@@ -3389,14 +3852,14 @@ function StartupScriptsPage({ apiClient, className }) {
3389
3852
  className: "mt-1.5 w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/30"
3390
3853
  }
3391
3854
  ),
3392
- /* @__PURE__ */ jsx8("p", { className: "mt-1 text-xs text-muted-foreground", children: "Lower runs first" })
3855
+ /* @__PURE__ */ jsx9("p", { className: "mt-1 text-xs text-muted-foreground", children: "Lower runs first" })
3393
3856
  ] }),
3394
- /* @__PURE__ */ jsxs8("div", { children: [
3395
- /* @__PURE__ */ jsxs8("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3396
- /* @__PURE__ */ jsx8(Clock, { className: "h-3.5 w-3.5" }),
3857
+ /* @__PURE__ */ jsxs9("div", { children: [
3858
+ /* @__PURE__ */ jsxs9("label", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5", children: [
3859
+ /* @__PURE__ */ jsx9(Clock, { className: "h-3.5 w-3.5" }),
3397
3860
  "Timeout (seconds)"
3398
3861
  ] }),
3399
- /* @__PURE__ */ jsx8(
3862
+ /* @__PURE__ */ jsx9(
3400
3863
  "input",
3401
3864
  {
3402
3865
  type: "number",
@@ -3409,13 +3872,13 @@ function StartupScriptsPage({ apiClient, className }) {
3409
3872
  )
3410
3873
  ] })
3411
3874
  ] }),
3412
- /* @__PURE__ */ jsxs8("div", { className: "space-y-3", children: [
3413
- /* @__PURE__ */ jsxs8("label", { className: "flex items-center justify-between cursor-pointer", children: [
3414
- /* @__PURE__ */ jsxs8("div", { children: [
3415
- /* @__PURE__ */ jsx8("span", { className: "text-sm font-medium text-foreground", children: "Continue on failure" }),
3416
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: "If script fails, continue starting the sandbox" })
3875
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-3", children: [
3876
+ /* @__PURE__ */ jsxs9("label", { className: "flex items-center justify-between cursor-pointer", children: [
3877
+ /* @__PURE__ */ jsxs9("div", { children: [
3878
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-foreground", children: "Continue on failure" }),
3879
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: "If script fails, continue starting the sandbox" })
3417
3880
  ] }),
3418
- /* @__PURE__ */ jsx8(
3881
+ /* @__PURE__ */ jsx9(
3419
3882
  "button",
3420
3883
  {
3421
3884
  type: "button",
@@ -3424,7 +3887,7 @@ function StartupScriptsPage({ apiClient, className }) {
3424
3887
  "relative h-6 w-11 rounded-full transition-colors",
3425
3888
  formData.continueOnFailure ? "bg-primary" : "bg-border"
3426
3889
  ),
3427
- children: /* @__PURE__ */ jsx8(
3890
+ children: /* @__PURE__ */ jsx9(
3428
3891
  "span",
3429
3892
  {
3430
3893
  className: cn(
@@ -3436,12 +3899,12 @@ function StartupScriptsPage({ apiClient, className }) {
3436
3899
  }
3437
3900
  )
3438
3901
  ] }),
3439
- /* @__PURE__ */ jsxs8("label", { className: "flex items-center justify-between cursor-pointer", children: [
3440
- /* @__PURE__ */ jsxs8("div", { children: [
3441
- /* @__PURE__ */ jsx8("span", { className: "text-sm font-medium text-foreground", children: "Run as root" }),
3442
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: "Execute with root privileges instead of the agent user" })
3902
+ /* @__PURE__ */ jsxs9("label", { className: "flex items-center justify-between cursor-pointer", children: [
3903
+ /* @__PURE__ */ jsxs9("div", { children: [
3904
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium text-foreground", children: "Run as root" }),
3905
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: "Execute with root privileges instead of the agent user" })
3443
3906
  ] }),
3444
- /* @__PURE__ */ jsx8(
3907
+ /* @__PURE__ */ jsx9(
3445
3908
  "button",
3446
3909
  {
3447
3910
  type: "button",
@@ -3450,7 +3913,7 @@ function StartupScriptsPage({ apiClient, className }) {
3450
3913
  "relative h-6 w-11 rounded-full transition-colors",
3451
3914
  formData.runAsRoot ? "bg-primary" : "bg-border"
3452
3915
  ),
3453
- children: /* @__PURE__ */ jsx8(
3916
+ children: /* @__PURE__ */ jsx9(
3454
3917
  "span",
3455
3918
  {
3456
3919
  className: cn(
@@ -3465,26 +3928,26 @@ function StartupScriptsPage({ apiClient, className }) {
3465
3928
  ] })
3466
3929
  ] })
3467
3930
  ] }),
3468
- formError && /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/10 p-3", children: [
3469
- /* @__PURE__ */ jsx8(AlertCircle3, { className: "h-4 w-4 text-destructive" }),
3470
- /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: formError })
3931
+ formError && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/10 p-3", children: [
3932
+ /* @__PURE__ */ jsx9(AlertCircle3, { className: "h-4 w-4 text-destructive" }),
3933
+ /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: formError })
3471
3934
  ] })
3472
3935
  ] }),
3473
- /* @__PURE__ */ jsxs8(DialogFooter3, { className: "flex items-center justify-between sm:justify-between", children: [
3474
- /* @__PURE__ */ jsx8("div", { children: !editingScript && /* @__PURE__ */ jsxs8(
3936
+ /* @__PURE__ */ jsxs9(DialogFooter4, { className: "flex items-center justify-between sm:justify-between", children: [
3937
+ /* @__PURE__ */ jsx9("div", { children: !editingScript && /* @__PURE__ */ jsxs9(
3475
3938
  "button",
3476
3939
  {
3477
3940
  type: "button",
3478
3941
  onClick: () => goToStep("picker"),
3479
3942
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
3480
3943
  children: [
3481
- /* @__PURE__ */ jsx8("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("path", { d: "m15 18-6-6 6-6" }) }),
3944
+ /* @__PURE__ */ jsx9("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx9("path", { d: "m15 18-6-6 6-6" }) }),
3482
3945
  "Back"
3483
3946
  ]
3484
3947
  }
3485
3948
  ) }),
3486
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
3487
- /* @__PURE__ */ jsx8(
3949
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
3950
+ /* @__PURE__ */ jsx9(
3488
3951
  "button",
3489
3952
  {
3490
3953
  type: "button",
@@ -3493,7 +3956,7 @@ function StartupScriptsPage({ apiClient, className }) {
3493
3956
  children: "Cancel"
3494
3957
  }
3495
3958
  ),
3496
- /* @__PURE__ */ jsx8(
3959
+ /* @__PURE__ */ jsx9(
3497
3960
  "button",
3498
3961
  {
3499
3962
  type: "button",
@@ -3510,17 +3973,17 @@ function StartupScriptsPage({ apiClient, className }) {
3510
3973
  `form-${stepKey}`
3511
3974
  )
3512
3975
  ] }) }),
3513
- /* @__PURE__ */ jsx8(Dialog3, { open: !!deleteTarget, onOpenChange: () => setDeleteTarget(null), children: /* @__PURE__ */ jsxs8(DialogContent3, { className: "max-w-md", children: [
3514
- /* @__PURE__ */ jsxs8(DialogHeader3, { children: [
3515
- /* @__PURE__ */ jsx8(DialogTitle3, { children: "Delete Startup Script" }),
3516
- /* @__PURE__ */ jsxs8(DialogDescription3, { children: [
3976
+ /* @__PURE__ */ jsx9(Dialog4, { open: !!deleteTarget, onOpenChange: () => setDeleteTarget(null), children: /* @__PURE__ */ jsxs9(DialogContent4, { className: "max-w-md", children: [
3977
+ /* @__PURE__ */ jsxs9(DialogHeader4, { children: [
3978
+ /* @__PURE__ */ jsx9(DialogTitle4, { children: "Delete Startup Script" }),
3979
+ /* @__PURE__ */ jsxs9(DialogDescription4, { children: [
3517
3980
  "Are you sure you want to delete \u201C",
3518
3981
  deleteTarget?.name,
3519
3982
  "\u201D? This action cannot be undone."
3520
3983
  ] })
3521
3984
  ] }),
3522
- /* @__PURE__ */ jsxs8(DialogFooter3, { children: [
3523
- /* @__PURE__ */ jsx8(
3985
+ /* @__PURE__ */ jsxs9(DialogFooter4, { children: [
3986
+ /* @__PURE__ */ jsx9(
3524
3987
  "button",
3525
3988
  {
3526
3989
  type: "button",
@@ -3529,7 +3992,7 @@ function StartupScriptsPage({ apiClient, className }) {
3529
3992
  children: "Cancel"
3530
3993
  }
3531
3994
  ),
3532
- /* @__PURE__ */ jsx8(
3995
+ /* @__PURE__ */ jsx9(
3533
3996
  "button",
3534
3997
  {
3535
3998
  type: "button",
@@ -3541,20 +4004,20 @@ function StartupScriptsPage({ apiClient, className }) {
3541
4004
  )
3542
4005
  ] })
3543
4006
  ] }) }),
3544
- /* @__PURE__ */ jsxs8("div", { className: "overflow-hidden rounded-lg border border-border bg-card shadow-[var(--shadow-card)]", children: [
3545
- /* @__PURE__ */ jsxs8("div", { className: "border-b border-border px-6 py-4 flex items-center justify-between", children: [
3546
- /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx8("button", { className: "text-xs font-bold uppercase tracking-widest text-foreground", children: "All Scripts" }) }),
3547
- /* @__PURE__ */ jsxs8("span", { className: "text-xs text-muted-foreground font-mono", children: [
4007
+ /* @__PURE__ */ jsxs9("div", { className: "overflow-hidden rounded-lg border border-border bg-card shadow-[var(--shadow-card)]", children: [
4008
+ /* @__PURE__ */ jsxs9("div", { className: "border-b border-border px-6 py-4 flex items-center justify-between", children: [
4009
+ /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx9("button", { className: "text-xs font-bold uppercase tracking-widest text-foreground", children: "All Scripts" }) }),
4010
+ /* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground font-mono", children: [
3548
4011
  scripts.length,
3549
4012
  " script",
3550
4013
  scripts.length !== 1 ? "s" : ""
3551
4014
  ] })
3552
4015
  ] }),
3553
- loading ? /* @__PURE__ */ jsx8("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx8("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : scripts.length === 0 ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
3554
- /* @__PURE__ */ jsx8(Terminal, { className: "h-10 w-10 text-muted-foreground mb-4" }),
3555
- /* @__PURE__ */ jsx8("h3", { className: "text-lg font-semibold text-foreground", children: "No startup scripts yet" }),
3556
- /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-muted-foreground max-w-sm", children: "Create a script to run automatically when your sandboxes start." }),
3557
- /* @__PURE__ */ jsxs8(
4016
+ loading ? /* @__PURE__ */ jsx9("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx9("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : scripts.length === 0 ? /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [
4017
+ /* @__PURE__ */ jsx9(Terminal, { className: "h-10 w-10 text-muted-foreground mb-4" }),
4018
+ /* @__PURE__ */ jsx9("h3", { className: "text-lg font-semibold text-foreground", children: "No startup scripts yet" }),
4019
+ /* @__PURE__ */ jsx9("p", { className: "mt-1 text-sm text-muted-foreground max-w-sm", children: "Create a script to run automatically when your sandboxes start." }),
4020
+ /* @__PURE__ */ jsxs9(
3558
4021
  "button",
3559
4022
  {
3560
4023
  type: "button",
@@ -3562,12 +4025,12 @@ function StartupScriptsPage({ apiClient, className }) {
3562
4025
  "aria-label": "Create your first startup script",
3563
4026
  className: "mt-4 inline-flex items-center gap-2 rounded-lg bg-[var(--btn-primary-bg)] px-4 py-2.5 text-sm font-bold text-[var(--btn-primary-text)] shadow-sm transition-colors hover:bg-[var(--btn-primary-hover)]",
3564
4027
  children: [
3565
- /* @__PURE__ */ jsx8(Plus4, { className: "h-4 w-4" }),
4028
+ /* @__PURE__ */ jsx9(Plus4, { className: "h-4 w-4" }),
3566
4029
  "New Script"
3567
4030
  ]
3568
4031
  }
3569
4032
  )
3570
- ] }) : /* @__PURE__ */ jsx8("div", { className: "divide-y divide-border", children: scripts.map((script) => /* @__PURE__ */ jsxs8(
4033
+ ] }) : /* @__PURE__ */ jsx9("div", { className: "divide-y divide-border", children: scripts.map((script) => /* @__PURE__ */ jsxs9(
3571
4034
  "div",
3572
4035
  {
3573
4036
  className: cn(
@@ -3575,7 +4038,7 @@ function StartupScriptsPage({ apiClient, className }) {
3575
4038
  !script.enabled && "opacity-60"
3576
4039
  ),
3577
4040
  children: [
3578
- /* @__PURE__ */ jsx8(
4041
+ /* @__PURE__ */ jsx9(
3579
4042
  "button",
3580
4043
  {
3581
4044
  type: "button",
@@ -3585,53 +4048,53 @@ function StartupScriptsPage({ apiClient, className }) {
3585
4048
  "flex h-8 w-8 shrink-0 items-center justify-center rounded-full transition-colors",
3586
4049
  script.enabled ? "bg-[var(--surface-success-bg,hsl(142 76% 90%))] text-[var(--surface-success-text,hsl(142 76% 36%))]" : "bg-muted text-muted-foreground"
3587
4050
  ),
3588
- children: script.enabled ? /* @__PURE__ */ jsx8(Power, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx8(PowerOff, { className: "h-4 w-4" })
4051
+ children: script.enabled ? /* @__PURE__ */ jsx9(Power, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx9(PowerOff, { className: "h-4 w-4" })
3589
4052
  }
3590
4053
  ),
3591
- /* @__PURE__ */ jsxs8("div", { className: "flex-1 min-w-0", children: [
3592
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
3593
- /* @__PURE__ */ jsx8("h4", { className: "text-sm font-bold text-foreground truncate", children: script.name }),
3594
- /* @__PURE__ */ jsx8("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: SCRIPT_TYPE_META[script.scriptType ?? "bash"].label }),
3595
- script.runOrder !== 100 && /* @__PURE__ */ jsxs8("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: [
4054
+ /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
4055
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
4056
+ /* @__PURE__ */ jsx9("h4", { className: "text-sm font-bold text-foreground truncate", children: script.name }),
4057
+ /* @__PURE__ */ jsx9("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: SCRIPT_TYPE_META[script.scriptType ?? "bash"].label }),
4058
+ script.runOrder !== 100 && /* @__PURE__ */ jsxs9("span", { className: "text-[10px] font-mono text-muted-foreground bg-muted rounded px-1.5 py-0.5", children: [
3596
4059
  "#",
3597
4060
  script.runOrder
3598
4061
  ] })
3599
4062
  ] }),
3600
- script.description && /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-xs text-muted-foreground truncate", children: script.description }),
3601
- /* @__PURE__ */ jsxs8("div", { className: "mt-1.5 flex flex-wrap gap-1.5", children: [
3602
- script.environments.map((env) => /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-medium text-primary", children: env }, env)),
3603
- script.injectSecrets.map((s) => /* @__PURE__ */ jsxs8("span", { className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground flex items-center gap-0.5", children: [
3604
- /* @__PURE__ */ jsx8(Lock2, { className: "h-2.5 w-2.5" }),
4063
+ script.description && /* @__PURE__ */ jsx9("p", { className: "mt-0.5 text-xs text-muted-foreground truncate", children: script.description }),
4064
+ /* @__PURE__ */ jsxs9("div", { className: "mt-1.5 flex flex-wrap gap-1.5", children: [
4065
+ script.environments.map((env) => /* @__PURE__ */ jsx9("span", { className: "rounded-full bg-primary/10 px-2 py-0.5 text-[10px] font-medium text-primary", children: env }, env)),
4066
+ script.injectSecrets.map((s) => /* @__PURE__ */ jsxs9("span", { className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground flex items-center gap-0.5", children: [
4067
+ /* @__PURE__ */ jsx9(Lock2, { className: "h-2.5 w-2.5" }),
3605
4068
  s
3606
4069
  ] }, s)),
3607
- script.continueOnFailure && /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-amber-500/10 px-2 py-0.5 text-[10px] font-medium text-amber-600", children: "soft fail" }),
3608
- script.runAsRoot && /* @__PURE__ */ jsx8("span", { className: "rounded-full bg-destructive/10 px-2 py-0.5 text-[10px] font-medium text-destructive", children: "root" })
4070
+ script.continueOnFailure && /* @__PURE__ */ jsx9("span", { className: "rounded-full bg-amber-500/10 px-2 py-0.5 text-[10px] font-medium text-amber-600", children: "soft fail" }),
4071
+ script.runAsRoot && /* @__PURE__ */ jsx9("span", { className: "rounded-full bg-destructive/10 px-2 py-0.5 text-[10px] font-medium text-destructive", children: "root" })
3609
4072
  ] })
3610
4073
  ] }),
3611
- /* @__PURE__ */ jsxs8("div", { className: "hidden md:flex items-center gap-1 text-xs text-muted-foreground", children: [
3612
- /* @__PURE__ */ jsx8(Clock, { className: "h-3.5 w-3.5" }),
4074
+ /* @__PURE__ */ jsxs9("div", { className: "hidden md:flex items-center gap-1 text-xs text-muted-foreground", children: [
4075
+ /* @__PURE__ */ jsx9(Clock, { className: "h-3.5 w-3.5" }),
3613
4076
  script.timeoutSeconds,
3614
4077
  "s"
3615
4078
  ] }),
3616
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1 sm:opacity-0 sm:group-hover:opacity-100 sm:focus-within:opacity-100 transition-opacity", children: [
3617
- /* @__PURE__ */ jsx8(
4079
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1 sm:opacity-0 sm:group-hover:opacity-100 sm:focus-within:opacity-100 transition-opacity", children: [
4080
+ /* @__PURE__ */ jsx9(
3618
4081
  "button",
3619
4082
  {
3620
4083
  type: "button",
3621
4084
  onClick: () => openEdit(script),
3622
4085
  className: "rounded-md p-2 text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
3623
4086
  "aria-label": `Edit ${script.name}`,
3624
- children: /* @__PURE__ */ jsx8(Pencil, { className: "h-4 w-4" })
4087
+ children: /* @__PURE__ */ jsx9(Pencil, { className: "h-4 w-4" })
3625
4088
  }
3626
4089
  ),
3627
- /* @__PURE__ */ jsx8(
4090
+ /* @__PURE__ */ jsx9(
3628
4091
  "button",
3629
4092
  {
3630
4093
  type: "button",
3631
4094
  onClick: () => setDeleteTarget(script),
3632
4095
  className: "rounded-md p-2 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors",
3633
4096
  "aria-label": `Delete ${script.name}`,
3634
- children: /* @__PURE__ */ jsx8(Trash24, { className: "h-4 w-4" })
4097
+ children: /* @__PURE__ */ jsx9(Trash24, { className: "h-4 w-4" })
3635
4098
  }
3636
4099
  )
3637
4100
  ] })
@@ -3640,20 +4103,20 @@ function StartupScriptsPage({ apiClient, className }) {
3640
4103
  script.id
3641
4104
  )) })
3642
4105
  ] }),
3643
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
3644
- /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
3645
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 mb-3", children: [
3646
- /* @__PURE__ */ jsx8("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx8(Play, { className: "h-5 w-5" }) }),
3647
- /* @__PURE__ */ jsx8("h3", { className: "text-sm font-bold text-foreground", children: "How Scripts Run" })
4106
+ /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [
4107
+ /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
4108
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 mb-3", children: [
4109
+ /* @__PURE__ */ jsx9("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx9(Play, { className: "h-5 w-5" }) }),
4110
+ /* @__PURE__ */ jsx9("h3", { className: "text-sm font-bold text-foreground", children: "How Scripts Run" })
3648
4111
  ] }),
3649
- /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: 'Scripts execute in order after the container starts but before the AI agent. They run as bash scripts with full access to mounted tools (Nix profile) and workspace. Failed scripts abort sandbox creation unless "continue on failure" is enabled.' })
4112
+ /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: 'Scripts execute in order after the container starts but before the AI agent. They run as bash scripts with full access to mounted tools (Nix profile) and workspace. Failed scripts abort sandbox creation unless "continue on failure" is enabled.' })
3650
4113
  ] }),
3651
- /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
3652
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 mb-3", children: [
3653
- /* @__PURE__ */ jsx8("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx8(Shield2, { className: "h-5 w-5" }) }),
3654
- /* @__PURE__ */ jsx8("h3", { className: "text-sm font-bold text-foreground", children: "Security & Secrets" })
4114
+ /* @__PURE__ */ jsxs9("div", { className: "rounded-lg border border-border bg-card p-6 shadow-[var(--shadow-card)]", children: [
4115
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 mb-3", children: [
4116
+ /* @__PURE__ */ jsx9("div", { className: "flex h-9 w-9 items-center justify-center rounded-md bg-[var(--brand-primary,hsl(var(--primary)))] text-[var(--btn-primary-text)]", children: /* @__PURE__ */ jsx9(Shield2, { className: "h-5 w-5" }) }),
4117
+ /* @__PURE__ */ jsx9("h3", { className: "text-sm font-bold text-foreground", children: "Security & Secrets" })
3655
4118
  ] }),
3656
- /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: "Selected secrets are injected as environment variables at execution time. Secret values are never stored in the script itself \u2014 they are decrypted and injected only when the sandbox starts. Scripts can use conditions to restrict execution to specific environments or resource tiers." })
4119
+ /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "Selected secrets are injected as environment variables at execution time. Secret values are never stored in the script itself \u2014 they are decrypted and injected only when the sandbox starts. Scripts can use conditions to restrict execution to specific environments or resource tiers." })
3657
4120
  ] })
3658
4121
  ] })
3659
4122
  ] });