@tangle-network/sandbox-ui 0.20.3 → 0.21.1
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/chat.d.ts +111 -1
- package/dist/chat.js +17 -3
- package/dist/{chunk-QNVVKMEW.js → chunk-4KAPMTPU.js} +1 -542
- package/dist/chunk-DNZ4DTNA.js +547 -0
- package/dist/chunk-ESRYVGHF.js +147 -0
- package/dist/{chunk-R6QNJQRH.js → chunk-LA5GHELP.js} +446 -451
- package/dist/{chunk-CMY7W45U.js → chunk-MEDE37J5.js} +8 -2
- package/dist/{chunk-CP2L6B53.js → chunk-R6NONXFC.js} +12 -8
- package/dist/{chunk-76IQLPW2.js → chunk-SOKKTB7W.js} +29 -5
- package/dist/{chunk-MQ52AYJX.js → chunk-TAAYDQGM.js} +236 -24
- package/dist/dashboard.d.ts +37 -48
- package/dist/dashboard.js +14 -8
- package/dist/globals.css +33 -209
- package/dist/harness-picker-C1W3rTeb.d.ts +49 -0
- package/dist/hooks.d.ts +64 -3
- package/dist/hooks.js +2 -2
- package/dist/index.d.ts +6 -4
- package/dist/index.js +33 -15
- package/dist/{template-card-gf-InrfN.d.ts → model-picker-DUfMTQo5.d.ts} +1 -86
- package/dist/pages.d.ts +5 -37
- package/dist/pages.js +304 -396
- package/dist/sdk-hooks-jUbIngSV.d.ts +96 -0
- package/dist/sdk-hooks.d.ts +2 -77
- package/dist/sdk-hooks.js +1 -1
- package/dist/styles.css +33 -209
- package/dist/template-card-UhV3pmRC.d.ts +88 -0
- package/dist/workspace.d.ts +7 -0
- package/dist/workspace.js +1 -1
- package/package.json +8 -8
|
@@ -185,7 +185,7 @@ function SidebarRailFooter({ children, className }) {
|
|
|
185
185
|
function RailSeparator({ className }) {
|
|
186
186
|
return /* @__PURE__ */ jsx2("div", { className: cn("my-2 h-px w-10 bg-[var(--md3-outline-variant)]", className) });
|
|
187
187
|
}
|
|
188
|
-
function RailButton({ icon:
|
|
188
|
+
function RailButton({ icon: Icon, label, isActive, badge, onClick, className, showLabel }) {
|
|
189
189
|
return /* @__PURE__ */ jsxs(
|
|
190
190
|
"button",
|
|
191
191
|
{
|
|
@@ -203,7 +203,7 @@ function RailButton({ icon: Icon2, label, isActive, badge, onClick, className, s
|
|
|
203
203
|
className
|
|
204
204
|
),
|
|
205
205
|
children: [
|
|
206
|
-
/* @__PURE__ */ jsx2(
|
|
206
|
+
/* @__PURE__ */ jsx2(Icon, { className: "h-5 w-5 shrink-0" }),
|
|
207
207
|
showLabel && /* @__PURE__ */ jsx2("span", { className: "text-sm font-medium", children: label }),
|
|
208
208
|
badge !== void 0 && badge > 0 && /* @__PURE__ */ jsx2("span", { className: "absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary text-[9px] font-bold text-[var(--md3-on-primary)] px-1 shadow-sm", children: badge > 99 ? "99+" : badge })
|
|
209
209
|
]
|
|
@@ -1139,168 +1139,30 @@ function PlanCards({ plans, className }) {
|
|
|
1139
1139
|
] });
|
|
1140
1140
|
}
|
|
1141
1141
|
|
|
1142
|
-
// src/dashboard/backend-selector.tsx
|
|
1143
|
-
import { ChevronDown } from "lucide-react";
|
|
1144
|
-
import * as Select from "@radix-ui/react-select";
|
|
1145
|
-
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1146
|
-
function BackendSelector({
|
|
1147
|
-
backends,
|
|
1148
|
-
selected,
|
|
1149
|
-
onChange,
|
|
1150
|
-
label = "Model",
|
|
1151
|
-
placeholder = "Select a model",
|
|
1152
|
-
className
|
|
1153
|
-
}) {
|
|
1154
|
-
const current = backends.find((b) => b.type === selected);
|
|
1155
|
-
return /* @__PURE__ */ jsxs10("div", { className: cn("space-y-1.5", className), children: [
|
|
1156
|
-
label && /* @__PURE__ */ jsx11("label", { className: "block text-xs font-medium text-muted-foreground uppercase tracking-[0.06em]", children: label }),
|
|
1157
|
-
/* @__PURE__ */ jsxs10(Select.Root, { value: selected, onValueChange: onChange, children: [
|
|
1158
|
-
/* @__PURE__ */ jsxs10(
|
|
1159
|
-
Select.Trigger,
|
|
1160
|
-
{
|
|
1161
|
-
className: cn(
|
|
1162
|
-
"flex w-full items-center justify-between gap-2 rounded-[var(--radius-md)]",
|
|
1163
|
-
"border border-border bg-card",
|
|
1164
|
-
"px-3 py-2.5 text-sm text-left",
|
|
1165
|
-
"transition-colors duration-[var(--transition-fast)]",
|
|
1166
|
-
"hover:border-primary/20 hover:bg-accent/30",
|
|
1167
|
-
"focus:outline-none focus:border-primary/30",
|
|
1168
|
-
"data-[state=open]:border-primary/30 data-[state=open]:bg-accent/30"
|
|
1169
|
-
),
|
|
1170
|
-
children: [
|
|
1171
|
-
/* @__PURE__ */ jsx11("div", { className: "min-w-0 flex-1", children: current ? /* @__PURE__ */ jsxs10("div", { children: [
|
|
1172
|
-
/* @__PURE__ */ jsx11("span", { className: "font-medium text-foreground", children: current.label }),
|
|
1173
|
-
current.description && /* @__PURE__ */ jsx11("span", { className: "ml-2 text-xs text-muted-foreground", children: current.description })
|
|
1174
|
-
] }) : /* @__PURE__ */ jsx11("span", { className: "text-muted-foreground", children: placeholder }) }),
|
|
1175
|
-
/* @__PURE__ */ jsx11(Select.Icon, { asChild: true, children: /* @__PURE__ */ jsx11(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-[var(--transition-fast)] data-[state=open]:rotate-180" }) })
|
|
1176
|
-
]
|
|
1177
|
-
}
|
|
1178
|
-
),
|
|
1179
|
-
/* @__PURE__ */ jsx11(Select.Portal, { children: /* @__PURE__ */ jsx11(
|
|
1180
|
-
Select.Content,
|
|
1181
|
-
{
|
|
1182
|
-
position: "popper",
|
|
1183
|
-
sideOffset: 4,
|
|
1184
|
-
className: cn(
|
|
1185
|
-
"z-50 w-[var(--radix-select-trigger-width)] overflow-hidden",
|
|
1186
|
-
"rounded-[var(--radius-md)] border border-border",
|
|
1187
|
-
"bg-card shadow-[var(--shadow-dropdown)]",
|
|
1188
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1189
|
-
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1190
|
-
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
1191
|
-
"data-[side=bottom]:slide-in-from-top-1"
|
|
1192
|
-
),
|
|
1193
|
-
children: /* @__PURE__ */ jsx11(Select.Viewport, { className: "p-1", children: backends.map((backend) => /* @__PURE__ */ jsxs10(
|
|
1194
|
-
Select.Item,
|
|
1195
|
-
{
|
|
1196
|
-
value: backend.type,
|
|
1197
|
-
className: cn(
|
|
1198
|
-
"relative flex cursor-pointer select-none flex-col rounded-[var(--radius-sm)]",
|
|
1199
|
-
"px-3 py-2.5 text-sm outline-none",
|
|
1200
|
-
"transition-colors duration-[var(--transition-fast)]",
|
|
1201
|
-
"hover:bg-accent/50 focus:bg-accent/50",
|
|
1202
|
-
"data-[state=checked]:bg-[var(--accent-surface-soft)] data-[state=checked]:text-[var(--brand-primary)]"
|
|
1203
|
-
),
|
|
1204
|
-
children: [
|
|
1205
|
-
/* @__PURE__ */ jsx11(Select.ItemText, { children: /* @__PURE__ */ jsx11("span", { className: "font-medium", children: backend.label }) }),
|
|
1206
|
-
backend.description && /* @__PURE__ */ jsx11("span", { className: "mt-0.5 text-xs text-muted-foreground data-[state=checked]:text-[var(--accent-text)]", children: backend.description })
|
|
1207
|
-
]
|
|
1208
|
-
},
|
|
1209
|
-
backend.type
|
|
1210
|
-
)) })
|
|
1211
|
-
}
|
|
1212
|
-
) })
|
|
1213
|
-
] })
|
|
1214
|
-
] });
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
// src/dashboard/harness-picker.tsx
|
|
1218
|
-
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1219
|
-
var HARNESS_OPTIONS = [
|
|
1220
|
-
{
|
|
1221
|
-
type: "opencode",
|
|
1222
|
-
label: "OpenCode",
|
|
1223
|
-
description: "Default agent \u2014 broad model support, deterministic streaming"
|
|
1224
|
-
},
|
|
1225
|
-
{
|
|
1226
|
-
type: "claude-code",
|
|
1227
|
-
label: "Claude Code",
|
|
1228
|
-
description: "Native Claude skills and tools (requires ANTHROPIC_API_KEY)"
|
|
1229
|
-
},
|
|
1230
|
-
{
|
|
1231
|
-
type: "codex",
|
|
1232
|
-
label: "Codex",
|
|
1233
|
-
description: "OpenAI Codex CLI (requires OPENAI_API_KEY)"
|
|
1234
|
-
},
|
|
1235
|
-
{
|
|
1236
|
-
type: "amp",
|
|
1237
|
-
label: "AMP",
|
|
1238
|
-
description: "Sourcegraph AMP agent"
|
|
1239
|
-
},
|
|
1240
|
-
{
|
|
1241
|
-
type: "factory-droids",
|
|
1242
|
-
label: "Factory Droids",
|
|
1243
|
-
description: "Factory Droid agent"
|
|
1244
|
-
},
|
|
1245
|
-
{
|
|
1246
|
-
type: "cli-base",
|
|
1247
|
-
label: "CLI base (no agent)",
|
|
1248
|
-
description: "Shell tools only \u2014 for non-AI scheduled tasks"
|
|
1249
|
-
}
|
|
1250
|
-
];
|
|
1251
|
-
function HarnessPicker({
|
|
1252
|
-
value,
|
|
1253
|
-
onChange,
|
|
1254
|
-
available,
|
|
1255
|
-
optionsOverride,
|
|
1256
|
-
label = "Agent harness",
|
|
1257
|
-
...rest
|
|
1258
|
-
}) {
|
|
1259
|
-
const allowed = new Set(available ?? HARNESS_OPTIONS.map((h) => h.type));
|
|
1260
|
-
const backends = HARNESS_OPTIONS.filter((h) => allowed.has(h.type)).map((h) => {
|
|
1261
|
-
const override = optionsOverride?.[h.type];
|
|
1262
|
-
return {
|
|
1263
|
-
type: h.type,
|
|
1264
|
-
label: override?.label ?? h.label,
|
|
1265
|
-
description: override?.description ?? h.description
|
|
1266
|
-
};
|
|
1267
|
-
});
|
|
1268
|
-
return /* @__PURE__ */ jsx12(
|
|
1269
|
-
BackendSelector,
|
|
1270
|
-
{
|
|
1271
|
-
backends,
|
|
1272
|
-
selected: value,
|
|
1273
|
-
onChange: (next) => onChange(next),
|
|
1274
|
-
label,
|
|
1275
|
-
...rest
|
|
1276
|
-
}
|
|
1277
|
-
);
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
1142
|
// src/dashboard/dashboard-layout.tsx
|
|
1281
1143
|
import * as React4 from "react";
|
|
1282
1144
|
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1283
|
-
import { Fragment as Fragment7, jsx as
|
|
1145
|
+
import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1284
1146
|
function SettingsIconSmall({ className }) {
|
|
1285
|
-
return /* @__PURE__ */
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1147
|
+
return /* @__PURE__ */ jsxs10("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1148
|
+
/* @__PURE__ */ jsx11("title", { children: "Settings" }),
|
|
1149
|
+
/* @__PURE__ */ jsx11("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
|
|
1150
|
+
/* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "3" })
|
|
1289
1151
|
] });
|
|
1290
1152
|
}
|
|
1291
1153
|
function MenuIcon({ className }) {
|
|
1292
|
-
return /* @__PURE__ */
|
|
1293
|
-
/* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1296
|
-
/* @__PURE__ */
|
|
1154
|
+
return /* @__PURE__ */ jsxs10("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1155
|
+
/* @__PURE__ */ jsx11("title", { children: "Menu icon" }),
|
|
1156
|
+
/* @__PURE__ */ jsx11("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
1157
|
+
/* @__PURE__ */ jsx11("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
1158
|
+
/* @__PURE__ */ jsx11("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
1297
1159
|
] });
|
|
1298
1160
|
}
|
|
1299
1161
|
function XIcon({ className }) {
|
|
1300
|
-
return /* @__PURE__ */
|
|
1301
|
-
/* @__PURE__ */
|
|
1302
|
-
/* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1162
|
+
return /* @__PURE__ */ jsxs10("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1163
|
+
/* @__PURE__ */ jsx11("title", { children: "Close icon" }),
|
|
1164
|
+
/* @__PURE__ */ jsx11("path", { d: "M18 6 6 18" }),
|
|
1165
|
+
/* @__PURE__ */ jsx11("path", { d: "m6 6 12 12" })
|
|
1304
1166
|
] });
|
|
1305
1167
|
}
|
|
1306
1168
|
function formatNotifDate(raw) {
|
|
@@ -1314,7 +1176,7 @@ function DefaultLink2({
|
|
|
1314
1176
|
children,
|
|
1315
1177
|
...rest
|
|
1316
1178
|
}) {
|
|
1317
|
-
return /* @__PURE__ */
|
|
1179
|
+
return /* @__PURE__ */ jsx11("a", { href: href ?? to, className, ...rest, children });
|
|
1318
1180
|
}
|
|
1319
1181
|
function DashboardLayoutInner({
|
|
1320
1182
|
children,
|
|
@@ -1369,16 +1231,16 @@ function DashboardLayoutInner({
|
|
|
1369
1231
|
);
|
|
1370
1232
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1371
1233
|
const buildSidebarContent = React4.useCallback(
|
|
1372
|
-
(showLabels) => /* @__PURE__ */
|
|
1373
|
-
/* @__PURE__ */
|
|
1374
|
-
/* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1234
|
+
(showLabels) => /* @__PURE__ */ jsxs10(Fragment7, { children: [
|
|
1235
|
+
/* @__PURE__ */ jsxs10(SidebarRail, { wide: showLabels, children: [
|
|
1236
|
+
/* @__PURE__ */ jsx11(SidebarRailHeader, { children: /* @__PURE__ */ jsx11(Link, { href: "/", to: "/", className: "p-1 rounded-md transition-colors hover:bg-muted/50", children: /* @__PURE__ */ jsx11(Logo, { variant, size: "sm", iconOnly: true }) }) }),
|
|
1237
|
+
/* @__PURE__ */ jsx11(SidebarRailNav, { children: navItems.map((item, i) => {
|
|
1376
1238
|
const isMode = modeSet.has(item.id);
|
|
1377
1239
|
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
1378
1240
|
const showSep = i > 0 && isMode && !prevIsMode;
|
|
1379
|
-
return /* @__PURE__ */
|
|
1380
|
-
showSep && /* @__PURE__ */
|
|
1381
|
-
isMode ? /* @__PURE__ */
|
|
1241
|
+
return /* @__PURE__ */ jsxs10(React4.Fragment, { children: [
|
|
1242
|
+
showSep && /* @__PURE__ */ jsx11(RailSeparator, {}),
|
|
1243
|
+
isMode ? /* @__PURE__ */ jsx11(
|
|
1382
1244
|
RailModeButton,
|
|
1383
1245
|
{
|
|
1384
1246
|
mode: item.id,
|
|
@@ -1387,7 +1249,7 @@ function DashboardLayoutInner({
|
|
|
1387
1249
|
badge: item.badge,
|
|
1388
1250
|
showLabel: showLabels
|
|
1389
1251
|
}
|
|
1390
|
-
) : /* @__PURE__ */
|
|
1252
|
+
) : /* @__PURE__ */ jsx11(Link, { href: item.href, to: item.href, children: /* @__PURE__ */ jsx11(
|
|
1391
1253
|
RailButton,
|
|
1392
1254
|
{
|
|
1393
1255
|
icon: item.icon,
|
|
@@ -1398,11 +1260,11 @@ function DashboardLayoutInner({
|
|
|
1398
1260
|
) })
|
|
1399
1261
|
] }, item.id);
|
|
1400
1262
|
}) }),
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
onSettingsClick ? /* @__PURE__ */
|
|
1263
|
+
/* @__PURE__ */ jsxs10(SidebarRailFooter, { children: [
|
|
1264
|
+
onSettingsClick ? /* @__PURE__ */ jsx11(RailButton, { icon: SettingsIconSmall, label: "Settings", onClick: onSettingsClick, showLabel: showLabels }) : /* @__PURE__ */ jsx11(Link, { href: settingsHref, to: settingsHref, children: /* @__PURE__ */ jsx11(RailButton, { icon: SettingsIconSmall, label: "Settings", showLabel: showLabels }) }),
|
|
1403
1265
|
railFooter,
|
|
1404
|
-
/* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1266
|
+
/* @__PURE__ */ jsx11(RailSeparator, {}),
|
|
1267
|
+
/* @__PURE__ */ jsx11(
|
|
1406
1268
|
ProfileAvatar,
|
|
1407
1269
|
{
|
|
1408
1270
|
user: sidebarUser,
|
|
@@ -1416,9 +1278,9 @@ function DashboardLayoutInner({
|
|
|
1416
1278
|
)
|
|
1417
1279
|
] })
|
|
1418
1280
|
] }),
|
|
1419
|
-
panels.length > 0 && /* @__PURE__ */
|
|
1420
|
-
/* @__PURE__ */
|
|
1421
|
-
/* @__PURE__ */
|
|
1281
|
+
panels.length > 0 && /* @__PURE__ */ jsxs10(SidebarPanel, { children: [
|
|
1282
|
+
/* @__PURE__ */ jsx11(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
1283
|
+
/* @__PURE__ */ jsx11(SidebarPanelContent, { children: activePanel?.content })
|
|
1422
1284
|
] })
|
|
1423
1285
|
] }),
|
|
1424
1286
|
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional — only the inputs that actually affect the sidebar tree
|
|
@@ -1443,8 +1305,8 @@ function DashboardLayoutInner({
|
|
|
1443
1305
|
);
|
|
1444
1306
|
const sidebarContent = React4.useMemo(() => buildSidebarContent(false), [buildSidebarContent]);
|
|
1445
1307
|
const mobileSidebarContent = React4.useMemo(() => buildSidebarContent(true), [buildSidebarContent]);
|
|
1446
|
-
return /* @__PURE__ */
|
|
1447
|
-
/* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1309
|
+
/* @__PURE__ */ jsxs10(
|
|
1448
1310
|
"nav",
|
|
1449
1311
|
{
|
|
1450
1312
|
className: "fixed top-0 z-50 bg-card border-b border-border flex justify-between items-center px-8 h-14 font-sans text-[13px] tracking-tight transition-[left,width] duration-200 ease-in-out",
|
|
@@ -1453,9 +1315,9 @@ function DashboardLayoutInner({
|
|
|
1453
1315
|
width: hidden ? "100%" : `calc(100% - ${contentMargin}px)`
|
|
1454
1316
|
},
|
|
1455
1317
|
children: [
|
|
1456
|
-
/* @__PURE__ */
|
|
1457
|
-
/* @__PURE__ */
|
|
1458
|
-
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */
|
|
1318
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-8", children: [
|
|
1319
|
+
/* @__PURE__ */ jsx11(Link, { href: "/", to: "/", className: "lg:hidden flex items-center p-1 rounded-md hover:bg-muted/50 transition-colors", children: /* @__PURE__ */ jsx11(Logo, { variant, size: "sm", iconOnly: true }) }),
|
|
1320
|
+
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */ jsx11("div", { className: "hidden md:flex gap-6", children: topNavLinks.map((link) => /* @__PURE__ */ jsx11(
|
|
1459
1321
|
Link,
|
|
1460
1322
|
{
|
|
1461
1323
|
href: link.href,
|
|
@@ -1469,21 +1331,21 @@ function DashboardLayoutInner({
|
|
|
1469
1331
|
link.href
|
|
1470
1332
|
)) })
|
|
1471
1333
|
] }),
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
onNewSandbox && /* @__PURE__ */
|
|
1334
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-4", children: [
|
|
1335
|
+
onNewSandbox && /* @__PURE__ */ jsxs10(
|
|
1474
1336
|
"button",
|
|
1475
1337
|
{
|
|
1476
1338
|
type: "button",
|
|
1477
1339
|
onClick: onNewSandbox,
|
|
1478
1340
|
className: "hidden md:flex items-center gap-2 bg-[var(--btn-primary-bg)] border border-[var(--border-accent)] text-[var(--btn-primary-text)] px-4 py-2 rounded-lg font-bold hover:bg-[var(--btn-primary-hover)] transition-all active:scale-95 text-xs",
|
|
1479
1341
|
children: [
|
|
1480
|
-
/* @__PURE__ */
|
|
1342
|
+
/* @__PURE__ */ jsx11(Plus2, { className: "h-3.5 w-3.5" }),
|
|
1481
1343
|
"New Sandbox"
|
|
1482
1344
|
]
|
|
1483
1345
|
}
|
|
1484
1346
|
),
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__PURE__ */
|
|
1347
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", ref: notifRef, children: [
|
|
1348
|
+
/* @__PURE__ */ jsxs10(
|
|
1487
1349
|
"button",
|
|
1488
1350
|
{
|
|
1489
1351
|
type: "button",
|
|
@@ -1492,15 +1354,15 @@ function DashboardLayoutInner({
|
|
|
1492
1354
|
"aria-label": "Notifications",
|
|
1493
1355
|
"aria-expanded": notificationsOpen,
|
|
1494
1356
|
children: [
|
|
1495
|
-
/* @__PURE__ */
|
|
1496
|
-
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */
|
|
1357
|
+
/* @__PURE__ */ jsx11(Bell, { className: "h-4 w-4" }),
|
|
1358
|
+
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */ jsx11("span", { className: "absolute top-1 right-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1497
1359
|
]
|
|
1498
1360
|
}
|
|
1499
1361
|
),
|
|
1500
|
-
notificationsOpen && /* @__PURE__ */
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
/* @__PURE__ */
|
|
1503
|
-
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */
|
|
1362
|
+
notificationsOpen && /* @__PURE__ */ jsxs10("div", { className: "absolute right-0 top-full mt-2 w-80 rounded-lg border border-border bg-card shadow-lg z-50", children: [
|
|
1363
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
|
|
1364
|
+
/* @__PURE__ */ jsx11("p", { className: "font-bold text-foreground text-sm", children: "Notifications" }),
|
|
1365
|
+
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */ jsx11(
|
|
1504
1366
|
"button",
|
|
1505
1367
|
{
|
|
1506
1368
|
type: "button",
|
|
@@ -1512,11 +1374,11 @@ function DashboardLayoutInner({
|
|
|
1512
1374
|
}
|
|
1513
1375
|
)
|
|
1514
1376
|
] }),
|
|
1515
|
-
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1518
|
-
/* @__PURE__ */
|
|
1519
|
-
] }) : /* @__PURE__ */
|
|
1377
|
+
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center justify-center px-4 py-8 text-center", children: [
|
|
1378
|
+
/* @__PURE__ */ jsx11(Bell, { className: "h-8 w-8 text-muted-foreground/40 mb-2" }),
|
|
1379
|
+
/* @__PURE__ */ jsx11("p", { className: "text-muted-foreground text-sm", children: "No notifications yet" }),
|
|
1380
|
+
/* @__PURE__ */ jsx11("p", { className: "text-muted-foreground/60 text-xs mt-1", children: "We'll notify you about important updates" })
|
|
1381
|
+
] }) : /* @__PURE__ */ jsx11("div", { className: "max-h-80 overflow-y-auto", children: notifData.items.map((n) => /* @__PURE__ */ jsxs10(
|
|
1520
1382
|
"button",
|
|
1521
1383
|
{
|
|
1522
1384
|
type: "button",
|
|
@@ -1528,9 +1390,9 @@ function DashboardLayoutInner({
|
|
|
1528
1390
|
if (!n.read) notifData.onMarkRead?.(n.id);
|
|
1529
1391
|
},
|
|
1530
1392
|
children: [
|
|
1531
|
-
/* @__PURE__ */
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1393
|
+
/* @__PURE__ */ jsx11("p", { className: cn("text-sm", !n.read ? "font-semibold text-foreground" : "text-muted-foreground"), children: n.title }),
|
|
1394
|
+
/* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: n.message }),
|
|
1395
|
+
/* @__PURE__ */ jsx11("p", { className: "text-[10px] text-muted-foreground/50 mt-1", children: formatNotifDate(n.createdAt) })
|
|
1534
1396
|
]
|
|
1535
1397
|
},
|
|
1536
1398
|
n.id
|
|
@@ -1538,7 +1400,7 @@ function DashboardLayoutInner({
|
|
|
1538
1400
|
] })
|
|
1539
1401
|
] })
|
|
1540
1402
|
] }),
|
|
1541
|
-
/* @__PURE__ */
|
|
1403
|
+
/* @__PURE__ */ jsx11(
|
|
1542
1404
|
"button",
|
|
1543
1405
|
{
|
|
1544
1406
|
type: "button",
|
|
@@ -1546,14 +1408,14 @@ function DashboardLayoutInner({
|
|
|
1546
1408
|
className: "rounded-md p-2 hover:bg-muted/50 lg:hidden",
|
|
1547
1409
|
"aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
|
|
1548
1410
|
"aria-expanded": mobileMenuOpen,
|
|
1549
|
-
children: mobileMenuOpen ? /* @__PURE__ */
|
|
1411
|
+
children: mobileMenuOpen ? /* @__PURE__ */ jsx11(XIcon, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx11(MenuIcon, { className: "h-6 w-6" })
|
|
1550
1412
|
}
|
|
1551
1413
|
)
|
|
1552
1414
|
]
|
|
1553
1415
|
}
|
|
1554
1416
|
),
|
|
1555
|
-
mobileMenuOpen && /* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1417
|
+
mobileMenuOpen && /* @__PURE__ */ jsx11("div", { className: "fixed inset-0 z-30 bg-black/50 lg:hidden", onClick: () => setMobileMenuOpen(false), "aria-hidden": "true" }),
|
|
1418
|
+
/* @__PURE__ */ jsx11(
|
|
1557
1419
|
"aside",
|
|
1558
1420
|
{
|
|
1559
1421
|
className: cn(
|
|
@@ -1566,17 +1428,17 @@ function DashboardLayoutInner({
|
|
|
1566
1428
|
children: mobileSidebarContent
|
|
1567
1429
|
}
|
|
1568
1430
|
),
|
|
1569
|
-
/* @__PURE__ */
|
|
1570
|
-
/* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ jsx11(Sidebar, { className: cn("hidden lg:flex", sidebarClassName), children: sidebarContent }),
|
|
1432
|
+
/* @__PURE__ */ jsx11(SidebarContent, { className: cn("pt-16 px-6 pb-8 lg:px-8 bg-background", contentClassName), children }),
|
|
1571
1433
|
footer
|
|
1572
1434
|
] });
|
|
1573
1435
|
}
|
|
1574
1436
|
function DashboardLayout({ defaultPanelOpen, defaultMode, ...props }) {
|
|
1575
|
-
return /* @__PURE__ */
|
|
1437
|
+
return /* @__PURE__ */ jsx11(SidebarProvider, { defaultPanelOpen, defaultMode, hasPanels: (props.panels?.length ?? 0) > 0, children: /* @__PURE__ */ jsx11(DashboardLayoutInner, { defaultPanelOpen, defaultMode, ...props }) });
|
|
1576
1438
|
}
|
|
1577
1439
|
|
|
1578
1440
|
// src/dashboard/profile-selector.tsx
|
|
1579
|
-
import { Check as Check2, ChevronDown
|
|
1441
|
+
import { Check as Check2, ChevronDown, Plus as Plus3, Settings } from "lucide-react";
|
|
1580
1442
|
import { Button as Button2 } from "@tangle-network/ui/primitives";
|
|
1581
1443
|
import { Badge } from "@tangle-network/ui/primitives";
|
|
1582
1444
|
import {
|
|
@@ -1587,7 +1449,7 @@ import {
|
|
|
1587
1449
|
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
1588
1450
|
DropdownMenuTrigger as DropdownMenuTrigger4
|
|
1589
1451
|
} from "@tangle-network/ui/primitives";
|
|
1590
|
-
import { Fragment as Fragment8, jsx as
|
|
1452
|
+
import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1591
1453
|
function ProfileSelector({
|
|
1592
1454
|
profiles,
|
|
1593
1455
|
selectedId,
|
|
@@ -1602,77 +1464,77 @@ function ProfileSelector({
|
|
|
1602
1464
|
const selected = profiles.find((p) => p.id === selectedId);
|
|
1603
1465
|
const builtinProfiles = profiles.filter((p) => p.is_builtin);
|
|
1604
1466
|
const customProfiles = profiles.filter((p) => !p.is_builtin);
|
|
1605
|
-
return /* @__PURE__ */
|
|
1606
|
-
label && /* @__PURE__ */
|
|
1607
|
-
/* @__PURE__ */
|
|
1608
|
-
/* @__PURE__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
1467
|
+
return /* @__PURE__ */ jsxs11("div", { className, children: [
|
|
1468
|
+
label && /* @__PURE__ */ jsx12("label", { className: "mb-2 block font-medium text-sm", children: label }),
|
|
1469
|
+
/* @__PURE__ */ jsxs11(DropdownMenu4, { children: [
|
|
1470
|
+
/* @__PURE__ */ jsx12(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsxs11(Button2, { variant: "outline", className: "w-full justify-between", children: [
|
|
1471
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate", children: selected ? selected.name : placeholder }),
|
|
1472
|
+
/* @__PURE__ */ jsx12(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1611
1473
|
] }) }),
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1474
|
+
/* @__PURE__ */ jsxs11(DropdownMenuContent4, { className: "w-[300px]", align: "start", children: [
|
|
1475
|
+
/* @__PURE__ */ jsxs11(
|
|
1614
1476
|
DropdownMenuItem4,
|
|
1615
1477
|
{
|
|
1616
1478
|
onClick: () => onSelect(null),
|
|
1617
1479
|
className: "flex items-center justify-between",
|
|
1618
1480
|
children: [
|
|
1619
|
-
/* @__PURE__ */
|
|
1620
|
-
!selectedId && /* @__PURE__ */
|
|
1481
|
+
/* @__PURE__ */ jsx12("span", { children: placeholder }),
|
|
1482
|
+
!selectedId && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1621
1483
|
]
|
|
1622
1484
|
}
|
|
1623
1485
|
),
|
|
1624
|
-
builtinProfiles.length > 0 && /* @__PURE__ */
|
|
1625
|
-
/* @__PURE__ */
|
|
1626
|
-
/* @__PURE__ */
|
|
1627
|
-
builtinProfiles.map((profile) => /* @__PURE__ */
|
|
1486
|
+
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1487
|
+
/* @__PURE__ */ jsx12(DropdownMenuSeparator4, {}),
|
|
1488
|
+
/* @__PURE__ */ jsx12(DropdownMenuLabel2, { children: "Built-in Profiles" }),
|
|
1489
|
+
builtinProfiles.map((profile) => /* @__PURE__ */ jsxs11(
|
|
1628
1490
|
DropdownMenuItem4,
|
|
1629
1491
|
{
|
|
1630
1492
|
onClick: () => onSelect(profile),
|
|
1631
1493
|
className: "flex flex-col items-start gap-1",
|
|
1632
1494
|
children: [
|
|
1633
|
-
/* @__PURE__ */
|
|
1634
|
-
/* @__PURE__ */
|
|
1635
|
-
/* @__PURE__ */
|
|
1636
|
-
profile.extends && /* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center justify-between", children: [
|
|
1496
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
1497
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
|
|
1498
|
+
profile.extends && /* @__PURE__ */ jsxs11(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
|
|
1637
1499
|
"extends ",
|
|
1638
1500
|
profile.extends
|
|
1639
1501
|
] })
|
|
1640
1502
|
] }),
|
|
1641
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1503
|
+
selectedId === profile.id && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1642
1504
|
] }),
|
|
1643
|
-
profile.description && /* @__PURE__ */
|
|
1505
|
+
profile.description && /* @__PURE__ */ jsx12("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
1644
1506
|
]
|
|
1645
1507
|
},
|
|
1646
1508
|
profile.id
|
|
1647
1509
|
))
|
|
1648
1510
|
] }),
|
|
1649
|
-
customProfiles.length > 0 && /* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1652
|
-
customProfiles.map((profile) => /* @__PURE__ */
|
|
1511
|
+
customProfiles.length > 0 && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1512
|
+
/* @__PURE__ */ jsx12(DropdownMenuSeparator4, {}),
|
|
1513
|
+
/* @__PURE__ */ jsx12(DropdownMenuLabel2, { children: "Custom Profiles" }),
|
|
1514
|
+
customProfiles.map((profile) => /* @__PURE__ */ jsxs11(
|
|
1653
1515
|
DropdownMenuItem4,
|
|
1654
1516
|
{
|
|
1655
1517
|
onClick: () => onSelect(profile),
|
|
1656
1518
|
className: "flex flex-col items-start gap-1",
|
|
1657
1519
|
children: [
|
|
1658
|
-
/* @__PURE__ */
|
|
1659
|
-
/* @__PURE__ */
|
|
1660
|
-
/* @__PURE__ */
|
|
1661
|
-
profile.model && /* @__PURE__ */
|
|
1520
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex w-full items-center justify-between", children: [
|
|
1521
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
1522
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
|
|
1523
|
+
profile.model && /* @__PURE__ */ jsx12(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
1662
1524
|
] }),
|
|
1663
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1525
|
+
selectedId === profile.id && /* @__PURE__ */ jsx12(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1664
1526
|
] }),
|
|
1665
|
-
profile.description && /* @__PURE__ */
|
|
1666
|
-
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */
|
|
1667
|
-
/* @__PURE__ */
|
|
1527
|
+
profile.description && /* @__PURE__ */ jsx12("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
1528
|
+
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs11("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
1529
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
1668
1530
|
profile.metrics.total_runs,
|
|
1669
1531
|
" runs"
|
|
1670
1532
|
] }),
|
|
1671
|
-
/* @__PURE__ */
|
|
1533
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
1672
1534
|
profile.metrics.success_rate.toFixed(0),
|
|
1673
1535
|
"% success"
|
|
1674
1536
|
] }),
|
|
1675
|
-
/* @__PURE__ */
|
|
1537
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
1676
1538
|
"~",
|
|
1677
1539
|
(profile.metrics.avg_duration_ms / 1e3).toFixed(1),
|
|
1678
1540
|
"s avg"
|
|
@@ -1683,26 +1545,26 @@ function ProfileSelector({
|
|
|
1683
1545
|
profile.id
|
|
1684
1546
|
))
|
|
1685
1547
|
] }),
|
|
1686
|
-
(onCreateClick || onManageClick) && /* @__PURE__ */
|
|
1687
|
-
/* @__PURE__ */
|
|
1688
|
-
onCreateClick && /* @__PURE__ */
|
|
1548
|
+
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs11(Fragment8, { children: [
|
|
1549
|
+
/* @__PURE__ */ jsx12(DropdownMenuSeparator4, {}),
|
|
1550
|
+
onCreateClick && /* @__PURE__ */ jsxs11(
|
|
1689
1551
|
DropdownMenuItem4,
|
|
1690
1552
|
{
|
|
1691
1553
|
onClick: onCreateClick,
|
|
1692
1554
|
className: "text-[var(--surface-info-text)]",
|
|
1693
1555
|
children: [
|
|
1694
|
-
/* @__PURE__ */
|
|
1556
|
+
/* @__PURE__ */ jsx12(Plus3, { className: "mr-2 h-4 w-4" }),
|
|
1695
1557
|
"Create New Profile"
|
|
1696
1558
|
]
|
|
1697
1559
|
}
|
|
1698
1560
|
),
|
|
1699
|
-
onManageClick && /* @__PURE__ */
|
|
1561
|
+
onManageClick && /* @__PURE__ */ jsxs11(
|
|
1700
1562
|
DropdownMenuItem4,
|
|
1701
1563
|
{
|
|
1702
1564
|
onClick: onManageClick,
|
|
1703
1565
|
className: "text-muted-foreground",
|
|
1704
1566
|
children: [
|
|
1705
|
-
/* @__PURE__ */
|
|
1567
|
+
/* @__PURE__ */ jsx12(Settings, { className: "mr-2 h-4 w-4" }),
|
|
1706
1568
|
"Manage Profiles"
|
|
1707
1569
|
]
|
|
1708
1570
|
}
|
|
@@ -1728,26 +1590,26 @@ function ProfileComparison({
|
|
|
1728
1590
|
const fastestProfile = profilesWithMetrics.reduce(
|
|
1729
1591
|
(best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
|
|
1730
1592
|
);
|
|
1731
|
-
return /* @__PURE__ */
|
|
1732
|
-
/* @__PURE__ */
|
|
1733
|
-
/* @__PURE__ */
|
|
1593
|
+
return /* @__PURE__ */ jsxs11("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
|
|
1594
|
+
/* @__PURE__ */ jsx12("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
|
|
1595
|
+
/* @__PURE__ */ jsx12("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
|
|
1734
1596
|
const isBestSuccess = profile.id === bestSuccess.id;
|
|
1735
1597
|
const isFastest = profile.id === fastestProfile.id;
|
|
1736
|
-
return /* @__PURE__ */
|
|
1598
|
+
return /* @__PURE__ */ jsxs11(
|
|
1737
1599
|
"div",
|
|
1738
1600
|
{
|
|
1739
1601
|
className: "flex items-center justify-between gap-4",
|
|
1740
1602
|
children: [
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
isBestSuccess && /* @__PURE__ */
|
|
1744
|
-
isFastest && !isBestSuccess && /* @__PURE__ */
|
|
1603
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
|
|
1604
|
+
/* @__PURE__ */ jsx12("span", { className: "font-medium", children: profile.name }),
|
|
1605
|
+
isBestSuccess && /* @__PURE__ */ jsx12(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
|
|
1606
|
+
isFastest && !isBestSuccess && /* @__PURE__ */ jsx12(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
|
|
1745
1607
|
] }),
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
1748
|
-
/* @__PURE__ */
|
|
1608
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
1609
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
1610
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground", children: "Success:" }),
|
|
1749
1611
|
" ",
|
|
1750
|
-
/* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ jsxs11(
|
|
1751
1613
|
"span",
|
|
1752
1614
|
{
|
|
1753
1615
|
className: (profile.metrics?.success_rate ?? 0) >= 80 ? "text-[var(--surface-success-text)]" : (profile.metrics?.success_rate ?? 0) >= 50 ? "text-[var(--surface-warning-text)]" : "text-[var(--surface-danger-text)]",
|
|
@@ -1758,13 +1620,13 @@ function ProfileComparison({
|
|
|
1758
1620
|
}
|
|
1759
1621
|
)
|
|
1760
1622
|
] }),
|
|
1761
|
-
/* @__PURE__ */
|
|
1762
|
-
/* @__PURE__ */
|
|
1623
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
1624
|
+
/* @__PURE__ */ jsx12("span", { className: "text-muted-foreground", children: "Avg:" }),
|
|
1763
1625
|
" ",
|
|
1764
1626
|
((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
|
|
1765
1627
|
"s"
|
|
1766
1628
|
] }),
|
|
1767
|
-
/* @__PURE__ */
|
|
1629
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-muted-foreground", children: [
|
|
1768
1630
|
profile.metrics?.total_runs,
|
|
1769
1631
|
" runs"
|
|
1770
1632
|
] })
|
|
@@ -1777,6 +1639,141 @@ function ProfileComparison({
|
|
|
1777
1639
|
] });
|
|
1778
1640
|
}
|
|
1779
1641
|
|
|
1642
|
+
// src/dashboard/metric-area-chart.tsx
|
|
1643
|
+
import * as React5 from "react";
|
|
1644
|
+
import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1645
|
+
var TONE_VARS = {
|
|
1646
|
+
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
1647
|
+
success: "var(--status-running, #22c55e)",
|
|
1648
|
+
warning: "var(--status-creating, #eab308)",
|
|
1649
|
+
danger: "var(--status-error, #ef4444)"
|
|
1650
|
+
};
|
|
1651
|
+
function buildSegments(points, width, height, yMax) {
|
|
1652
|
+
if (points.length === 0 || yMax <= 0) return [];
|
|
1653
|
+
const t0 = points[0].at;
|
|
1654
|
+
const t1 = points[points.length - 1].at;
|
|
1655
|
+
const span = Math.max(1, t1 - t0);
|
|
1656
|
+
const x = (at) => points.length === 1 ? width / 2 : (at - t0) / span * width;
|
|
1657
|
+
const y = (v) => height - Math.min(1, Math.max(0, v / yMax)) * height;
|
|
1658
|
+
const segments = [];
|
|
1659
|
+
let run = [];
|
|
1660
|
+
const flush = () => {
|
|
1661
|
+
if (run.length === 0) return;
|
|
1662
|
+
const line = run.map((p, i) => `${i === 0 ? "M" : "L"}${p.px.toFixed(2)},${p.py.toFixed(2)}`).join(" ");
|
|
1663
|
+
const first = run[0];
|
|
1664
|
+
const last = run[run.length - 1];
|
|
1665
|
+
const area = `${line} L${last.px.toFixed(2)},${height} L${first.px.toFixed(2)},${height} Z`;
|
|
1666
|
+
segments.push({ path: line, area });
|
|
1667
|
+
run = [];
|
|
1668
|
+
};
|
|
1669
|
+
for (const point of points) {
|
|
1670
|
+
if (point.value === null) {
|
|
1671
|
+
flush();
|
|
1672
|
+
continue;
|
|
1673
|
+
}
|
|
1674
|
+
run.push({ px: x(point.at), py: y(point.value) });
|
|
1675
|
+
}
|
|
1676
|
+
flush();
|
|
1677
|
+
return segments;
|
|
1678
|
+
}
|
|
1679
|
+
function MetricAreaChart({
|
|
1680
|
+
points,
|
|
1681
|
+
label,
|
|
1682
|
+
formatValue,
|
|
1683
|
+
maxValue,
|
|
1684
|
+
detail,
|
|
1685
|
+
tone = "primary",
|
|
1686
|
+
height = 96,
|
|
1687
|
+
emptyState,
|
|
1688
|
+
className
|
|
1689
|
+
}) {
|
|
1690
|
+
const gradientId = React5.useId();
|
|
1691
|
+
const width = 400;
|
|
1692
|
+
const values = points.map((p) => p.value).filter((v) => v !== null);
|
|
1693
|
+
const latest = values.length > 0 ? values[values.length - 1] : null;
|
|
1694
|
+
const observedMax = values.length > 0 ? Math.max(...values) : 0;
|
|
1695
|
+
const yMax = maxValue ?? (observedMax > 0 ? observedMax * 1.1 : 1);
|
|
1696
|
+
const segments = buildSegments(points, width, height, yMax);
|
|
1697
|
+
const color = TONE_VARS[tone];
|
|
1698
|
+
return /* @__PURE__ */ jsxs12(
|
|
1699
|
+
"div",
|
|
1700
|
+
{
|
|
1701
|
+
className: cn(
|
|
1702
|
+
"rounded-lg border border-border bg-card p-4 shadow-sm",
|
|
1703
|
+
className
|
|
1704
|
+
),
|
|
1705
|
+
"data-testid": `metric-chart-${label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
1706
|
+
children: [
|
|
1707
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-baseline justify-between gap-3", children: [
|
|
1708
|
+
/* @__PURE__ */ jsx13("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-[0.12em]", children: label }),
|
|
1709
|
+
/* @__PURE__ */ jsxs12("div", { className: "text-right", children: [
|
|
1710
|
+
/* @__PURE__ */ jsx13("span", { className: "font-semibold text-foreground text-xl tabular-nums tracking-tight", children: latest === null ? "\u2014" : formatValue(latest) }),
|
|
1711
|
+
detail && /* @__PURE__ */ jsx13("span", { className: "ml-1.5 text-muted-foreground text-xs", children: detail })
|
|
1712
|
+
] })
|
|
1713
|
+
] }),
|
|
1714
|
+
/* @__PURE__ */ jsx13("div", { className: "mt-3", children: values.length === 0 ? /* @__PURE__ */ jsx13(
|
|
1715
|
+
"div",
|
|
1716
|
+
{
|
|
1717
|
+
className: "flex items-center justify-center text-muted-foreground text-xs",
|
|
1718
|
+
style: { height },
|
|
1719
|
+
children: emptyState ?? "Waiting for samples\u2026"
|
|
1720
|
+
}
|
|
1721
|
+
) : /* @__PURE__ */ jsxs12(
|
|
1722
|
+
"svg",
|
|
1723
|
+
{
|
|
1724
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
1725
|
+
preserveAspectRatio: "none",
|
|
1726
|
+
className: "block w-full",
|
|
1727
|
+
style: { height },
|
|
1728
|
+
role: "img",
|
|
1729
|
+
"aria-label": `${label} chart`,
|
|
1730
|
+
children: [
|
|
1731
|
+
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */ jsx13(
|
|
1732
|
+
"line",
|
|
1733
|
+
{
|
|
1734
|
+
x1: 0,
|
|
1735
|
+
x2: width,
|
|
1736
|
+
y1: height * fraction,
|
|
1737
|
+
y2: height * fraction,
|
|
1738
|
+
stroke: "currentColor",
|
|
1739
|
+
className: "text-border",
|
|
1740
|
+
strokeWidth: 1,
|
|
1741
|
+
strokeDasharray: "3 5",
|
|
1742
|
+
vectorEffect: "non-scaling-stroke"
|
|
1743
|
+
},
|
|
1744
|
+
fraction
|
|
1745
|
+
)),
|
|
1746
|
+
/* @__PURE__ */ jsx13("defs", { children: /* @__PURE__ */ jsxs12("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
1747
|
+
/* @__PURE__ */ jsx13("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
1748
|
+
/* @__PURE__ */ jsx13("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
1749
|
+
] }) }),
|
|
1750
|
+
segments.map((segment) => /* @__PURE__ */ jsxs12(React5.Fragment, { children: [
|
|
1751
|
+
/* @__PURE__ */ jsx13("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
1752
|
+
/* @__PURE__ */ jsx13(
|
|
1753
|
+
"path",
|
|
1754
|
+
{
|
|
1755
|
+
d: segment.path,
|
|
1756
|
+
fill: "none",
|
|
1757
|
+
stroke: color,
|
|
1758
|
+
strokeWidth: 1.75,
|
|
1759
|
+
vectorEffect: "non-scaling-stroke",
|
|
1760
|
+
strokeLinejoin: "round",
|
|
1761
|
+
strokeLinecap: "round"
|
|
1762
|
+
}
|
|
1763
|
+
)
|
|
1764
|
+
] }, segment.path))
|
|
1765
|
+
]
|
|
1766
|
+
}
|
|
1767
|
+
) }),
|
|
1768
|
+
/* @__PURE__ */ jsxs12("div", { className: "mt-1.5 flex justify-between text-[10px] text-muted-foreground tabular-nums", children: [
|
|
1769
|
+
/* @__PURE__ */ jsx13("span", { children: values.length > 0 ? formatValue(0) : "" }),
|
|
1770
|
+
/* @__PURE__ */ jsx13("span", { children: values.length > 0 ? formatValue(yMax) : "" })
|
|
1771
|
+
] })
|
|
1772
|
+
]
|
|
1773
|
+
}
|
|
1774
|
+
);
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1780
1777
|
// src/dashboard/variant-list.tsx
|
|
1781
1778
|
import {
|
|
1782
1779
|
Check as Check3,
|
|
@@ -1790,7 +1787,7 @@ import {
|
|
|
1790
1787
|
} from "lucide-react";
|
|
1791
1788
|
import { Button as Button3 } from "@tangle-network/ui/primitives";
|
|
1792
1789
|
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
1793
|
-
import { Fragment as
|
|
1790
|
+
import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1794
1791
|
var statusConfig = {
|
|
1795
1792
|
pending: {
|
|
1796
1793
|
icon: Clock3,
|
|
@@ -1874,7 +1871,7 @@ function VariantList({
|
|
|
1874
1871
|
isActioning,
|
|
1875
1872
|
className
|
|
1876
1873
|
}) {
|
|
1877
|
-
return /* @__PURE__ */
|
|
1874
|
+
return /* @__PURE__ */ jsx14("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
|
|
1878
1875
|
const status = statusConfig[variant.status];
|
|
1879
1876
|
const StatusIcon = status.icon;
|
|
1880
1877
|
const isSelected = variant.id === selectedId;
|
|
@@ -1886,7 +1883,7 @@ function VariantList({
|
|
|
1886
1883
|
children: [
|
|
1887
1884
|
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
1888
1885
|
/* @__PURE__ */ jsxs13(Badge2, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
|
|
1889
|
-
/* @__PURE__ */
|
|
1886
|
+
/* @__PURE__ */ jsx14(
|
|
1890
1887
|
StatusIcon,
|
|
1891
1888
|
{
|
|
1892
1889
|
className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
|
|
@@ -1894,26 +1891,26 @@ function VariantList({
|
|
|
1894
1891
|
),
|
|
1895
1892
|
status.label
|
|
1896
1893
|
] }),
|
|
1897
|
-
/* @__PURE__ */
|
|
1894
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
|
|
1898
1895
|
variant.sublabel && /* @__PURE__ */ jsxs13("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
1899
1896
|
"(",
|
|
1900
1897
|
variant.sublabel,
|
|
1901
1898
|
")"
|
|
1902
1899
|
] }),
|
|
1903
1900
|
variant.durationMs && /* @__PURE__ */ jsxs13("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1904
|
-
/* @__PURE__ */
|
|
1901
|
+
/* @__PURE__ */ jsx14(Timer, { className: "h-3 w-3" }),
|
|
1905
1902
|
(variant.durationMs / 1e3).toFixed(1),
|
|
1906
1903
|
"s"
|
|
1907
1904
|
] }),
|
|
1908
1905
|
/* @__PURE__ */ jsxs13("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
1909
|
-
variant.outcome && /* @__PURE__ */
|
|
1906
|
+
variant.outcome && /* @__PURE__ */ jsx14(
|
|
1910
1907
|
Badge2,
|
|
1911
1908
|
{
|
|
1912
1909
|
className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
|
|
1913
1910
|
children: outcomeConfig[variant.outcome].label
|
|
1914
1911
|
}
|
|
1915
1912
|
),
|
|
1916
|
-
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs13(
|
|
1913
|
+
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs13(Fragment10, { children: [
|
|
1917
1914
|
/* @__PURE__ */ jsxs13(
|
|
1918
1915
|
Button3,
|
|
1919
1916
|
{
|
|
@@ -1926,7 +1923,7 @@ function VariantList({
|
|
|
1926
1923
|
},
|
|
1927
1924
|
disabled: isActioning === variant.id,
|
|
1928
1925
|
children: [
|
|
1929
|
-
/* @__PURE__ */
|
|
1926
|
+
/* @__PURE__ */ jsx14(Check3, { className: "mr-1 h-3 w-3" }),
|
|
1930
1927
|
"Accept"
|
|
1931
1928
|
]
|
|
1932
1929
|
}
|
|
@@ -1943,13 +1940,13 @@ function VariantList({
|
|
|
1943
1940
|
},
|
|
1944
1941
|
disabled: isActioning === variant.id,
|
|
1945
1942
|
children: [
|
|
1946
|
-
/* @__PURE__ */
|
|
1943
|
+
/* @__PURE__ */ jsx14(X, { className: "mr-1 h-3 w-3" }),
|
|
1947
1944
|
"Reject"
|
|
1948
1945
|
]
|
|
1949
1946
|
}
|
|
1950
1947
|
)
|
|
1951
1948
|
] }),
|
|
1952
|
-
variant.detailsUrl && /* @__PURE__ */
|
|
1949
|
+
variant.detailsUrl && /* @__PURE__ */ jsx14(
|
|
1953
1950
|
Button3,
|
|
1954
1951
|
{
|
|
1955
1952
|
variant: "ghost",
|
|
@@ -1959,13 +1956,13 @@ function VariantList({
|
|
|
1959
1956
|
e.stopPropagation();
|
|
1960
1957
|
window.open(variant.detailsUrl, "_blank");
|
|
1961
1958
|
},
|
|
1962
|
-
children: /* @__PURE__ */
|
|
1959
|
+
children: /* @__PURE__ */ jsx14(ExternalLink2, { className: "h-3.5 w-3.5" })
|
|
1963
1960
|
}
|
|
1964
1961
|
)
|
|
1965
1962
|
] })
|
|
1966
1963
|
] }),
|
|
1967
|
-
variant.error && /* @__PURE__ */
|
|
1968
|
-
variant.summary && /* @__PURE__ */
|
|
1964
|
+
variant.error && /* @__PURE__ */ jsx14("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
|
|
1965
|
+
variant.summary && /* @__PURE__ */ jsx14("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
|
|
1969
1966
|
]
|
|
1970
1967
|
},
|
|
1971
1968
|
variant.id
|
|
@@ -1976,7 +1973,7 @@ function VariantList({
|
|
|
1976
1973
|
// src/dashboard/system-logs.tsx
|
|
1977
1974
|
import { Terminal as Terminal3 } from "lucide-react";
|
|
1978
1975
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
|
|
1979
|
-
import { jsx as
|
|
1976
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1980
1977
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
1981
1978
|
const [logs, setLogs] = useState4([]);
|
|
1982
1979
|
const [error, setError] = useState4(null);
|
|
@@ -2032,15 +2029,15 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2032
2029
|
return /* @__PURE__ */ jsxs14("div", { className: cn("flex flex-col h-full bg-background text-foreground font-mono text-sm leading-relaxed overflow-hidden rounded-lg border border-border", className), children: [
|
|
2033
2030
|
/* @__PURE__ */ jsxs14("div", { className: "flex-none flex items-center justify-between border-b border-border bg-muted/50 backdrop-blur-md px-4 py-2", children: [
|
|
2034
2031
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
2035
|
-
/* @__PURE__ */
|
|
2036
|
-
/* @__PURE__ */
|
|
2032
|
+
/* @__PURE__ */ jsx15(Terminal3, { className: "h-4 w-4 text-primary animate-pulse" }),
|
|
2033
|
+
/* @__PURE__ */ jsx15("span", { className: "font-bold text-xs uppercase tracking-widest text-muted-foreground", children: "System Traces" })
|
|
2037
2034
|
] }),
|
|
2038
2035
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
|
|
2039
2036
|
error && /* @__PURE__ */ jsxs14("span", { className: "text-destructive text-xs flex items-center gap-1", children: [
|
|
2040
|
-
/* @__PURE__ */
|
|
2037
|
+
/* @__PURE__ */ jsx15("span", { className: "w-2 h-2 rounded-full bg-destructive animate-ping" }),
|
|
2041
2038
|
" Error fetching logs"
|
|
2042
2039
|
] }),
|
|
2043
|
-
/* @__PURE__ */
|
|
2040
|
+
/* @__PURE__ */ jsx15(
|
|
2044
2041
|
"button",
|
|
2045
2042
|
{
|
|
2046
2043
|
onClick: () => {
|
|
@@ -2055,13 +2052,13 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2055
2052
|
)
|
|
2056
2053
|
] })
|
|
2057
2054
|
] }),
|
|
2058
|
-
/* @__PURE__ */
|
|
2055
|
+
/* @__PURE__ */ jsx15(
|
|
2059
2056
|
"div",
|
|
2060
2057
|
{
|
|
2061
2058
|
ref: scrollRef,
|
|
2062
2059
|
onScroll: handleScroll,
|
|
2063
2060
|
className: "flex-1 overflow-y-auto p-4 space-y-1",
|
|
2064
|
-
children: logs.length === 0 && !error ? /* @__PURE__ */
|
|
2061
|
+
children: logs.length === 0 && !error ? /* @__PURE__ */ jsx15("div", { className: "flex h-full items-center justify-center text-muted-foreground italic", children: "Waiting for orchestrator logs..." }) : logs.map((log, i) => /* @__PURE__ */ jsxs14("div", { className: "break-words", children: [
|
|
2065
2062
|
/* @__PURE__ */ jsxs14("span", { className: "text-muted-foreground mr-3 select-none", children: [
|
|
2066
2063
|
"[",
|
|
2067
2064
|
log.timestamp || i.toString().padStart(4, "0"),
|
|
@@ -2077,7 +2074,7 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2077
2074
|
log.scope,
|
|
2078
2075
|
"]"
|
|
2079
2076
|
] }),
|
|
2080
|
-
/* @__PURE__ */
|
|
2077
|
+
/* @__PURE__ */ jsx15("span", { className: log.level.toUpperCase() === "ERROR" || log.message.toLowerCase().includes("failed") ? "text-destructive" : log.level.toUpperCase() === "WARN" ? "text-warning" : "text-foreground", children: log.message })
|
|
2081
2078
|
] }, `${log.timestamp}-${log.scope}-${i}`))
|
|
2082
2079
|
}
|
|
2083
2080
|
)
|
|
@@ -2088,50 +2085,50 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2088
2085
|
import { Clock as Clock4, Layers, MessageSquare, DollarSign } from "lucide-react";
|
|
2089
2086
|
import { StatCard } from "@tangle-network/ui/primitives";
|
|
2090
2087
|
import { Skeleton as Skeleton2 } from "@tangle-network/ui/primitives";
|
|
2091
|
-
import { jsx as
|
|
2088
|
+
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2092
2089
|
function UsageSummary({ data, loading = false, className }) {
|
|
2093
2090
|
if (loading || !data) {
|
|
2094
|
-
return /* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsx16("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx16(Skeleton2, { className: "h-28 rounded-xl" }, i)) });
|
|
2095
2092
|
}
|
|
2096
2093
|
return /* @__PURE__ */ jsxs15("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: [
|
|
2097
|
-
/* @__PURE__ */
|
|
2094
|
+
/* @__PURE__ */ jsx16(
|
|
2098
2095
|
StatCard,
|
|
2099
2096
|
{
|
|
2100
2097
|
variant: "sandbox",
|
|
2101
2098
|
title: "Compute Hours",
|
|
2102
2099
|
value: data.computeHours.toFixed(1),
|
|
2103
2100
|
subtitle: "This billing period",
|
|
2104
|
-
icon: /* @__PURE__ */
|
|
2101
|
+
icon: /* @__PURE__ */ jsx16(Clock4, { className: "h-5 w-5" })
|
|
2105
2102
|
}
|
|
2106
2103
|
),
|
|
2107
|
-
/* @__PURE__ */
|
|
2104
|
+
/* @__PURE__ */ jsx16(
|
|
2108
2105
|
StatCard,
|
|
2109
2106
|
{
|
|
2110
2107
|
variant: "sandbox",
|
|
2111
2108
|
title: "Active Sessions",
|
|
2112
2109
|
value: data.activeSessions,
|
|
2113
2110
|
subtitle: "Currently running",
|
|
2114
|
-
icon: /* @__PURE__ */
|
|
2111
|
+
icon: /* @__PURE__ */ jsx16(Layers, { className: "h-5 w-5" })
|
|
2115
2112
|
}
|
|
2116
2113
|
),
|
|
2117
|
-
/* @__PURE__ */
|
|
2114
|
+
/* @__PURE__ */ jsx16(
|
|
2118
2115
|
StatCard,
|
|
2119
2116
|
{
|
|
2120
2117
|
variant: "sandbox",
|
|
2121
2118
|
title: "Messages Sent",
|
|
2122
2119
|
value: data.messagesSent.toLocaleString(),
|
|
2123
2120
|
subtitle: "Agent interactions",
|
|
2124
|
-
icon: /* @__PURE__ */
|
|
2121
|
+
icon: /* @__PURE__ */ jsx16(MessageSquare, { className: "h-5 w-5" })
|
|
2125
2122
|
}
|
|
2126
2123
|
),
|
|
2127
|
-
/* @__PURE__ */
|
|
2124
|
+
/* @__PURE__ */ jsx16(
|
|
2128
2125
|
StatCard,
|
|
2129
2126
|
{
|
|
2130
2127
|
variant: "sandbox",
|
|
2131
2128
|
title: "Estimated Cost",
|
|
2132
2129
|
value: `$${data.estimatedCost.toFixed(2)}`,
|
|
2133
2130
|
subtitle: "This billing period",
|
|
2134
|
-
icon: /* @__PURE__ */
|
|
2131
|
+
icon: /* @__PURE__ */ jsx16(DollarSign, { className: "h-5 w-5" })
|
|
2135
2132
|
}
|
|
2136
2133
|
)
|
|
2137
2134
|
] });
|
|
@@ -2139,17 +2136,17 @@ function UsageSummary({ data, loading = false, className }) {
|
|
|
2139
2136
|
|
|
2140
2137
|
// src/dashboard/git-panel.tsx
|
|
2141
2138
|
import { GitBranch, GitCommit, FileEdit, FilePlus, File } from "lucide-react";
|
|
2142
|
-
import { jsx as
|
|
2139
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2143
2140
|
function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
2144
2141
|
if (loading) {
|
|
2145
|
-
return /* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2142
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2143
|
+
/* @__PURE__ */ jsx17("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2147
2144
|
"Loading git info..."
|
|
2148
2145
|
] }) });
|
|
2149
2146
|
}
|
|
2150
2147
|
if (!status) {
|
|
2151
|
-
return /* @__PURE__ */
|
|
2152
|
-
/* @__PURE__ */
|
|
2148
|
+
return /* @__PURE__ */ jsx17("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2149
|
+
/* @__PURE__ */ jsx17(GitBranch, { className: "h-4 w-4" }),
|
|
2153
2150
|
"No git repository detected"
|
|
2154
2151
|
] }) });
|
|
2155
2152
|
}
|
|
@@ -2157,38 +2154,38 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2157
2154
|
return /* @__PURE__ */ jsxs16("div", { className: cn("rounded-lg border border-border bg-card overflow-hidden", className), children: [
|
|
2158
2155
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between border-b border-border bg-muted/30 px-4 py-3", children: [
|
|
2159
2156
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
/* @__PURE__ */
|
|
2157
|
+
/* @__PURE__ */ jsx17(GitBranch, { className: "h-4 w-4 text-primary" }),
|
|
2158
|
+
/* @__PURE__ */ jsx17("span", { className: "text-sm font-bold text-foreground", children: status.branch }),
|
|
2162
2159
|
status.isDirty && /* @__PURE__ */ jsxs16("span", { className: "rounded-full bg-[var(--surface-warning-bg)] px-1.5 py-0.5 text-[10px] font-bold text-[var(--surface-warning-text)]", children: [
|
|
2163
2160
|
changedCount,
|
|
2164
2161
|
" change",
|
|
2165
2162
|
changedCount !== 1 ? "s" : ""
|
|
2166
2163
|
] })
|
|
2167
2164
|
] }),
|
|
2168
|
-
onRefresh && /* @__PURE__ */
|
|
2165
|
+
onRefresh && /* @__PURE__ */ jsx17("button", { type: "button", onClick: onRefresh, className: "text-xs text-muted-foreground hover:text-foreground transition-colors", children: "Refresh" })
|
|
2169
2166
|
] }),
|
|
2170
|
-
changedCount > 0 && /* @__PURE__ */
|
|
2167
|
+
changedCount > 0 && /* @__PURE__ */ jsx17("div", { className: "border-b border-border px-4 py-3", children: /* @__PURE__ */ jsxs16("div", { className: "space-y-1.5", children: [
|
|
2171
2168
|
status.staged.map((f) => /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2172
|
-
/* @__PURE__ */
|
|
2173
|
-
/* @__PURE__ */
|
|
2174
|
-
/* @__PURE__ */
|
|
2169
|
+
/* @__PURE__ */ jsx17(FilePlus, { className: "h-3 w-3 text-[var(--surface-success-text)]" }),
|
|
2170
|
+
/* @__PURE__ */ jsx17("span", { className: "font-mono text-foreground truncate", children: f }),
|
|
2171
|
+
/* @__PURE__ */ jsx17("span", { className: "text-[var(--surface-success-text)] text-[10px] font-bold ml-auto", children: "STAGED" })
|
|
2175
2172
|
] }, `s-${f}`)),
|
|
2176
2173
|
status.modified.map((f) => /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2177
|
-
/* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
2174
|
+
/* @__PURE__ */ jsx17(FileEdit, { className: "h-3 w-3 text-[var(--surface-warning-text)]" }),
|
|
2175
|
+
/* @__PURE__ */ jsx17("span", { className: "font-mono text-foreground truncate", children: f })
|
|
2179
2176
|
] }, `m-${f}`)),
|
|
2180
2177
|
status.untracked.map((f) => /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2181
|
-
/* @__PURE__ */
|
|
2182
|
-
/* @__PURE__ */
|
|
2178
|
+
/* @__PURE__ */ jsx17(File, { className: "h-3 w-3 text-muted-foreground" }),
|
|
2179
|
+
/* @__PURE__ */ jsx17("span", { className: "font-mono text-muted-foreground truncate", children: f })
|
|
2183
2180
|
] }, `u-${f}`))
|
|
2184
2181
|
] }) }),
|
|
2185
2182
|
log.length > 0 && /* @__PURE__ */ jsxs16("div", { className: "px-4 py-3", children: [
|
|
2186
|
-
/* @__PURE__ */
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2183
|
+
/* @__PURE__ */ jsx17("div", { className: "mb-2 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Recent Commits" }),
|
|
2184
|
+
/* @__PURE__ */ jsx17("div", { className: "space-y-2", children: log.slice(0, 5).map((commit) => /* @__PURE__ */ jsxs16("div", { className: "flex items-start gap-2 text-xs", children: [
|
|
2185
|
+
/* @__PURE__ */ jsx17(GitCommit, { className: "h-3 w-3 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2189
2186
|
/* @__PURE__ */ jsxs16("div", { className: "min-w-0", children: [
|
|
2190
|
-
/* @__PURE__ */
|
|
2191
|
-
/* @__PURE__ */
|
|
2187
|
+
/* @__PURE__ */ jsx17("span", { className: "font-mono text-primary mr-1.5", children: commit.shortSha }),
|
|
2188
|
+
/* @__PURE__ */ jsx17("span", { className: "text-foreground", children: commit.message })
|
|
2192
2189
|
] })
|
|
2193
2190
|
] }, commit.shortSha)) })
|
|
2194
2191
|
] }),
|
|
@@ -2208,14 +2205,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2208
2205
|
}
|
|
2209
2206
|
|
|
2210
2207
|
// src/dashboard/ports-list.tsx
|
|
2211
|
-
import * as
|
|
2208
|
+
import * as React7 from "react";
|
|
2212
2209
|
import { Copy as Copy3, Check as Check4, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2213
|
-
import { jsx as
|
|
2210
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2214
2211
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2215
|
-
const [newPort, setNewPort] =
|
|
2216
|
-
const [copiedPort, setCopiedPort] =
|
|
2217
|
-
const copyTimerRef =
|
|
2218
|
-
|
|
2212
|
+
const [newPort, setNewPort] = React7.useState("");
|
|
2213
|
+
const [copiedPort, setCopiedPort] = React7.useState(null);
|
|
2214
|
+
const copyTimerRef = React7.useRef(null);
|
|
2215
|
+
React7.useEffect(() => {
|
|
2219
2216
|
return () => {
|
|
2220
2217
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2221
2218
|
};
|
|
@@ -2238,47 +2235,47 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2238
2235
|
}
|
|
2239
2236
|
};
|
|
2240
2237
|
return /* @__PURE__ */ jsxs17("div", { className: cn("space-y-4", className), children: [
|
|
2241
|
-
ports.length > 0 ? /* @__PURE__ */
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
/* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
/* @__PURE__ */
|
|
2246
|
-
/* @__PURE__ */
|
|
2238
|
+
ports.length > 0 ? /* @__PURE__ */ jsx18("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs17("table", { className: "w-full text-sm", children: [
|
|
2239
|
+
/* @__PURE__ */ jsx18("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs17("tr", { children: [
|
|
2240
|
+
/* @__PURE__ */ jsx18("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Port" }),
|
|
2241
|
+
/* @__PURE__ */ jsx18("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Public URL" }),
|
|
2242
|
+
/* @__PURE__ */ jsx18("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2243
|
+
/* @__PURE__ */ jsx18("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2247
2244
|
] }) }),
|
|
2248
|
-
/* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2250
|
-
/* @__PURE__ */
|
|
2245
|
+
/* @__PURE__ */ jsx18("tbody", { className: "divide-y divide-border", children: ports.map((p) => /* @__PURE__ */ jsxs17("tr", { children: [
|
|
2246
|
+
/* @__PURE__ */ jsx18("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.port }),
|
|
2247
|
+
/* @__PURE__ */ jsx18("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs17(
|
|
2251
2248
|
"button",
|
|
2252
2249
|
{
|
|
2253
2250
|
type: "button",
|
|
2254
2251
|
onClick: () => handleCopy(p.url, p.port),
|
|
2255
2252
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2256
2253
|
children: [
|
|
2257
|
-
/* @__PURE__ */
|
|
2258
|
-
copiedPort === p.port ? /* @__PURE__ */
|
|
2254
|
+
/* @__PURE__ */ jsx18("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2255
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx18(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx18(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2259
2256
|
]
|
|
2260
2257
|
}
|
|
2261
2258
|
) }),
|
|
2262
|
-
/* @__PURE__ */
|
|
2259
|
+
/* @__PURE__ */ jsx18("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx18("span", { className: cn(
|
|
2263
2260
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2264
2261
|
p.status === "active" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]"
|
|
2265
2262
|
), children: p.status }) }),
|
|
2266
|
-
/* @__PURE__ */
|
|
2263
|
+
/* @__PURE__ */ jsx18("td", { className: "px-4 py-3 text-right", children: onRemovePort && /* @__PURE__ */ jsx18(
|
|
2267
2264
|
"button",
|
|
2268
2265
|
{
|
|
2269
2266
|
type: "button",
|
|
2270
2267
|
onClick: () => onRemovePort(p.port),
|
|
2271
2268
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2272
|
-
children: /* @__PURE__ */
|
|
2269
|
+
children: /* @__PURE__ */ jsx18(Trash23, { className: "h-3.5 w-3.5" })
|
|
2273
2270
|
}
|
|
2274
2271
|
) })
|
|
2275
2272
|
] }, p.port)) })
|
|
2276
2273
|
] }) }) : /* @__PURE__ */ jsxs17("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2277
|
-
/* @__PURE__ */
|
|
2278
|
-
/* @__PURE__ */
|
|
2274
|
+
/* @__PURE__ */ jsx18(Globe, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2275
|
+
/* @__PURE__ */ jsx18("p", { className: "text-sm text-muted-foreground", children: "No ports exposed yet" })
|
|
2279
2276
|
] }),
|
|
2280
2277
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-3", children: [
|
|
2281
|
-
/* @__PURE__ */
|
|
2278
|
+
/* @__PURE__ */ jsx18(
|
|
2282
2279
|
"input",
|
|
2283
2280
|
{
|
|
2284
2281
|
type: "number",
|
|
@@ -2299,7 +2296,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2299
2296
|
disabled: !newPort || isExposing,
|
|
2300
2297
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2301
2298
|
children: [
|
|
2302
|
-
/* @__PURE__ */
|
|
2299
|
+
/* @__PURE__ */ jsx18(Plus4, { className: "h-4 w-4" }),
|
|
2303
2300
|
"Expose"
|
|
2304
2301
|
]
|
|
2305
2302
|
}
|
|
@@ -2309,9 +2306,9 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2309
2306
|
}
|
|
2310
2307
|
|
|
2311
2308
|
// src/dashboard/process-list.tsx
|
|
2312
|
-
import * as
|
|
2309
|
+
import * as React8 from "react";
|
|
2313
2310
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
|
|
2314
|
-
import { jsx as
|
|
2311
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2315
2312
|
function formatUptime(startedAt) {
|
|
2316
2313
|
if (!startedAt) return "-";
|
|
2317
2314
|
const ms = Date.now() - new Date(startedAt).getTime();
|
|
@@ -2321,7 +2318,7 @@ function formatUptime(startedAt) {
|
|
|
2321
2318
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2322
2319
|
}
|
|
2323
2320
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2324
|
-
const [newCommand, setNewCommand] =
|
|
2321
|
+
const [newCommand, setNewCommand] = React8.useState("");
|
|
2325
2322
|
const handleSpawn = () => {
|
|
2326
2323
|
const cmd = newCommand.trim();
|
|
2327
2324
|
if (cmd) {
|
|
@@ -2331,41 +2328,41 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2331
2328
|
};
|
|
2332
2329
|
return /* @__PURE__ */ jsxs18("div", { className: cn("space-y-4", className), children: [
|
|
2333
2330
|
loading ? /* @__PURE__ */ jsxs18("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2334
|
-
/* @__PURE__ */
|
|
2335
|
-
/* @__PURE__ */
|
|
2336
|
-
] }) : processes.length > 0 ? /* @__PURE__ */
|
|
2337
|
-
/* @__PURE__ */
|
|
2338
|
-
/* @__PURE__ */
|
|
2339
|
-
/* @__PURE__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2342
|
-
/* @__PURE__ */
|
|
2331
|
+
/* @__PURE__ */ jsx19(Activity3, { className: "mx-auto h-6 w-6 text-muted-foreground animate-spin mb-2" }),
|
|
2332
|
+
/* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "Loading processes..." })
|
|
2333
|
+
] }) : processes.length > 0 ? /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs18("table", { className: "w-full text-sm", children: [
|
|
2334
|
+
/* @__PURE__ */ jsx19("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs18("tr", { children: [
|
|
2335
|
+
/* @__PURE__ */ jsx19("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "PID" }),
|
|
2336
|
+
/* @__PURE__ */ jsx19("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Command" }),
|
|
2337
|
+
/* @__PURE__ */ jsx19("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2338
|
+
/* @__PURE__ */ jsx19("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Uptime" }),
|
|
2339
|
+
/* @__PURE__ */ jsx19("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2343
2340
|
] }) }),
|
|
2344
|
-
/* @__PURE__ */
|
|
2345
|
-
/* @__PURE__ */
|
|
2346
|
-
/* @__PURE__ */
|
|
2347
|
-
/* @__PURE__ */
|
|
2341
|
+
/* @__PURE__ */ jsx19("tbody", { className: "divide-y divide-border", children: processes.map((p) => /* @__PURE__ */ jsxs18("tr", { children: [
|
|
2342
|
+
/* @__PURE__ */ jsx19("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.pid }),
|
|
2343
|
+
/* @__PURE__ */ jsx19("td", { className: "px-4 py-3 font-mono text-xs text-foreground truncate max-w-[250px]", children: p.command }),
|
|
2344
|
+
/* @__PURE__ */ jsx19("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx19("span", { className: cn(
|
|
2348
2345
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2349
2346
|
p.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-muted text-muted-foreground"
|
|
2350
2347
|
), children: p.running ? "running" : `exited (${p.exitCode ?? "?"})` }) }),
|
|
2351
|
-
/* @__PURE__ */
|
|
2352
|
-
/* @__PURE__ */
|
|
2348
|
+
/* @__PURE__ */ jsx19("td", { className: "px-4 py-3 font-mono text-xs text-muted-foreground", children: formatUptime(p.startedAt) }),
|
|
2349
|
+
/* @__PURE__ */ jsx19("td", { className: "px-4 py-3 text-right", children: p.running && /* @__PURE__ */ jsx19(
|
|
2353
2350
|
"button",
|
|
2354
2351
|
{
|
|
2355
2352
|
type: "button",
|
|
2356
2353
|
onClick: () => onKill(p.pid),
|
|
2357
2354
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2358
2355
|
title: "Kill process",
|
|
2359
|
-
children: /* @__PURE__ */
|
|
2356
|
+
children: /* @__PURE__ */ jsx19(Skull, { className: "h-3.5 w-3.5" })
|
|
2360
2357
|
}
|
|
2361
2358
|
) })
|
|
2362
2359
|
] }, `${p.pid}-${p.startedAt ?? p.command}`)) })
|
|
2363
2360
|
] }) }) : /* @__PURE__ */ jsxs18("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2364
|
-
/* @__PURE__ */
|
|
2365
|
-
/* @__PURE__ */
|
|
2361
|
+
/* @__PURE__ */ jsx19(Terminal4, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2362
|
+
/* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "No processes running" })
|
|
2366
2363
|
] }),
|
|
2367
2364
|
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-3", children: [
|
|
2368
|
-
/* @__PURE__ */
|
|
2365
|
+
/* @__PURE__ */ jsx19(
|
|
2369
2366
|
"input",
|
|
2370
2367
|
{
|
|
2371
2368
|
type: "text",
|
|
@@ -2384,7 +2381,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2384
2381
|
disabled: !newCommand.trim(),
|
|
2385
2382
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2386
2383
|
children: [
|
|
2387
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx19(Plus5, { className: "h-4 w-4" }),
|
|
2388
2385
|
"Spawn"
|
|
2389
2386
|
]
|
|
2390
2387
|
}
|
|
@@ -2394,11 +2391,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2394
2391
|
}
|
|
2395
2392
|
|
|
2396
2393
|
// src/dashboard/network-config.tsx
|
|
2397
|
-
import * as
|
|
2394
|
+
import * as React9 from "react";
|
|
2398
2395
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
2399
|
-
import { jsx as
|
|
2396
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2400
2397
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
2401
|
-
const [newCidr, setNewCidr] =
|
|
2398
|
+
const [newCidr, setNewCidr] = React9.useState("");
|
|
2402
2399
|
const isValidCidr = (value) => {
|
|
2403
2400
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
2404
2401
|
if (!match) return false;
|
|
@@ -2420,20 +2417,20 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2420
2417
|
};
|
|
2421
2418
|
if (loading || !config) {
|
|
2422
2419
|
return /* @__PURE__ */ jsxs19("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2423
|
-
/* @__PURE__ */
|
|
2424
|
-
/* @__PURE__ */
|
|
2420
|
+
/* @__PURE__ */ jsx20(Network2, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2421
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "Loading network configuration..." })
|
|
2425
2422
|
] });
|
|
2426
2423
|
}
|
|
2427
2424
|
return /* @__PURE__ */ jsxs19("div", { className: cn("space-y-4", className), children: [
|
|
2428
2425
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between rounded-lg border border-border bg-card px-4 py-3", children: [
|
|
2429
2426
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-3", children: [
|
|
2430
|
-
/* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsx20(ShieldAlert, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2431
2428
|
/* @__PURE__ */ jsxs19("div", { children: [
|
|
2432
|
-
/* @__PURE__ */
|
|
2433
|
-
/* @__PURE__ */
|
|
2429
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-foreground", children: "Block Outbound Traffic" }),
|
|
2430
|
+
/* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: "Prevent the sandbox from making external network requests" })
|
|
2434
2431
|
] })
|
|
2435
2432
|
] }),
|
|
2436
|
-
/* @__PURE__ */
|
|
2433
|
+
/* @__PURE__ */ jsx20(
|
|
2437
2434
|
"button",
|
|
2438
2435
|
{
|
|
2439
2436
|
type: "button",
|
|
@@ -2445,7 +2442,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2445
2442
|
"relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
|
|
2446
2443
|
config.blockOutbound ? "bg-destructive" : "bg-muted"
|
|
2447
2444
|
),
|
|
2448
|
-
children: /* @__PURE__ */
|
|
2445
|
+
children: /* @__PURE__ */ jsx20(
|
|
2449
2446
|
"span",
|
|
2450
2447
|
{
|
|
2451
2448
|
className: cn(
|
|
@@ -2458,21 +2455,21 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2458
2455
|
)
|
|
2459
2456
|
] }),
|
|
2460
2457
|
/* @__PURE__ */ jsxs19("div", { children: [
|
|
2461
|
-
/* @__PURE__ */
|
|
2462
|
-
config.allowList.length > 0 ? /* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2464
|
-
/* @__PURE__ */
|
|
2458
|
+
/* @__PURE__ */ jsx20("h4", { className: "text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider", children: "Allowlist (CIDR)" }),
|
|
2459
|
+
config.allowList.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "space-y-1.5 mb-3", children: config.allowList.map((cidr) => /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between rounded border border-border bg-muted/20 px-3 py-2", children: [
|
|
2460
|
+
/* @__PURE__ */ jsx20("span", { className: "font-mono text-xs text-foreground", children: cidr }),
|
|
2461
|
+
/* @__PURE__ */ jsx20(
|
|
2465
2462
|
"button",
|
|
2466
2463
|
{
|
|
2467
2464
|
type: "button",
|
|
2468
2465
|
onClick: () => handleRemoveCidr(cidr),
|
|
2469
2466
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2470
|
-
children: /* @__PURE__ */
|
|
2467
|
+
children: /* @__PURE__ */ jsx20(Trash24, { className: "h-3 w-3" })
|
|
2471
2468
|
}
|
|
2472
2469
|
)
|
|
2473
|
-
] }, cidr)) }) : /* @__PURE__ */
|
|
2470
|
+
] }, cidr)) }) : /* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground mb-3", children: "No CIDR rules configured. All traffic is allowed." }),
|
|
2474
2471
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-3", children: [
|
|
2475
|
-
/* @__PURE__ */
|
|
2472
|
+
/* @__PURE__ */ jsx20(
|
|
2476
2473
|
"input",
|
|
2477
2474
|
{
|
|
2478
2475
|
type: "text",
|
|
@@ -2491,7 +2488,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2491
2488
|
disabled: !newCidr.trim(),
|
|
2492
2489
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2493
2490
|
children: [
|
|
2494
|
-
/* @__PURE__ */
|
|
2491
|
+
/* @__PURE__ */ jsx20(Plus6, { className: "h-4 w-4" }),
|
|
2495
2492
|
"Add"
|
|
2496
2493
|
]
|
|
2497
2494
|
}
|
|
@@ -2502,9 +2499,9 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2502
2499
|
}
|
|
2503
2500
|
|
|
2504
2501
|
// src/dashboard/backend-config.tsx
|
|
2505
|
-
import * as
|
|
2502
|
+
import * as React10 from "react";
|
|
2506
2503
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
2507
|
-
import { Fragment as
|
|
2504
|
+
import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2508
2505
|
function BackendConfig({
|
|
2509
2506
|
status,
|
|
2510
2507
|
mcpServers,
|
|
@@ -2514,10 +2511,10 @@ function BackendConfig({
|
|
|
2514
2511
|
loading = false,
|
|
2515
2512
|
className
|
|
2516
2513
|
}) {
|
|
2517
|
-
const [showAddMcp, setShowAddMcp] =
|
|
2518
|
-
const [mcpName, setMcpName] =
|
|
2519
|
-
const [mcpCommand, setMcpCommand] =
|
|
2520
|
-
const [mcpArgs, setMcpArgs] =
|
|
2514
|
+
const [showAddMcp, setShowAddMcp] = React10.useState(false);
|
|
2515
|
+
const [mcpName, setMcpName] = React10.useState("");
|
|
2516
|
+
const [mcpCommand, setMcpCommand] = React10.useState("");
|
|
2517
|
+
const [mcpArgs, setMcpArgs] = React10.useState("");
|
|
2521
2518
|
const handleAddMcp = () => {
|
|
2522
2519
|
const name = mcpName.trim();
|
|
2523
2520
|
const command = mcpCommand.trim();
|
|
@@ -2535,14 +2532,14 @@ function BackendConfig({
|
|
|
2535
2532
|
};
|
|
2536
2533
|
if (loading || !status) {
|
|
2537
2534
|
return /* @__PURE__ */ jsxs20("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2538
|
-
/* @__PURE__ */
|
|
2539
|
-
/* @__PURE__ */
|
|
2535
|
+
/* @__PURE__ */ jsx21(Bot, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2536
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Loading backend status..." })
|
|
2540
2537
|
] });
|
|
2541
2538
|
}
|
|
2542
2539
|
return /* @__PURE__ */ jsxs20("div", { className: cn("space-y-4", className), children: [
|
|
2543
2540
|
/* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2544
2541
|
/* @__PURE__ */ jsxs20("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2545
|
-
/* @__PURE__ */
|
|
2542
|
+
/* @__PURE__ */ jsx21("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider", children: "Agent Status" }),
|
|
2546
2543
|
/* @__PURE__ */ jsxs20(
|
|
2547
2544
|
"button",
|
|
2548
2545
|
{
|
|
@@ -2550,30 +2547,30 @@ function BackendConfig({
|
|
|
2550
2547
|
onClick: onRestart,
|
|
2551
2548
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2552
2549
|
children: [
|
|
2553
|
-
/* @__PURE__ */
|
|
2550
|
+
/* @__PURE__ */ jsx21(RefreshCw2, { className: "h-3 w-3" }),
|
|
2554
2551
|
"Restart"
|
|
2555
2552
|
]
|
|
2556
2553
|
}
|
|
2557
2554
|
)
|
|
2558
2555
|
] }),
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
/* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2556
|
+
/* @__PURE__ */ jsx21("div", { className: "p-4", children: /* @__PURE__ */ jsxs20("dl", { className: "grid grid-cols-[100px_1fr] gap-y-3 text-sm", children: [
|
|
2557
|
+
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: "Status" }),
|
|
2558
|
+
/* @__PURE__ */ jsx21("dd", { children: /* @__PURE__ */ jsx21("span", { className: cn(
|
|
2562
2559
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2563
2560
|
status.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-destructive/10 text-destructive"
|
|
2564
2561
|
), children: status.running ? "Running" : "Stopped" }) }),
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
/* @__PURE__ */
|
|
2567
|
-
status.provider && /* @__PURE__ */ jsxs20(
|
|
2568
|
-
/* @__PURE__ */
|
|
2569
|
-
/* @__PURE__ */
|
|
2562
|
+
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: "Model" }),
|
|
2563
|
+
/* @__PURE__ */ jsx21("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
|
|
2564
|
+
status.provider && /* @__PURE__ */ jsxs20(Fragment11, { children: [
|
|
2565
|
+
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: "Provider" }),
|
|
2566
|
+
/* @__PURE__ */ jsx21("dd", { className: "font-mono text-xs", children: status.provider })
|
|
2570
2567
|
] })
|
|
2571
2568
|
] }) })
|
|
2572
2569
|
] }),
|
|
2573
2570
|
/* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2574
2571
|
/* @__PURE__ */ jsxs20("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2575
2572
|
/* @__PURE__ */ jsxs20("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
2576
|
-
/* @__PURE__ */
|
|
2573
|
+
/* @__PURE__ */ jsx21(Wrench, { className: "h-3.5 w-3.5" }),
|
|
2577
2574
|
"MCP Servers"
|
|
2578
2575
|
] }),
|
|
2579
2576
|
/* @__PURE__ */ jsxs20(
|
|
@@ -2583,17 +2580,17 @@ function BackendConfig({
|
|
|
2583
2580
|
onClick: () => setShowAddMcp(!showAddMcp),
|
|
2584
2581
|
className: "inline-flex items-center gap-1.5 rounded-md bg-primary/20 border border-primary/30 px-2.5 py-1 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2585
2582
|
children: [
|
|
2586
|
-
/* @__PURE__ */
|
|
2583
|
+
/* @__PURE__ */ jsx21(Plus7, { className: "h-3 w-3" }),
|
|
2587
2584
|
"Add"
|
|
2588
2585
|
]
|
|
2589
2586
|
}
|
|
2590
2587
|
)
|
|
2591
2588
|
] }),
|
|
2592
|
-
mcpServers.length > 0 ? /* @__PURE__ */
|
|
2589
|
+
mcpServers.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "divide-y divide-border", children: mcpServers.map((s) => /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between px-4 py-3", children: [
|
|
2593
2590
|
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
2594
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ jsx21(Server, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
|
|
2595
2592
|
/* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
|
|
2596
|
-
/* @__PURE__ */
|
|
2593
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm font-medium text-foreground truncate", children: s.name }),
|
|
2597
2594
|
/* @__PURE__ */ jsxs20("p", { className: "text-xs font-mono text-muted-foreground truncate", children: [
|
|
2598
2595
|
s.command,
|
|
2599
2596
|
" ",
|
|
@@ -2602,23 +2599,23 @@ function BackendConfig({
|
|
|
2602
2599
|
] })
|
|
2603
2600
|
] }),
|
|
2604
2601
|
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2605
|
-
s.status && /* @__PURE__ */
|
|
2602
|
+
s.status && /* @__PURE__ */ jsx21("span", { className: cn(
|
|
2606
2603
|
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[9px] font-bold uppercase",
|
|
2607
2604
|
s.status === "running" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : s.status === "error" ? "bg-destructive/10 text-destructive" : "bg-muted text-muted-foreground"
|
|
2608
2605
|
), children: s.status }),
|
|
2609
|
-
/* @__PURE__ */
|
|
2606
|
+
/* @__PURE__ */ jsx21(
|
|
2610
2607
|
"button",
|
|
2611
2608
|
{
|
|
2612
2609
|
type: "button",
|
|
2613
2610
|
onClick: () => onRemoveMcp(s.name),
|
|
2614
2611
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2615
|
-
children: /* @__PURE__ */
|
|
2612
|
+
children: /* @__PURE__ */ jsx21(Trash25, { className: "h-3.5 w-3.5" })
|
|
2616
2613
|
}
|
|
2617
2614
|
)
|
|
2618
2615
|
] })
|
|
2619
|
-
] }, s.name)) }) : /* @__PURE__ */
|
|
2616
|
+
] }, s.name)) }) : /* @__PURE__ */ jsx21("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: "No MCP servers configured" }) }),
|
|
2620
2617
|
showAddMcp && /* @__PURE__ */ jsxs20("div", { className: "p-4 border-t border-border bg-muted/10 space-y-2", children: [
|
|
2621
|
-
/* @__PURE__ */
|
|
2618
|
+
/* @__PURE__ */ jsx21(
|
|
2622
2619
|
"input",
|
|
2623
2620
|
{
|
|
2624
2621
|
type: "text",
|
|
@@ -2628,7 +2625,7 @@ function BackendConfig({
|
|
|
2628
2625
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2629
2626
|
}
|
|
2630
2627
|
),
|
|
2631
|
-
/* @__PURE__ */
|
|
2628
|
+
/* @__PURE__ */ jsx21(
|
|
2632
2629
|
"input",
|
|
2633
2630
|
{
|
|
2634
2631
|
type: "text",
|
|
@@ -2638,7 +2635,7 @@ function BackendConfig({
|
|
|
2638
2635
|
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"
|
|
2639
2636
|
}
|
|
2640
2637
|
),
|
|
2641
|
-
/* @__PURE__ */
|
|
2638
|
+
/* @__PURE__ */ jsx21(
|
|
2642
2639
|
"input",
|
|
2643
2640
|
{
|
|
2644
2641
|
type: "text",
|
|
@@ -2649,7 +2646,7 @@ function BackendConfig({
|
|
|
2649
2646
|
}
|
|
2650
2647
|
),
|
|
2651
2648
|
/* @__PURE__ */ jsxs20("div", { className: "flex justify-end gap-2 pt-1", children: [
|
|
2652
|
-
/* @__PURE__ */
|
|
2649
|
+
/* @__PURE__ */ jsx21(
|
|
2653
2650
|
"button",
|
|
2654
2651
|
{
|
|
2655
2652
|
type: "button",
|
|
@@ -2658,7 +2655,7 @@ function BackendConfig({
|
|
|
2658
2655
|
children: "Cancel"
|
|
2659
2656
|
}
|
|
2660
2657
|
),
|
|
2661
|
-
/* @__PURE__ */
|
|
2658
|
+
/* @__PURE__ */ jsx21(
|
|
2662
2659
|
"button",
|
|
2663
2660
|
{
|
|
2664
2661
|
type: "button",
|
|
@@ -2675,9 +2672,9 @@ function BackendConfig({
|
|
|
2675
2672
|
}
|
|
2676
2673
|
|
|
2677
2674
|
// src/dashboard/snapshot-list.tsx
|
|
2678
|
-
import * as
|
|
2675
|
+
import * as React11 from "react";
|
|
2679
2676
|
import { Camera, Clock as Clock5, HardDrive, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
2680
|
-
import { jsx as
|
|
2677
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2681
2678
|
function formatBytes(bytes) {
|
|
2682
2679
|
if (bytes == null || bytes < 0) return "-";
|
|
2683
2680
|
if (bytes === 0) return "0 B";
|
|
@@ -2692,8 +2689,8 @@ function formatDate(dateStr) {
|
|
|
2692
2689
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
2693
2690
|
}
|
|
2694
2691
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
2695
|
-
const [showCreate, setShowCreate] =
|
|
2696
|
-
const [tags, setTags] =
|
|
2692
|
+
const [showCreate, setShowCreate] = React11.useState(false);
|
|
2693
|
+
const [tags, setTags] = React11.useState("");
|
|
2697
2694
|
const handleCreate = () => {
|
|
2698
2695
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
2699
2696
|
onCreate(tagList);
|
|
@@ -2702,7 +2699,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2702
2699
|
};
|
|
2703
2700
|
return /* @__PURE__ */ jsxs21("div", { className: cn("space-y-4", className), children: [
|
|
2704
2701
|
/* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-between", children: [
|
|
2705
|
-
/* @__PURE__ */
|
|
2702
|
+
/* @__PURE__ */ jsx22("h3", { className: "text-sm font-bold text-foreground", children: "Snapshots" }),
|
|
2706
2703
|
/* @__PURE__ */ jsxs21(
|
|
2707
2704
|
"button",
|
|
2708
2705
|
{
|
|
@@ -2710,15 +2707,15 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2710
2707
|
onClick: () => setShowCreate(!showCreate),
|
|
2711
2708
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-primary/20 border border-primary/30 px-3 py-1.5 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2712
2709
|
children: [
|
|
2713
|
-
/* @__PURE__ */
|
|
2710
|
+
/* @__PURE__ */ jsx22(Plus8, { className: "h-3.5 w-3.5" }),
|
|
2714
2711
|
"Create Snapshot"
|
|
2715
2712
|
]
|
|
2716
2713
|
}
|
|
2717
2714
|
)
|
|
2718
2715
|
] }),
|
|
2719
2716
|
showCreate && /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-3", children: [
|
|
2720
|
-
/* @__PURE__ */
|
|
2721
|
-
/* @__PURE__ */
|
|
2717
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-foreground font-medium", children: "Create a new snapshot of the current sandbox state." }),
|
|
2718
|
+
/* @__PURE__ */ jsx22(
|
|
2722
2719
|
"input",
|
|
2723
2720
|
{
|
|
2724
2721
|
type: "text",
|
|
@@ -2730,7 +2727,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2730
2727
|
}
|
|
2731
2728
|
),
|
|
2732
2729
|
/* @__PURE__ */ jsxs21("div", { className: "flex justify-end gap-2", children: [
|
|
2733
|
-
/* @__PURE__ */
|
|
2730
|
+
/* @__PURE__ */ jsx22(
|
|
2734
2731
|
"button",
|
|
2735
2732
|
{
|
|
2736
2733
|
type: "button",
|
|
@@ -2746,7 +2743,7 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2746
2743
|
onClick: handleCreate,
|
|
2747
2744
|
className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
2748
2745
|
children: [
|
|
2749
|
-
/* @__PURE__ */
|
|
2746
|
+
/* @__PURE__ */ jsx22(Camera, { className: "h-3 w-3 mr-1.5 inline" }),
|
|
2750
2747
|
"Create"
|
|
2751
2748
|
]
|
|
2752
2749
|
}
|
|
@@ -2754,28 +2751,28 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2754
2751
|
] })
|
|
2755
2752
|
] }),
|
|
2756
2753
|
loading ? /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2757
|
-
/* @__PURE__ */
|
|
2758
|
-
/* @__PURE__ */
|
|
2759
|
-
] }) : snapshots.length > 0 ? /* @__PURE__ */
|
|
2760
|
-
/* @__PURE__ */
|
|
2761
|
-
/* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2765
|
-
/* @__PURE__ */
|
|
2754
|
+
/* @__PURE__ */ jsx22(Camera, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2755
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Loading snapshots..." })
|
|
2756
|
+
] }) : snapshots.length > 0 ? /* @__PURE__ */ jsx22("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs21("table", { className: "w-full text-sm", children: [
|
|
2757
|
+
/* @__PURE__ */ jsx22("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2758
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "ID" }),
|
|
2759
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Created" }),
|
|
2760
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Size" }),
|
|
2761
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Tags" }),
|
|
2762
|
+
/* @__PURE__ */ jsx22("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-24" })
|
|
2766
2763
|
] }) }),
|
|
2767
|
-
/* @__PURE__ */
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
/* @__PURE__ */
|
|
2770
|
-
/* @__PURE__ */
|
|
2764
|
+
/* @__PURE__ */ jsx22("tbody", { className: "divide-y divide-border", children: snapshots.map((s) => /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2765
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: s.id.slice(0, 12) }),
|
|
2766
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs21("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2767
|
+
/* @__PURE__ */ jsx22(Clock5, { className: "h-3 w-3" }),
|
|
2771
2768
|
formatDate(s.createdAt)
|
|
2772
2769
|
] }) }),
|
|
2773
|
-
/* @__PURE__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2770
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs21("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2771
|
+
/* @__PURE__ */ jsx22(HardDrive, { className: "h-3 w-3" }),
|
|
2775
2772
|
formatBytes(s.sizeBytes)
|
|
2776
2773
|
] }) }),
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2774
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3", children: s.tags?.length ? /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-1 flex-wrap", children: s.tags.map((tag) => /* @__PURE__ */ jsx22("span", { className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground border border-border", children: tag }, tag)) }) : /* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: "-" }) }),
|
|
2775
|
+
/* @__PURE__ */ jsx22("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-end gap-2", children: [
|
|
2779
2776
|
/* @__PURE__ */ jsxs21(
|
|
2780
2777
|
"button",
|
|
2781
2778
|
{
|
|
@@ -2784,12 +2781,12 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2784
2781
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2785
2782
|
title: "Restore to new sandbox",
|
|
2786
2783
|
children: [
|
|
2787
|
-
/* @__PURE__ */
|
|
2784
|
+
/* @__PURE__ */ jsx22(RotateCcw, { className: "h-3 w-3" }),
|
|
2788
2785
|
"Restore"
|
|
2789
2786
|
]
|
|
2790
2787
|
}
|
|
2791
2788
|
),
|
|
2792
|
-
onSaveAsTemplate && /* @__PURE__ */
|
|
2789
|
+
onSaveAsTemplate && /* @__PURE__ */ jsx22(
|
|
2793
2790
|
"button",
|
|
2794
2791
|
{
|
|
2795
2792
|
type: "button",
|
|
@@ -2802,15 +2799,15 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2802
2799
|
] }) })
|
|
2803
2800
|
] }, s.id)) })
|
|
2804
2801
|
] }) }) : /* @__PURE__ */ jsxs21("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2807
|
-
/* @__PURE__ */
|
|
2802
|
+
/* @__PURE__ */ jsx22(Camera, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2803
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "No snapshots yet" }),
|
|
2804
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground mt-1", children: "Create a snapshot to save the current state of your sandbox." })
|
|
2808
2805
|
] })
|
|
2809
2806
|
] });
|
|
2810
2807
|
}
|
|
2811
2808
|
|
|
2812
2809
|
// src/dashboard/promo-banner.tsx
|
|
2813
|
-
import { Fragment as
|
|
2810
|
+
import { Fragment as Fragment12, jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2814
2811
|
function PromoBanner({
|
|
2815
2812
|
title,
|
|
2816
2813
|
description,
|
|
@@ -2825,21 +2822,21 @@ function PromoBanner({
|
|
|
2825
2822
|
"mt-6 inline-flex items-center gap-2 rounded-md border border-white/20 bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-medium text-[var(--btn-primary-text)] transition-colors",
|
|
2826
2823
|
disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
|
|
2827
2824
|
);
|
|
2828
|
-
const buttonContent = /* @__PURE__ */ jsxs22(
|
|
2825
|
+
const buttonContent = /* @__PURE__ */ jsxs22(Fragment12, { children: [
|
|
2829
2826
|
buttonLabel,
|
|
2830
2827
|
/* @__PURE__ */ jsxs22("svg", { "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "h-4 w-4", children: [
|
|
2831
|
-
/* @__PURE__ */
|
|
2832
|
-
/* @__PURE__ */
|
|
2828
|
+
/* @__PURE__ */ jsx23("path", { d: "M5 12h14" }),
|
|
2829
|
+
/* @__PURE__ */ jsx23("path", { d: "m12 5 7 7-7 7" })
|
|
2833
2830
|
] })
|
|
2834
2831
|
] });
|
|
2835
2832
|
return /* @__PURE__ */ jsxs22("div", { className: cn("relative overflow-hidden rounded-xl bg-[var(--brand-strong)] p-8 md:flex md:items-center md:justify-between", className), children: [
|
|
2836
2833
|
/* @__PURE__ */ jsxs22("div", { className: "relative z-10", children: [
|
|
2837
|
-
/* @__PURE__ */
|
|
2838
|
-
/* @__PURE__ */
|
|
2839
|
-
href && !disabled ? /* @__PURE__ */
|
|
2834
|
+
/* @__PURE__ */ jsx23("h3", { className: "text-xl font-bold text-[var(--brand-strong-text)]", children: title }),
|
|
2835
|
+
/* @__PURE__ */ jsx23("p", { className: "mt-2 max-w-md text-sm text-[var(--brand-strong-text-muted)]", children: description }),
|
|
2836
|
+
href && !disabled ? /* @__PURE__ */ jsx23("a", { href, target: "_blank", rel: "noopener noreferrer", onClick, className: buttonClasses, children: buttonContent }) : /* @__PURE__ */ jsx23("button", { type: "button", onClick, disabled, className: buttonClasses, children: buttonContent })
|
|
2840
2837
|
] }),
|
|
2841
|
-
icon && /* @__PURE__ */
|
|
2842
|
-
/* @__PURE__ */
|
|
2838
|
+
icon && /* @__PURE__ */ jsx23("div", { className: "relative z-10 mt-6 flex items-center md:mt-0", children: /* @__PURE__ */ jsx23("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl border border-white/10 bg-white/10", children: icon }) }),
|
|
2839
|
+
/* @__PURE__ */ jsx23("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-1/3 bg-gradient-to-l from-white/5 to-transparent" })
|
|
2843
2840
|
] });
|
|
2844
2841
|
}
|
|
2845
2842
|
|
|
@@ -2875,12 +2872,10 @@ export {
|
|
|
2875
2872
|
SandboxTable,
|
|
2876
2873
|
InvoiceTable,
|
|
2877
2874
|
PlanCards,
|
|
2878
|
-
BackendSelector,
|
|
2879
|
-
HARNESS_OPTIONS,
|
|
2880
|
-
HarnessPicker,
|
|
2881
2875
|
DashboardLayout,
|
|
2882
2876
|
ProfileSelector,
|
|
2883
2877
|
ProfileComparison,
|
|
2878
|
+
MetricAreaChart,
|
|
2884
2879
|
VariantList,
|
|
2885
2880
|
SystemLogsViewer,
|
|
2886
2881
|
UsageSummary,
|