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