@tangle-network/sandbox-ui 0.10.3 → 0.10.5
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/{chunk-D4CZWJCD.js → chunk-36QY2W5G.js} +187 -90
- package/dist/{chunk-OHPW55EV.js → chunk-QMU2PWOU.js} +3 -1
- package/dist/{chunk-7LBHRASD.js → chunk-Z5PSS3VD.js} +127 -58
- package/dist/dashboard.d.ts +2 -2
- package/dist/dashboard.js +7 -3
- package/dist/globals.css +27 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/pages.d.ts +16 -2
- package/dist/pages.js +552 -187
- package/dist/primitives.d.ts +48 -296
- package/dist/primitives.js +3 -1
- package/dist/sidebar-drop-zone-tDBsuOH5.d.ts +301 -0
- package/dist/styles.css +27 -0
- package/dist/{usage-chart-SSiOgeQI.d.ts → usage-chart-CPTcNlGs.d.ts} +8 -1
- package/dist/{variant-list-DHP2OXFE.d.ts → variant-list-DAhiR-7S.d.ts} +14 -1
- package/package.json +1 -1
package/dist/pages.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
BillingDashboard,
|
|
25
25
|
PricingPage,
|
|
26
26
|
UsageChart
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-QMU2PWOU.js";
|
|
28
28
|
import {
|
|
29
29
|
Skeleton,
|
|
30
30
|
SkeletonCard
|
|
@@ -298,20 +298,65 @@ function BillingPage({
|
|
|
298
298
|
|
|
299
299
|
// src/pages/provisioning-wizard.tsx
|
|
300
300
|
import * as React2 from "react";
|
|
301
|
-
import {
|
|
301
|
+
import {
|
|
302
|
+
ArrowLeft,
|
|
303
|
+
Layers,
|
|
304
|
+
Cpu,
|
|
305
|
+
Bot,
|
|
306
|
+
Info,
|
|
307
|
+
Loader2,
|
|
308
|
+
Settings,
|
|
309
|
+
Plus,
|
|
310
|
+
Trash2,
|
|
311
|
+
Check
|
|
312
|
+
} from "lucide-react";
|
|
302
313
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
303
|
-
var VALID_DRIVERS = /* @__PURE__ */ new Set([
|
|
314
|
+
var VALID_DRIVERS = /* @__PURE__ */ new Set([
|
|
315
|
+
"docker",
|
|
316
|
+
"firecracker",
|
|
317
|
+
"tangle"
|
|
318
|
+
]);
|
|
304
319
|
var DEFAULT_MODEL_OPTIONS = [
|
|
305
320
|
{ value: "claude-sonnet", label: "Claude Sonnet 4.6 (Highly Capable)" }
|
|
306
321
|
];
|
|
307
322
|
var DEFAULT_MODEL_TIER = DEFAULT_MODEL_OPTIONS[0]?.value ?? "claude-sonnet";
|
|
308
323
|
var STACK_DISPLAY = {
|
|
309
|
-
universal: {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
324
|
+
universal: {
|
|
325
|
+
name: "Default",
|
|
326
|
+
abbr: "D",
|
|
327
|
+
color: "violet",
|
|
328
|
+
textClass: "text-[var(--surface-violet-text)]"
|
|
329
|
+
},
|
|
330
|
+
ethereum: {
|
|
331
|
+
name: "Ethereum",
|
|
332
|
+
abbr: "\u039E",
|
|
333
|
+
color: "blue",
|
|
334
|
+
textClass: "text-[var(--surface-info-text)]"
|
|
335
|
+
},
|
|
336
|
+
solana: {
|
|
337
|
+
name: "Solana",
|
|
338
|
+
abbr: "S",
|
|
339
|
+
color: "green",
|
|
340
|
+
textClass: "text-[var(--surface-success-text)]"
|
|
341
|
+
},
|
|
342
|
+
tangle: {
|
|
343
|
+
name: "Tangle",
|
|
344
|
+
abbr: "T",
|
|
345
|
+
color: "purple",
|
|
346
|
+
textClass: "text-[var(--surface-violet-text)]"
|
|
347
|
+
},
|
|
348
|
+
"ai-sdk": {
|
|
349
|
+
name: "AI SDK",
|
|
350
|
+
abbr: "AI",
|
|
351
|
+
color: "teal",
|
|
352
|
+
textClass: "text-[var(--surface-teal-text)]"
|
|
353
|
+
},
|
|
354
|
+
rust: {
|
|
355
|
+
name: "Rust",
|
|
356
|
+
abbr: "Rs",
|
|
357
|
+
color: "orange",
|
|
358
|
+
textClass: "text-[var(--surface-orange-text)]"
|
|
359
|
+
}
|
|
315
360
|
};
|
|
316
361
|
function resolveEnvironment(env) {
|
|
317
362
|
if (env.id.startsWith("template:")) {
|
|
@@ -338,9 +383,27 @@ function resolveEnvironment(env) {
|
|
|
338
383
|
};
|
|
339
384
|
}
|
|
340
385
|
var defaultEnvironments = [
|
|
341
|
-
{
|
|
342
|
-
|
|
343
|
-
|
|
386
|
+
{
|
|
387
|
+
id: "node",
|
|
388
|
+
name: "Node.js",
|
|
389
|
+
description: "v20.x LTS with optimized runtime for asynchronous event-driven agents.",
|
|
390
|
+
icon: /* @__PURE__ */ jsx2("span", { className: "text-[var(--code-success)] text-2xl font-bold", children: "N" }),
|
|
391
|
+
color: "green"
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: "python",
|
|
395
|
+
name: "Python",
|
|
396
|
+
description: "v3.11 pre-installed with PyTorch and common data science libraries.",
|
|
397
|
+
icon: /* @__PURE__ */ jsx2("span", { className: "text-sky-400 text-2xl font-bold", children: "Py" }),
|
|
398
|
+
color: "blue"
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
id: "ubuntu",
|
|
402
|
+
name: "Ubuntu",
|
|
403
|
+
description: "Full 22.04 LTS terminal access for custom containerized workloads.",
|
|
404
|
+
icon: /* @__PURE__ */ jsx2("span", { className: "text-orange-400 text-2xl font-bold", children: "U" }),
|
|
405
|
+
color: "orange"
|
|
406
|
+
}
|
|
344
407
|
];
|
|
345
408
|
var CPU_MIN = 0.5;
|
|
346
409
|
var CPU_MAX = 8;
|
|
@@ -354,17 +417,29 @@ var DEFAULT_PRICING_RATES = {
|
|
|
354
417
|
diskPerGbHr: 11e-4,
|
|
355
418
|
minChargePerHr: void 0
|
|
356
419
|
};
|
|
420
|
+
function formatPerSecondValue(hourlyValue) {
|
|
421
|
+
return (hourlyValue / 3600).toFixed(8);
|
|
422
|
+
}
|
|
357
423
|
var RAW_PRESETS = [
|
|
358
424
|
{ name: "Lightweight", cpu: 2, ram: 4, storage: 50 },
|
|
359
425
|
{ name: "Standard", cpu: 4, ram: 16, storage: 128 },
|
|
360
426
|
{ name: "Performance", cpu: 8, ram: 32, storage: 256 }
|
|
361
427
|
];
|
|
362
|
-
function
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
428
|
+
function computeHourlyCost(cpu, ram, storage, rates) {
|
|
429
|
+
const compute = cpu * rates.cpuPerHr;
|
|
430
|
+
const memory = ram * rates.ramPerGbHr;
|
|
431
|
+
const storageCost = storage * rates.diskPerGbHr;
|
|
432
|
+
const lineSum = compute + memory + storageCost;
|
|
433
|
+
const floor = rates.minChargePerHr ?? 0;
|
|
434
|
+
return {
|
|
435
|
+
compute,
|
|
436
|
+
memory,
|
|
437
|
+
storage: storageCost,
|
|
438
|
+
lineSum,
|
|
439
|
+
floor,
|
|
440
|
+
floorApplies: floor > lineSum,
|
|
441
|
+
total: Math.max(floor, lineSum)
|
|
442
|
+
};
|
|
368
443
|
}
|
|
369
444
|
function ProvisioningWizard({
|
|
370
445
|
environments: environmentsProp,
|
|
@@ -382,11 +457,22 @@ function ProvisioningWizard({
|
|
|
382
457
|
pricingRates,
|
|
383
458
|
planTiers
|
|
384
459
|
}) {
|
|
385
|
-
const cpuMax = Math.max(
|
|
386
|
-
|
|
387
|
-
|
|
460
|
+
const cpuMax = Math.max(
|
|
461
|
+
CPU_MIN,
|
|
462
|
+
Math.min(resourceLimits?.cpuMax ?? CPU_MAX, CPU_MAX)
|
|
463
|
+
);
|
|
464
|
+
const ramMax = Math.max(
|
|
465
|
+
RAM_MIN,
|
|
466
|
+
Math.min(resourceLimits?.ramMaxGB ?? RAM_MAX, RAM_MAX)
|
|
467
|
+
);
|
|
468
|
+
const storageMax = Math.max(
|
|
469
|
+
STORAGE_MIN,
|
|
470
|
+
Math.min(resourceLimits?.storageMaxGB ?? STORAGE_MAX, STORAGE_MAX)
|
|
471
|
+
);
|
|
388
472
|
const dc = defaultConfig;
|
|
389
|
-
const [envList, setEnvList] = React2.useState(
|
|
473
|
+
const [envList, setEnvList] = React2.useState(
|
|
474
|
+
environmentsProp ?? defaultEnvironments
|
|
475
|
+
);
|
|
390
476
|
const onLoadEnvironmentsRef = React2.useRef(onLoadEnvironments);
|
|
391
477
|
onLoadEnvironmentsRef.current = onLoadEnvironments;
|
|
392
478
|
React2.useEffect(() => {
|
|
@@ -395,7 +481,10 @@ function ProvisioningWizard({
|
|
|
395
481
|
onLoadEnvironmentsRef.current().then((entries) => {
|
|
396
482
|
if (!cancelled) setEnvList(entries.map(resolveEnvironment));
|
|
397
483
|
}).catch((err) => {
|
|
398
|
-
if (!cancelled)
|
|
484
|
+
if (!cancelled)
|
|
485
|
+
setLoadError(
|
|
486
|
+
err instanceof Error ? err.message : "Failed to load environments"
|
|
487
|
+
);
|
|
399
488
|
});
|
|
400
489
|
} else if (environmentsProp) {
|
|
401
490
|
setEnvList(environmentsProp);
|
|
@@ -406,22 +495,32 @@ function ProvisioningWizard({
|
|
|
406
495
|
}, [environmentsProp]);
|
|
407
496
|
const environments = envList;
|
|
408
497
|
const effectiveDefault = dc?.environment ?? defaultEnvironment;
|
|
409
|
-
const [selectedEnv, setSelectedEnv] = React2.useState(
|
|
498
|
+
const [selectedEnv, setSelectedEnv] = React2.useState(
|
|
499
|
+
effectiveDefault ?? environments[0]?.id ?? ""
|
|
500
|
+
);
|
|
410
501
|
React2.useEffect(() => {
|
|
411
502
|
if (effectiveDefault && envList.some((e) => e.id === effectiveDefault)) {
|
|
412
503
|
setSelectedEnv(effectiveDefault);
|
|
413
504
|
}
|
|
414
505
|
}, [envList, effectiveDefault]);
|
|
415
|
-
const [cpuCores, setCpuCores] = React2.useState(
|
|
506
|
+
const [cpuCores, setCpuCores] = React2.useState(
|
|
507
|
+
Math.min(dc?.cpuCores ?? 4, cpuMax)
|
|
508
|
+
);
|
|
416
509
|
const [ramGB, setRamGB] = React2.useState(Math.min(dc?.ramGB ?? 16, ramMax));
|
|
417
|
-
const [storageGB, setStorageGB] = React2.useState(
|
|
510
|
+
const [storageGB, setStorageGB] = React2.useState(
|
|
511
|
+
Math.min(dc?.storageGB ?? 128, storageMax)
|
|
512
|
+
);
|
|
418
513
|
React2.useEffect(() => {
|
|
419
514
|
setCpuCores((prev) => Math.min(prev, cpuMax));
|
|
420
515
|
setRamGB((prev) => Math.min(prev, ramMax));
|
|
421
516
|
setStorageGB((prev) => Math.min(prev, storageMax));
|
|
422
517
|
}, [cpuMax, ramMax, storageMax]);
|
|
423
|
-
const [modelTier, setModelTier] = React2.useState(
|
|
424
|
-
|
|
518
|
+
const [modelTier, setModelTier] = React2.useState(
|
|
519
|
+
dc?.modelTier ?? DEFAULT_MODEL_TIER
|
|
520
|
+
);
|
|
521
|
+
const [systemPrompt, setSystemPrompt] = React2.useState(
|
|
522
|
+
dc?.systemPrompt ?? ""
|
|
523
|
+
);
|
|
425
524
|
React2.useEffect(() => {
|
|
426
525
|
const options = modelOptions ?? DEFAULT_MODEL_OPTIONS;
|
|
427
526
|
if (options.length === 0) return;
|
|
@@ -438,9 +537,12 @@ function ProvisioningWizard({
|
|
|
438
537
|
const [envVars, setEnvVars] = React2.useState(dc?.envVars ?? [{ key: "", value: "" }]);
|
|
439
538
|
const [driver, setDriver] = React2.useState(dc?.driver ?? "docker");
|
|
440
539
|
const [bare, setBare] = React2.useState(dc?.bare ?? false);
|
|
441
|
-
const [startupScriptIds, setStartupScriptIds] = React2.useState(
|
|
540
|
+
const [startupScriptIds, setStartupScriptIds] = React2.useState(
|
|
541
|
+
dc?.startupScriptIds ?? []
|
|
542
|
+
);
|
|
442
543
|
const [availableScripts, setAvailableScripts] = React2.useState([]);
|
|
443
544
|
const [activePreset, setActivePreset] = React2.useState(null);
|
|
545
|
+
const [pricingView, setPricingView] = React2.useState("hourly");
|
|
444
546
|
const [showAdvanced, setShowAdvanced] = React2.useState(false);
|
|
445
547
|
const [loadError, setLoadError] = React2.useState(null);
|
|
446
548
|
const onLoadStartupScriptsRef = React2.useRef(onLoadStartupScripts);
|
|
@@ -451,7 +553,10 @@ function ProvisioningWizard({
|
|
|
451
553
|
onLoadStartupScriptsRef.current().then((scripts) => {
|
|
452
554
|
if (!cancelled) setAvailableScripts(scripts);
|
|
453
555
|
}).catch((err) => {
|
|
454
|
-
if (!cancelled)
|
|
556
|
+
if (!cancelled)
|
|
557
|
+
setLoadError(
|
|
558
|
+
err instanceof Error ? err.message : "Failed to load startup scripts"
|
|
559
|
+
);
|
|
455
560
|
});
|
|
456
561
|
}
|
|
457
562
|
return () => {
|
|
@@ -459,7 +564,9 @@ function ProvisioningWizard({
|
|
|
459
564
|
};
|
|
460
565
|
}, []);
|
|
461
566
|
const isMultistep = variant === "multistep";
|
|
462
|
-
const [currentStep, setCurrentStep] = React2.useState(
|
|
567
|
+
const [currentStep, setCurrentStep] = React2.useState(
|
|
568
|
+
skipToReview && dc && isMultistep ? 3 : 1
|
|
569
|
+
);
|
|
463
570
|
const [isDeploying, setIsDeploying] = React2.useState(false);
|
|
464
571
|
const [deployError, setDeployError] = React2.useState(null);
|
|
465
572
|
const handleDeploy = async () => {
|
|
@@ -467,8 +574,25 @@ function ProvisioningWizard({
|
|
|
467
574
|
setIsDeploying(true);
|
|
468
575
|
setDeployError(null);
|
|
469
576
|
try {
|
|
470
|
-
const validScriptIds = new Set(
|
|
471
|
-
|
|
577
|
+
const validScriptIds = new Set(
|
|
578
|
+
availableScripts.filter((s) => s.enabled).map((s) => s.id)
|
|
579
|
+
);
|
|
580
|
+
await onSubmit({
|
|
581
|
+
environment: selectedEnv,
|
|
582
|
+
cpuCores,
|
|
583
|
+
ramGB,
|
|
584
|
+
storageGB,
|
|
585
|
+
modelTier,
|
|
586
|
+
systemPrompt,
|
|
587
|
+
name,
|
|
588
|
+
gitUrl,
|
|
589
|
+
envVars: envVars.filter((e) => e.key.trim() !== ""),
|
|
590
|
+
driver,
|
|
591
|
+
bare,
|
|
592
|
+
startupScriptIds: startupScriptIds.filter(
|
|
593
|
+
(id) => validScriptIds.has(id)
|
|
594
|
+
)
|
|
595
|
+
});
|
|
472
596
|
} catch (err) {
|
|
473
597
|
setDeployError(err instanceof Error ? err.message : "Deployment failed");
|
|
474
598
|
} finally {
|
|
@@ -511,18 +635,43 @@ function ProvisioningWizard({
|
|
|
511
635
|
if (matching) setActivePreset(matching.name);
|
|
512
636
|
return;
|
|
513
637
|
}
|
|
514
|
-
const largestFitting = [...RAW_PRESETS].reverse().find(
|
|
638
|
+
const largestFitting = [...RAW_PRESETS].reverse().find(
|
|
639
|
+
(p) => p.cpu <= cpuMax && p.ram <= ramMax && p.storage <= storageMax
|
|
640
|
+
);
|
|
515
641
|
if (largestFitting) {
|
|
516
|
-
applyPreset(
|
|
642
|
+
applyPreset(
|
|
643
|
+
largestFitting.name,
|
|
644
|
+
largestFitting.cpu,
|
|
645
|
+
largestFitting.ram,
|
|
646
|
+
largestFitting.storage
|
|
647
|
+
);
|
|
517
648
|
} else {
|
|
518
649
|
setActivePreset(null);
|
|
519
650
|
}
|
|
520
651
|
}, [cpuMax, ramMax, storageMax, dc]);
|
|
521
652
|
const effectivePricingRates = pricingRates ?? DEFAULT_PRICING_RATES;
|
|
522
|
-
const
|
|
653
|
+
const hourlyCostBreakdown = computeHourlyCost(
|
|
654
|
+
cpuCores,
|
|
655
|
+
ramGB,
|
|
656
|
+
storageGB,
|
|
657
|
+
effectivePricingRates
|
|
658
|
+
);
|
|
659
|
+
const hourCost = hourlyCostBreakdown.total.toFixed(2);
|
|
660
|
+
const displayValue = pricingView === "hourly" ? hourCost : formatPerSecondValue(hourlyCostBreakdown.total);
|
|
661
|
+
const pricingSuffix = pricingView === "hourly" ? "/ hour" : "/ sec";
|
|
662
|
+
const rateSuffix = pricingView === "hourly" ? "/h" : "/s";
|
|
663
|
+
const fmtRate = (v) => pricingView === "hourly" ? v.toFixed(2) : formatPerSecondValue(v);
|
|
523
664
|
return /* @__PURE__ */ jsxs2("div", { className: cn("max-w-6xl mx-auto flex flex-col", className), children: [
|
|
524
665
|
/* @__PURE__ */ jsxs2("div", { className: "mb-6 flex items-center gap-4 shrink-0", children: [
|
|
525
|
-
onBack && /* @__PURE__ */ jsx2(
|
|
666
|
+
onBack && /* @__PURE__ */ jsx2(
|
|
667
|
+
"button",
|
|
668
|
+
{
|
|
669
|
+
type: "button",
|
|
670
|
+
onClick: onBack,
|
|
671
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border border-border hover:bg-muted/50 transition-colors text-foreground",
|
|
672
|
+
children: /* @__PURE__ */ jsx2(ArrowLeft, { className: "h-5 w-5" })
|
|
673
|
+
}
|
|
674
|
+
),
|
|
526
675
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
527
676
|
/* @__PURE__ */ jsx2("h1", { className: "text-3xl font-extrabold tracking-tight text-foreground mb-1", children: "Sandbox Provisioning" }),
|
|
528
677
|
/* @__PURE__ */ jsx2("p", { className: "text-muted-foreground text-sm", children: "Select your stack, allocate resources, and configure your agent." })
|
|
@@ -531,16 +680,39 @@ function ProvisioningWizard({
|
|
|
531
680
|
/* @__PURE__ */ jsxs2("div", { className: "grid grid-cols-12 gap-6 flex-1 min-h-0", children: [
|
|
532
681
|
/* @__PURE__ */ jsxs2("div", { className: "col-span-12 xl:col-span-8 flex flex-col min-h-0", children: [
|
|
533
682
|
isMultistep && /* @__PURE__ */ jsx2("div", { className: "flex items-center gap-2 mb-4 bg-card border border-border p-3 rounded-2xl mx-auto max-w-2xl justify-between shrink-0", children: [1, 2, 3].map((s) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center", children: [
|
|
534
|
-
/* @__PURE__ */ jsx2(
|
|
535
|
-
"
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
683
|
+
/* @__PURE__ */ jsx2(
|
|
684
|
+
"div",
|
|
685
|
+
{
|
|
686
|
+
className: cn(
|
|
687
|
+
"w-7 h-7 rounded-full flex items-center justify-center font-bold text-xs shrink-0 transition-all duration-200",
|
|
688
|
+
currentStep === s ? "bg-primary text-primary-foreground ring-2 ring-primary/30 ring-offset-2 ring-offset-card shadow-sm" : currentStep > s ? "bg-primary text-primary-foreground" : "bg-muted border border-border text-muted-foreground"
|
|
689
|
+
),
|
|
690
|
+
children: currentStep > s ? /* @__PURE__ */ jsx2(Check, { className: "h-3.5 w-3.5" }) : s
|
|
691
|
+
}
|
|
692
|
+
),
|
|
693
|
+
/* @__PURE__ */ jsxs2(
|
|
694
|
+
"span",
|
|
695
|
+
{
|
|
696
|
+
className: cn(
|
|
697
|
+
"ml-2 sm:ml-3 font-bold text-sm tracking-tight hidden sm:inline transition-colors duration-200",
|
|
698
|
+
currentStep === s ? "text-foreground" : currentStep > s ? "text-primary" : "text-muted-foreground"
|
|
699
|
+
),
|
|
700
|
+
children: [
|
|
701
|
+
s === 1 && "Environment",
|
|
702
|
+
s === 2 && "Resources",
|
|
703
|
+
s === 3 && "AI Agent"
|
|
704
|
+
]
|
|
705
|
+
}
|
|
706
|
+
),
|
|
707
|
+
s < 3 && /* @__PURE__ */ jsx2(
|
|
708
|
+
"div",
|
|
709
|
+
{
|
|
710
|
+
className: cn(
|
|
711
|
+
"w-4 sm:w-8 h-0.5 mx-2 sm:mx-4 rounded-full transition-colors duration-300",
|
|
712
|
+
currentStep > s ? "bg-primary" : "bg-border"
|
|
713
|
+
)
|
|
714
|
+
}
|
|
715
|
+
)
|
|
544
716
|
] }, s)) }),
|
|
545
717
|
dc && isMultistep && /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between bg-card border border-border rounded-2xl px-4 py-3 shrink-0", children: [
|
|
546
718
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
@@ -557,11 +729,11 @@ function ProvisioningWizard({
|
|
|
557
729
|
setCpuCores(Math.min(4, cpuMax));
|
|
558
730
|
setRamGB(Math.min(16, ramMax));
|
|
559
731
|
setStorageGB(Math.min(128, storageMax));
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
732
|
+
const resetOptions = modelOptions ?? DEFAULT_MODEL_OPTIONS;
|
|
733
|
+
const firstAvailable = resetOptions.find(
|
|
734
|
+
(o) => !o.disabled
|
|
735
|
+
);
|
|
736
|
+
setModelTier(firstAvailable?.value ?? DEFAULT_MODEL_TIER);
|
|
565
737
|
setSystemPrompt("");
|
|
566
738
|
setName("");
|
|
567
739
|
setGitUrl("");
|
|
@@ -570,6 +742,7 @@ function ProvisioningWizard({
|
|
|
570
742
|
setBare(false);
|
|
571
743
|
setStartupScriptIds([]);
|
|
572
744
|
setActivePreset(null);
|
|
745
|
+
setPricingView("hourly");
|
|
573
746
|
},
|
|
574
747
|
className: "text-xs font-bold text-primary hover:text-primary/70 transition-colors",
|
|
575
748
|
children: "Start from scratch"
|
|
@@ -599,10 +772,16 @@ function ProvisioningWizard({
|
|
|
599
772
|
selectedEnv === env.id && /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 bg-gradient-to-br from-primary/8 to-transparent pointer-events-none" }),
|
|
600
773
|
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-start mb-3 relative z-10", children: [
|
|
601
774
|
/* @__PURE__ */ jsx2("div", { className: "w-10 h-10 rounded-full flex items-center justify-center bg-muted/50 border border-border shadow-inner", children: env.icon }),
|
|
602
|
-
/* @__PURE__ */ jsx2(
|
|
603
|
-
"
|
|
604
|
-
|
|
605
|
-
|
|
775
|
+
/* @__PURE__ */ jsx2(
|
|
776
|
+
"div",
|
|
777
|
+
{
|
|
778
|
+
className: cn(
|
|
779
|
+
"w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200",
|
|
780
|
+
selectedEnv === env.id ? "border-primary bg-primary" : "border-border group-hover:border-primary/40"
|
|
781
|
+
),
|
|
782
|
+
children: selectedEnv === env.id && /* @__PURE__ */ jsx2(Check, { className: "h-3 w-3 text-primary-foreground animate-in zoom-in duration-200" })
|
|
783
|
+
}
|
|
784
|
+
)
|
|
606
785
|
] }),
|
|
607
786
|
/* @__PURE__ */ jsx2("h3", { className: "font-bold text-sm mb-0.5 text-foreground relative z-10", children: env.name }),
|
|
608
787
|
/* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground leading-relaxed relative z-10", children: env.description })
|
|
@@ -632,14 +811,24 @@ function ProvisioningWizard({
|
|
|
632
811
|
),
|
|
633
812
|
children: [
|
|
634
813
|
p.locked && /* @__PURE__ */ jsx2("div", { className: "absolute -top-1.5 -right-1.5 bg-primary text-primary-foreground text-[9px] font-bold px-1.5 py-0.5 rounded-full uppercase tracking-wider", children: p.unlockLabel }),
|
|
635
|
-
/* @__PURE__ */ jsx2(
|
|
814
|
+
/* @__PURE__ */ jsx2(
|
|
815
|
+
"div",
|
|
816
|
+
{
|
|
817
|
+
className: cn(
|
|
818
|
+
"font-bold text-sm transition-colors duration-200",
|
|
819
|
+
active ? "text-primary" : p.locked ? "text-muted-foreground" : "text-foreground"
|
|
820
|
+
),
|
|
821
|
+
children: p.name
|
|
822
|
+
}
|
|
823
|
+
),
|
|
636
824
|
/* @__PURE__ */ jsxs2("div", { className: "text-xs text-muted-foreground mt-0.5 font-mono", children: [
|
|
637
825
|
p.cpu,
|
|
638
826
|
" vCPU",
|
|
639
827
|
p.cpu === 1 ? "" : "s",
|
|
640
828
|
" / ",
|
|
641
829
|
p.ram,
|
|
642
|
-
"GB /
|
|
830
|
+
"GB /",
|
|
831
|
+
" ",
|
|
643
832
|
p.storage,
|
|
644
833
|
"GB"
|
|
645
834
|
] })
|
|
@@ -650,43 +839,69 @@ function ProvisioningWizard({
|
|
|
650
839
|
}) })
|
|
651
840
|
] }),
|
|
652
841
|
/* @__PURE__ */ jsx2("div", { className: "space-y-6", children: [
|
|
653
|
-
{
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
842
|
+
{
|
|
843
|
+
label: "Compute Cores (CPU)",
|
|
844
|
+
value: cpuCores,
|
|
845
|
+
setter: setCpuCores,
|
|
846
|
+
min: CPU_MIN,
|
|
847
|
+
max: cpuMax,
|
|
848
|
+
step: 0.5,
|
|
849
|
+
unit: "vCPU"
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
label: "Memory (RAM)",
|
|
853
|
+
value: ramGB,
|
|
854
|
+
setter: setRamGB,
|
|
855
|
+
min: RAM_MIN,
|
|
856
|
+
max: ramMax,
|
|
857
|
+
step: 1,
|
|
858
|
+
unit: "GB"
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
label: "Ephemeral Storage",
|
|
862
|
+
value: storageGB,
|
|
863
|
+
setter: setStorageGB,
|
|
864
|
+
min: STORAGE_MIN,
|
|
865
|
+
max: storageMax,
|
|
866
|
+
step: 8,
|
|
867
|
+
unit: "GB"
|
|
868
|
+
}
|
|
869
|
+
].map(
|
|
870
|
+
({ label, value, setter, min, max, step: s, unit }) => {
|
|
871
|
+
const displayUnit = unit === "vCPU" ? `${value} vCPU${value === 1 ? "" : "s"}` : `${value}${unit}`;
|
|
872
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
873
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-end border-b border-border pb-1.5 mb-2", children: [
|
|
874
|
+
/* @__PURE__ */ jsx2("label", { className: "font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: label }),
|
|
875
|
+
/* @__PURE__ */ jsx2("span", { className: "text-xl font-bold text-foreground tracking-tight", children: displayUnit })
|
|
682
876
|
] }),
|
|
683
|
-
/* @__PURE__ */
|
|
684
|
-
|
|
685
|
-
|
|
877
|
+
/* @__PURE__ */ jsx2(
|
|
878
|
+
"input",
|
|
879
|
+
{
|
|
880
|
+
type: "range",
|
|
881
|
+
min,
|
|
882
|
+
max,
|
|
883
|
+
step: s,
|
|
884
|
+
value,
|
|
885
|
+
onChange: (e) => {
|
|
886
|
+
setter(+e.target.value);
|
|
887
|
+
setActivePreset(null);
|
|
888
|
+
},
|
|
889
|
+
className: "w-full h-2 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-2 [&::-moz-range-track]:bg-border [&::-moz-range-track]:rounded-full [&::-moz-range-track]:h-2 [&::-webkit-slider-thumb]:bg-primary [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:-mt-[6px] [&::-webkit-slider-thumb]:shadow-md [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-foreground [&::-webkit-slider-thumb]:transition-transform [&::-webkit-slider-thumb]:hover:scale-110"
|
|
890
|
+
}
|
|
891
|
+
),
|
|
892
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground/60 mt-1", children: [
|
|
893
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
894
|
+
min,
|
|
895
|
+
unit === "vCPU" ? min === 1 ? " vCPU" : " vCPUs" : unit
|
|
896
|
+
] }),
|
|
897
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
898
|
+
max,
|
|
899
|
+
unit === "vCPU" ? max === 1 ? " vCPU" : " vCPUs" : unit
|
|
900
|
+
] })
|
|
686
901
|
] })
|
|
687
|
-
] })
|
|
688
|
-
|
|
689
|
-
|
|
902
|
+
] }, label);
|
|
903
|
+
}
|
|
904
|
+
) })
|
|
690
905
|
] }) }),
|
|
691
906
|
(!isMultistep || currentStep === 3) && /* @__PURE__ */ jsx2(React2.Fragment, { children: /* @__PURE__ */ jsxs2("section", { className: "bg-card border border-border rounded-[24px] p-6 shadow-2xl relative overflow-hidden animate-in fade-in slide-in-from-bottom-4 duration-300", children: [
|
|
692
907
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3 mb-5", children: [
|
|
@@ -703,16 +918,18 @@ function ProvisioningWizard({
|
|
|
703
918
|
onChange: (e) => setModelTier(e.target.value),
|
|
704
919
|
disabled: modelOptions && modelOptions.filter((o) => !o.disabled).length === 0,
|
|
705
920
|
className: "w-full bg-card border border-border rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent appearance-none disabled:opacity-50 disabled:cursor-not-allowed",
|
|
706
|
-
children: (modelOptions ?? DEFAULT_MODEL_OPTIONS).map(
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
921
|
+
children: (modelOptions ?? DEFAULT_MODEL_OPTIONS).map(
|
|
922
|
+
(option) => /* @__PURE__ */ jsx2(
|
|
923
|
+
"option",
|
|
924
|
+
{
|
|
925
|
+
value: option.value,
|
|
926
|
+
disabled: option.disabled,
|
|
927
|
+
className: "bg-gray-900",
|
|
928
|
+
children: option.label
|
|
929
|
+
},
|
|
930
|
+
option.value
|
|
931
|
+
)
|
|
932
|
+
)
|
|
716
933
|
}
|
|
717
934
|
),
|
|
718
935
|
modelOptions && modelOptions.length > 0 && modelOptions.every((o) => o.disabled) && /* @__PURE__ */ jsx2("p", { className: "text-xs text-muted-foreground mt-2", children: "All model options are currently disabled. Please upgrade your plan or contact support." })
|
|
@@ -766,12 +983,22 @@ function ProvisioningWizard({
|
|
|
766
983
|
{
|
|
767
984
|
value: driver,
|
|
768
985
|
onChange: (e) => {
|
|
769
|
-
if (VALID_DRIVERS.has(e.target.value))
|
|
986
|
+
if (VALID_DRIVERS.has(e.target.value))
|
|
987
|
+
setDriver(
|
|
988
|
+
e.target.value
|
|
989
|
+
);
|
|
770
990
|
},
|
|
771
991
|
className: "w-full bg-card border border-border rounded-xl h-12 px-4 font-bold text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent appearance-none",
|
|
772
992
|
children: [
|
|
773
993
|
/* @__PURE__ */ jsx2("option", { value: "docker", className: "bg-gray-900", children: "Docker container (Default)" }),
|
|
774
|
-
/* @__PURE__ */ jsx2(
|
|
994
|
+
/* @__PURE__ */ jsx2(
|
|
995
|
+
"option",
|
|
996
|
+
{
|
|
997
|
+
value: "firecracker",
|
|
998
|
+
className: "bg-gray-900",
|
|
999
|
+
children: "Firecracker microVM (Secure)"
|
|
1000
|
+
}
|
|
1001
|
+
),
|
|
775
1002
|
/* @__PURE__ */ jsx2("option", { value: "tangle", className: "bg-gray-900", children: "Tangle Distributed Node" })
|
|
776
1003
|
]
|
|
777
1004
|
}
|
|
@@ -794,10 +1021,21 @@ function ProvisioningWizard({
|
|
|
794
1021
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
795
1022
|
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center mb-2", children: [
|
|
796
1023
|
/* @__PURE__ */ jsx2("label", { className: "block font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Environment Variables" }),
|
|
797
|
-
/* @__PURE__ */ jsxs2(
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
1024
|
+
/* @__PURE__ */ jsxs2(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
type: "button",
|
|
1028
|
+
onClick: () => setEnvVars([
|
|
1029
|
+
...envVars,
|
|
1030
|
+
{ key: "", value: "" }
|
|
1031
|
+
]),
|
|
1032
|
+
className: "flex items-center gap-1 text-xs text-primary hover:text-primary/70 transition-colors font-bold",
|
|
1033
|
+
children: [
|
|
1034
|
+
/* @__PURE__ */ jsx2(Plus, { className: "h-3 w-3" }),
|
|
1035
|
+
" Add Var"
|
|
1036
|
+
]
|
|
1037
|
+
}
|
|
1038
|
+
)
|
|
801
1039
|
] }),
|
|
802
1040
|
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
803
1041
|
envVars.map((env, i) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-2", children: [
|
|
@@ -806,7 +1044,11 @@ function ProvisioningWizard({
|
|
|
806
1044
|
{
|
|
807
1045
|
type: "text",
|
|
808
1046
|
value: env.key,
|
|
809
|
-
onChange: (e) => setEnvVars(
|
|
1047
|
+
onChange: (e) => setEnvVars(
|
|
1048
|
+
envVars.map(
|
|
1049
|
+
(v, idx) => idx === i ? { ...v, key: e.target.value } : v
|
|
1050
|
+
)
|
|
1051
|
+
),
|
|
810
1052
|
className: "flex-1 bg-card border border-border rounded-xl h-10 px-3 font-mono text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary placeholder:text-muted-foreground",
|
|
811
1053
|
placeholder: "API_KEY"
|
|
812
1054
|
}
|
|
@@ -816,12 +1058,26 @@ function ProvisioningWizard({
|
|
|
816
1058
|
{
|
|
817
1059
|
type: "password",
|
|
818
1060
|
value: env.value,
|
|
819
|
-
onChange: (e) => setEnvVars(
|
|
1061
|
+
onChange: (e) => setEnvVars(
|
|
1062
|
+
envVars.map(
|
|
1063
|
+
(v, idx) => idx === i ? { ...v, value: e.target.value } : v
|
|
1064
|
+
)
|
|
1065
|
+
),
|
|
820
1066
|
className: "flex-[2] bg-card border border-border rounded-xl h-10 px-3 font-mono text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary placeholder:text-muted-foreground",
|
|
821
1067
|
placeholder: "sk-xxxxxxxxxxx"
|
|
822
1068
|
}
|
|
823
1069
|
),
|
|
824
|
-
/* @__PURE__ */ jsx2(
|
|
1070
|
+
/* @__PURE__ */ jsx2(
|
|
1071
|
+
"button",
|
|
1072
|
+
{
|
|
1073
|
+
type: "button",
|
|
1074
|
+
onClick: () => setEnvVars(
|
|
1075
|
+
envVars.filter((_, idx) => idx !== i)
|
|
1076
|
+
),
|
|
1077
|
+
className: "h-10 w-10 flex items-center justify-center shrink-0 rounded-xl bg-card border border-border text-red-400 hover:bg-red-500/10 hover:border-red-500/30 transition-colors",
|
|
1078
|
+
children: /* @__PURE__ */ jsx2(Trash2, { className: "h-4 w-4" })
|
|
1079
|
+
}
|
|
1080
|
+
)
|
|
825
1081
|
] }, i)),
|
|
826
1082
|
envVars.length === 0 && /* @__PURE__ */ jsx2("div", { className: "text-center p-3 bg-card border border-border rounded-xl text-muted-foreground/60 text-sm italic", children: "No environment variables set" })
|
|
827
1083
|
] })
|
|
@@ -829,36 +1085,82 @@ function ProvisioningWizard({
|
|
|
829
1085
|
availableScripts.length > 0 && /* @__PURE__ */ jsxs2("div", { children: [
|
|
830
1086
|
/* @__PURE__ */ jsx2("div", { className: "text-xs font-bold uppercase tracking-widest text-muted-foreground mb-2", children: "Startup Scripts" }),
|
|
831
1087
|
/* @__PURE__ */ jsx2("div", { className: "space-y-2", children: availableScripts.filter((s) => s.enabled).map((script) => {
|
|
832
|
-
const selected = startupScriptIds.includes(
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1088
|
+
const selected = startupScriptIds.includes(
|
|
1089
|
+
script.id
|
|
1090
|
+
);
|
|
1091
|
+
return /* @__PURE__ */ jsxs2(
|
|
1092
|
+
"label",
|
|
1093
|
+
{
|
|
1094
|
+
className: "flex items-start gap-3 cursor-pointer group rounded-lg border border-border p-3 transition-colors hover:border-primary/30",
|
|
1095
|
+
children: [
|
|
1096
|
+
/* @__PURE__ */ jsx2(
|
|
1097
|
+
"input",
|
|
1098
|
+
{
|
|
1099
|
+
type: "checkbox",
|
|
1100
|
+
checked: selected,
|
|
1101
|
+
onChange: () => setStartupScriptIds(
|
|
1102
|
+
(prev) => selected ? prev.filter(
|
|
1103
|
+
(id) => id !== script.id
|
|
1104
|
+
) : [...prev, script.id]
|
|
1105
|
+
),
|
|
1106
|
+
className: "mt-0.5 h-4 w-4 rounded border-border text-primary focus:ring-primary/30"
|
|
1107
|
+
}
|
|
841
1108
|
),
|
|
842
|
-
className: "
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1109
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex-1 min-w-0", children: [
|
|
1110
|
+
/* @__PURE__ */ jsx2("div", { className: "text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: script.name }),
|
|
1111
|
+
script.description && /* @__PURE__ */ jsx2("div", { className: "text-xs text-muted-foreground mt-0.5", children: script.description }),
|
|
1112
|
+
script.injectSecrets.length > 0 && /* @__PURE__ */ jsx2("div", { className: "flex flex-wrap gap-1 mt-1.5", children: script.injectSecrets.map((s) => /* @__PURE__ */ jsxs2(
|
|
1113
|
+
"span",
|
|
1114
|
+
{
|
|
1115
|
+
className: "inline-flex items-center gap-0.5 rounded-full bg-muted px-2 py-0.5 text-[10px] text-muted-foreground",
|
|
1116
|
+
children: [
|
|
1117
|
+
/* @__PURE__ */ jsxs2(
|
|
1118
|
+
"svg",
|
|
1119
|
+
{
|
|
1120
|
+
className: "h-2.5 w-2.5",
|
|
1121
|
+
viewBox: "0 0 24 24",
|
|
1122
|
+
fill: "none",
|
|
1123
|
+
stroke: "currentColor",
|
|
1124
|
+
strokeWidth: "2",
|
|
1125
|
+
children: [
|
|
1126
|
+
/* @__PURE__ */ jsx2(
|
|
1127
|
+
"rect",
|
|
1128
|
+
{
|
|
1129
|
+
x: "3",
|
|
1130
|
+
y: "11",
|
|
1131
|
+
width: "18",
|
|
1132
|
+
height: "11",
|
|
1133
|
+
rx: "2",
|
|
1134
|
+
ry: "2"
|
|
1135
|
+
}
|
|
1136
|
+
),
|
|
1137
|
+
/* @__PURE__ */ jsx2("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
1138
|
+
]
|
|
1139
|
+
}
|
|
1140
|
+
),
|
|
1141
|
+
s
|
|
1142
|
+
]
|
|
1143
|
+
},
|
|
1144
|
+
s
|
|
1145
|
+
)) })
|
|
1146
|
+
] })
|
|
1147
|
+
]
|
|
1148
|
+
},
|
|
1149
|
+
script.id
|
|
1150
|
+
);
|
|
857
1151
|
}) })
|
|
858
1152
|
] }),
|
|
859
1153
|
/* @__PURE__ */ jsx2("div", { className: "pt-2 border-t border-border", children: /* @__PURE__ */ jsxs2("label", { className: "flex items-center gap-3 cursor-pointer group", children: [
|
|
860
1154
|
/* @__PURE__ */ jsxs2("div", { className: "relative flex items-center justify-center shrink-0", children: [
|
|
861
|
-
/* @__PURE__ */ jsx2(
|
|
1155
|
+
/* @__PURE__ */ jsx2(
|
|
1156
|
+
"input",
|
|
1157
|
+
{
|
|
1158
|
+
type: "checkbox",
|
|
1159
|
+
className: "sr-only peer",
|
|
1160
|
+
checked: bare,
|
|
1161
|
+
onChange: (e) => setBare(e.target.checked)
|
|
1162
|
+
}
|
|
1163
|
+
),
|
|
862
1164
|
/* @__PURE__ */ jsx2("div", { className: "w-10 h-6 bg-muted peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-primary hover:bg-muted/80 transition-colors" })
|
|
863
1165
|
] }),
|
|
864
1166
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
@@ -877,57 +1179,96 @@ function ProvisioningWizard({
|
|
|
877
1179
|
/* @__PURE__ */ jsx2("div", { className: "hidden" }),
|
|
878
1180
|
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center mb-4 relative z-10", children: [
|
|
879
1181
|
/* @__PURE__ */ jsx2("span", { className: "font-label text-xs font-bold uppercase tracking-widest text-muted-foreground", children: "Run Cost" }),
|
|
880
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsxs2(
|
|
1183
|
+
"div",
|
|
1184
|
+
{
|
|
1185
|
+
role: "group",
|
|
1186
|
+
"aria-label": "Pricing view",
|
|
1187
|
+
className: "inline-flex items-center rounded-full border border-border bg-muted/50 p-0.5",
|
|
1188
|
+
children: [
|
|
1189
|
+
/* @__PURE__ */ jsx2(
|
|
1190
|
+
"button",
|
|
1191
|
+
{
|
|
1192
|
+
type: "button",
|
|
1193
|
+
"aria-pressed": pricingView === "hourly",
|
|
1194
|
+
onClick: () => setPricingView("hourly"),
|
|
1195
|
+
className: cn(
|
|
1196
|
+
"rounded-full px-2.5 py-0.5 text-[10px] font-bold transition-all",
|
|
1197
|
+
pricingView === "hourly" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
1198
|
+
),
|
|
1199
|
+
children: "Per Hour"
|
|
1200
|
+
}
|
|
1201
|
+
),
|
|
1202
|
+
/* @__PURE__ */ jsx2(
|
|
1203
|
+
"button",
|
|
1204
|
+
{
|
|
1205
|
+
type: "button",
|
|
1206
|
+
"aria-pressed": pricingView === "perSecond",
|
|
1207
|
+
onClick: () => setPricingView("perSecond"),
|
|
1208
|
+
className: cn(
|
|
1209
|
+
"rounded-full px-2.5 py-0.5 text-[10px] font-bold transition-all",
|
|
1210
|
+
pricingView === "perSecond" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
1211
|
+
),
|
|
1212
|
+
children: "Per Second"
|
|
1213
|
+
}
|
|
1214
|
+
)
|
|
1215
|
+
]
|
|
1216
|
+
}
|
|
1217
|
+
)
|
|
881
1218
|
] }),
|
|
882
1219
|
/* @__PURE__ */ jsxs2("div", { className: "flex items-baseline gap-2 mb-5 relative z-10", children: [
|
|
883
|
-
/* @__PURE__ */ jsxs2(
|
|
884
|
-
"
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
const memoryCost = ramGB * effectivePricingRates.ramPerGbHr;
|
|
892
|
-
const storageCost = storageGB * effectivePricingRates.diskPerGbHr;
|
|
893
|
-
const lineSum = computeCost + memoryCost + storageCost;
|
|
894
|
-
const floor = effectivePricingRates.minChargePerHr ?? 0;
|
|
895
|
-
const floorApplies = floor > lineSum;
|
|
896
|
-
return /* @__PURE__ */ jsxs2("div", { className: "space-y-2 relative z-10 bg-card border border-border rounded-xl p-3", children: [
|
|
897
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
898
|
-
/* @__PURE__ */ jsx2("span", { children: "COMPUTE" }),
|
|
899
|
-
/* @__PURE__ */ jsxs2("span", { className: "text-foreground", children: [
|
|
900
|
-
"$",
|
|
901
|
-
computeCost.toFixed(2),
|
|
902
|
-
"/h"
|
|
903
|
-
] })
|
|
904
|
-
] }),
|
|
905
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
906
|
-
/* @__PURE__ */ jsx2("span", { children: "MEMORY" }),
|
|
907
|
-
/* @__PURE__ */ jsxs2("span", { className: "text-foreground/80", children: [
|
|
908
|
-
"$",
|
|
909
|
-
memoryCost.toFixed(2),
|
|
910
|
-
"/h"
|
|
911
|
-
] })
|
|
912
|
-
] }),
|
|
913
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
914
|
-
/* @__PURE__ */ jsx2("span", { children: "STORAGE" }),
|
|
915
|
-
/* @__PURE__ */ jsxs2("span", { className: "text-foreground/80", children: [
|
|
916
|
-
"$",
|
|
917
|
-
storageCost.toFixed(2),
|
|
918
|
-
"/h"
|
|
919
|
-
] })
|
|
920
|
-
] }),
|
|
921
|
-
floorApplies && /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-primary border-t border-border pt-2", children: [
|
|
922
|
-
/* @__PURE__ */ jsx2("span", { children: "MIN CHARGE" }),
|
|
923
|
-
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1220
|
+
/* @__PURE__ */ jsxs2(
|
|
1221
|
+
"span",
|
|
1222
|
+
{
|
|
1223
|
+
className: cn(
|
|
1224
|
+
"font-black text-foreground tracking-tighter animate-in fade-in duration-200",
|
|
1225
|
+
pricingView === "hourly" ? "text-4xl" : "text-2xl"
|
|
1226
|
+
),
|
|
1227
|
+
children: [
|
|
924
1228
|
"$",
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1229
|
+
displayValue
|
|
1230
|
+
]
|
|
1231
|
+
},
|
|
1232
|
+
pricingView
|
|
1233
|
+
),
|
|
1234
|
+
/* @__PURE__ */ jsx2("span", { className: "text-muted-foreground text-sm font-bold", children: pricingSuffix })
|
|
1235
|
+
] }),
|
|
1236
|
+
/* @__PURE__ */ jsxs2("div", { className: "space-y-2 relative z-10 bg-card border border-border rounded-xl p-3", children: [
|
|
1237
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
1238
|
+
/* @__PURE__ */ jsx2("span", { children: "COMPUTE" }),
|
|
1239
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-foreground", children: [
|
|
1240
|
+
"$",
|
|
1241
|
+
fmtRate(hourlyCostBreakdown.compute),
|
|
1242
|
+
rateSuffix
|
|
1243
|
+
] })
|
|
1244
|
+
] }),
|
|
1245
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
1246
|
+
/* @__PURE__ */ jsx2("span", { children: "MEMORY" }),
|
|
1247
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-foreground/80", children: [
|
|
1248
|
+
"$",
|
|
1249
|
+
fmtRate(hourlyCostBreakdown.memory),
|
|
1250
|
+
rateSuffix
|
|
1251
|
+
] })
|
|
1252
|
+
] }),
|
|
1253
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-muted-foreground", children: [
|
|
1254
|
+
/* @__PURE__ */ jsx2("span", { children: "STORAGE" }),
|
|
1255
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-foreground/80", children: [
|
|
1256
|
+
"$",
|
|
1257
|
+
fmtRate(hourlyCostBreakdown.storage),
|
|
1258
|
+
rateSuffix
|
|
928
1259
|
] })
|
|
929
|
-
] })
|
|
930
|
-
|
|
1260
|
+
] }),
|
|
1261
|
+
hourlyCostBreakdown.floorApplies && /* @__PURE__ */ jsxs2("div", { className: "flex justify-between text-xs font-mono tracking-widest text-primary border-t border-border pt-2", children: [
|
|
1262
|
+
/* @__PURE__ */ jsx2("span", { children: "MIN CHARGE" }),
|
|
1263
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
1264
|
+
"$",
|
|
1265
|
+
fmtRate(
|
|
1266
|
+
hourlyCostBreakdown.floor - hourlyCostBreakdown.lineSum
|
|
1267
|
+
),
|
|
1268
|
+
rateSuffix
|
|
1269
|
+
] })
|
|
1270
|
+
] })
|
|
1271
|
+
] })
|
|
931
1272
|
] }),
|
|
932
1273
|
deployError && /* @__PURE__ */ jsxs2("div", { className: "rounded-xl border border-destructive/30 bg-destructive/10 p-3 flex items-center gap-2", children: [
|
|
933
1274
|
/* @__PURE__ */ jsx2(Info, { className: "h-4 w-4 text-destructive shrink-0" }),
|
|
@@ -941,7 +1282,8 @@ function ProvisioningWizard({
|
|
|
941
1282
|
onClick: () => setCurrentStep((s) => s + 1),
|
|
942
1283
|
className: "w-full relative overflow-hidden h-12 bg-primary text-primary-foreground font-extrabold text-sm rounded-2xl hover:brightness-110 transition-all active:scale-[0.98] shadow-md",
|
|
943
1284
|
children: [
|
|
944
|
-
"Continue to
|
|
1285
|
+
"Continue to",
|
|
1286
|
+
" ",
|
|
945
1287
|
currentStep === 1 ? "Resources" : "Agent Config"
|
|
946
1288
|
]
|
|
947
1289
|
}
|
|
@@ -1763,9 +2105,9 @@ function ProfileDetailDialog({
|
|
|
1763
2105
|
|
|
1764
2106
|
// src/pages/secrets-page.tsx
|
|
1765
2107
|
import * as React5 from "react";
|
|
1766
|
-
import { Lock, Plus as Plus3, Trash2 as Trash23, Eye, EyeOff, AlertCircle as AlertCircle2, Key, Shield, CheckCircle } from "lucide-react";
|
|
2108
|
+
import { Lock, Plus as Plus3, Trash2 as Trash23, Eye, EyeOff, AlertCircle as AlertCircle2, Key, Shield, CheckCircle, Users, ArrowRight } from "lucide-react";
|
|
1767
2109
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1768
|
-
function SecretsPage({ apiClient, className }) {
|
|
2110
|
+
function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
1769
2111
|
const [secrets, setSecrets] = React5.useState([]);
|
|
1770
2112
|
const [loading, setLoading] = React5.useState(true);
|
|
1771
2113
|
const [error, setError] = React5.useState(null);
|
|
@@ -1856,6 +2198,29 @@ function SecretsPage({ apiClient, className }) {
|
|
|
1856
2198
|
}
|
|
1857
2199
|
)
|
|
1858
2200
|
] }),
|
|
2201
|
+
teamSecretsHint && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3 rounded-lg border border-border bg-[var(--accent-surface-soft)]/40 px-4 py-3", children: [
|
|
2202
|
+
/* @__PURE__ */ jsx5(Users, { className: "h-5 w-5 shrink-0 text-[var(--accent-text)]", "aria-hidden": "true" }),
|
|
2203
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex-1 text-sm", children: [
|
|
2204
|
+
/* @__PURE__ */ jsx5("p", { className: "font-semibold text-foreground", children: "Setting up secrets for a team?" }),
|
|
2205
|
+
/* @__PURE__ */ jsxs5("p", { className: "mt-0.5 text-muted-foreground text-xs", children: [
|
|
2206
|
+
"Secrets here are ",
|
|
2207
|
+
/* @__PURE__ */ jsx5("strong", { children: "personal" }),
|
|
2208
|
+
" \u2014 only available in sandboxes you create. To share credentials with teammates, configure them on the team page instead."
|
|
2209
|
+
] })
|
|
2210
|
+
] }),
|
|
2211
|
+
/* @__PURE__ */ jsxs5(
|
|
2212
|
+
"button",
|
|
2213
|
+
{
|
|
2214
|
+
type: "button",
|
|
2215
|
+
onClick: teamSecretsHint.onNavigate,
|
|
2216
|
+
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",
|
|
2217
|
+
children: [
|
|
2218
|
+
teamSecretsHint.label ?? "Manage team secrets",
|
|
2219
|
+
/* @__PURE__ */ jsx5(ArrowRight, { className: "h-3 w-3", "aria-hidden": "true" })
|
|
2220
|
+
]
|
|
2221
|
+
}
|
|
2222
|
+
)
|
|
2223
|
+
] }),
|
|
1859
2224
|
/* @__PURE__ */ jsxs5("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-4", children: [
|
|
1860
2225
|
/* @__PURE__ */ jsxs5("div", { className: "rounded-lg border border-border bg-card p-5 shadow-[var(--shadow-card)]", children: [
|
|
1861
2226
|
/* @__PURE__ */ jsx5("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Total Active Secrets" }),
|