@truefoundry/trueforge-ui 0.0.0 → 0.1.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +17 -0
  4. package/README.md +640 -3
  5. package/dist/ConnectorSettings-CLBEWGQJ.js +898 -0
  6. package/dist/ConnectorSettings-CLBEWGQJ.js.map +1 -0
  7. package/dist/DockLayout-WRF7EQLD.js +35 -0
  8. package/dist/DockLayout-WRF7EQLD.js.map +1 -0
  9. package/dist/DrawerLayout-X2UXYTOS.js +156 -0
  10. package/dist/DrawerLayout-X2UXYTOS.js.map +1 -0
  11. package/dist/ModelSettings-IJ55QJQO.js +1082 -0
  12. package/dist/ModelSettings-IJ55QJQO.js.map +1 -0
  13. package/dist/OpenUiFenceBlock-SLLZSTMJ.js +9 -0
  14. package/dist/OpenUiFenceBlock-SLLZSTMJ.js.map +1 -0
  15. package/dist/SandboxSettings-S5XGZWOL.js +505 -0
  16. package/dist/SandboxSettings-S5XGZWOL.js.map +1 -0
  17. package/dist/SettingsBuilder-64Y33NP3.js +128 -0
  18. package/dist/SettingsBuilder-64Y33NP3.js.map +1 -0
  19. package/dist/SidebarLayout-M7HEOZVK.js +236 -0
  20. package/dist/SidebarLayout-M7HEOZVK.js.map +1 -0
  21. package/dist/SkillSettings-MXK4ZEI7.js +389 -0
  22. package/dist/SkillSettings-MXK4ZEI7.js.map +1 -0
  23. package/dist/WidgetLayout-7MDOKLHU.js +101 -0
  24. package/dist/WidgetLayout-7MDOKLHU.js.map +1 -0
  25. package/dist/assistant-ui.d.ts +1 -0
  26. package/dist/assistant-ui.js +9 -0
  27. package/dist/assistant-ui.js.map +1 -0
  28. package/dist/chunk-42GF723P.js +24 -0
  29. package/dist/chunk-42GF723P.js.map +1 -0
  30. package/dist/chunk-CFLVPV5M.js +29 -0
  31. package/dist/chunk-CFLVPV5M.js.map +1 -0
  32. package/dist/chunk-M6MHLVSO.js +8 -0
  33. package/dist/chunk-M6MHLVSO.js.map +1 -0
  34. package/dist/chunk-NBMP2XNL.js +89 -0
  35. package/dist/chunk-NBMP2XNL.js.map +1 -0
  36. package/dist/chunk-UBOFEI77.js +567 -0
  37. package/dist/chunk-UBOFEI77.js.map +1 -0
  38. package/dist/chunk-UHGSHDBM.js +633 -0
  39. package/dist/chunk-UHGSHDBM.js.map +1 -0
  40. package/dist/chunk-UXZOL5GO.js +2088 -0
  41. package/dist/chunk-UXZOL5GO.js.map +1 -0
  42. package/dist/chunk-WFC3W4C3.js +73 -0
  43. package/dist/chunk-WFC3W4C3.js.map +1 -0
  44. package/dist/chunk-XSHXH6EI.js +6800 -0
  45. package/dist/chunk-XSHXH6EI.js.map +1 -0
  46. package/dist/createTrueFoundryServer-B72bU-J7.d.ts +28 -0
  47. package/dist/index.d.ts +1569 -0
  48. package/dist/index.js +781 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +479 -0
  51. package/dist/plugins/trueforge-agent-server-adapter/index.js +830 -0
  52. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -0
  53. package/dist/styles.css +2 -0
  54. package/package.json +129 -6
  55. package/index.js +0 -1
@@ -0,0 +1,505 @@
1
+ "use client";
2
+ import {
3
+ Accordion,
4
+ AccordionDetails,
5
+ AccordionSummary,
6
+ Button,
7
+ CenteredModal,
8
+ auiInputClass,
9
+ getErrorMessage,
10
+ useToasterOptional
11
+ } from "./chunk-XSHXH6EI.js";
12
+ import {
13
+ Icon,
14
+ useCatalogServer
15
+ } from "./chunk-UHGSHDBM.js";
16
+ import "./chunk-42GF723P.js";
17
+ import {
18
+ cn
19
+ } from "./chunk-UBOFEI77.js";
20
+
21
+ // src/containers/SettingsBuilder/SandboxSettings.tsx
22
+ import { useCallback, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
23
+
24
+ // src/containers/SettingsBuilder/ConfigureSandboxForm.tsx
25
+ import { useEffect, useState } from "react";
26
+ import { jsx, jsxs } from "react/jsx-runtime";
27
+ var EMPTY_CONFIG = {
28
+ // Snapshot/image is release-owned now; kept only to satisfy the external SandboxProviderConfig type.
29
+ snapshotName: "",
30
+ execTimeoutMs: 3e5,
31
+ autoStopIntervalInMinutes: 15,
32
+ autoArchiveIntervalInMinutes: 10080,
33
+ autoDeleteIntervalInMinutes: 43200
34
+ };
35
+ var inputClassName = auiInputClass("h-11 shadow-sm");
36
+ function parseNonNegInt(raw) {
37
+ if (raw.trim() === "") return null;
38
+ const n = Number(raw);
39
+ if (!Number.isFinite(n) || n < 0) return null;
40
+ return n;
41
+ }
42
+ var ConfigureSandboxForm = ({
43
+ open,
44
+ onOpenChange,
45
+ onSave,
46
+ title,
47
+ description,
48
+ initialConfig = null,
49
+ requireApiKey = true,
50
+ busy = false,
51
+ error
52
+ }) => {
53
+ const [execTimeoutMs, setExecTimeoutMs] = useState("");
54
+ const [autoStopIntervalInMinutes, setAutoStopIntervalInMinutes] = useState("");
55
+ const [autoArchiveIntervalInMinutes, setAutoArchiveIntervalInMinutes] = useState("");
56
+ const [autoDeleteIntervalInMinutes, setAutoDeleteIntervalInMinutes] = useState("");
57
+ const [apiKey, setApiKey] = useState("");
58
+ const [advancedOpen, setAdvancedOpen] = useState(false);
59
+ const resetForm = () => {
60
+ setExecTimeoutMs("");
61
+ setAutoStopIntervalInMinutes("");
62
+ setAutoArchiveIntervalInMinutes("");
63
+ setAutoDeleteIntervalInMinutes("");
64
+ setApiKey("");
65
+ setAdvancedOpen(false);
66
+ };
67
+ useEffect(() => {
68
+ if (!open) return;
69
+ const config = initialConfig ?? EMPTY_CONFIG;
70
+ setExecTimeoutMs(String(config.execTimeoutMs));
71
+ setAutoStopIntervalInMinutes(String(config.autoStopIntervalInMinutes));
72
+ setAutoArchiveIntervalInMinutes(String(config.autoArchiveIntervalInMinutes));
73
+ setAutoDeleteIntervalInMinutes(String(config.autoDeleteIntervalInMinutes));
74
+ setApiKey("");
75
+ setAdvancedOpen(false);
76
+ }, [open, initialConfig]);
77
+ const handleOpenChange = (nextOpen) => {
78
+ if (!nextOpen) resetForm();
79
+ onOpenChange(nextOpen);
80
+ };
81
+ const execTimeout = parseNonNegInt(execTimeoutMs);
82
+ const autoStop = parseNonNegInt(autoStopIntervalInMinutes);
83
+ const autoArchive = parseNonNegInt(autoArchiveIntervalInMinutes);
84
+ const autoDelete = parseNonNegInt(autoDeleteIntervalInMinutes);
85
+ const trimmedKey = apiKey.trim();
86
+ const isValid = (!requireApiKey || !!trimmedKey) && execTimeout != null && autoStop != null && autoArchive != null && autoDelete != null;
87
+ const handleSubmit = async (event) => {
88
+ event.preventDefault();
89
+ if (!isValid || busy || execTimeout == null || autoStop == null || autoArchive == null || autoDelete == null) {
90
+ return;
91
+ }
92
+ try {
93
+ await onSave({
94
+ // Snapshot/image is release-owned; the field is retained only for the external type.
95
+ snapshotName: "",
96
+ execTimeoutMs: execTimeout,
97
+ autoStopIntervalInMinutes: autoStop,
98
+ autoArchiveIntervalInMinutes: autoArchive,
99
+ autoDeleteIntervalInMinutes: autoDelete,
100
+ apiKey: trimmedKey
101
+ });
102
+ resetForm();
103
+ onOpenChange(false);
104
+ } catch {
105
+ }
106
+ };
107
+ return /* @__PURE__ */ jsx(
108
+ CenteredModal,
109
+ {
110
+ open,
111
+ onOpenChange: handleOpenChange,
112
+ title,
113
+ description,
114
+ contentSized: true,
115
+ headerIcon: /* @__PURE__ */ jsx(
116
+ "span",
117
+ {
118
+ className: "flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary",
119
+ "aria-hidden": true,
120
+ children: /* @__PURE__ */ jsx(Icon, { name: "cube", className: "size-6" })
121
+ }
122
+ ),
123
+ children: /* @__PURE__ */ jsxs("form", { className: "flex flex-col overflow-y-auto p-5 md:p-6", onSubmit: handleSubmit, children: [
124
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
125
+ /* @__PURE__ */ jsxs("div", { children: [
126
+ /* @__PURE__ */ jsxs("label", { htmlFor: "sandbox-api-key", className: "mb-1.5 block text-sm font-medium text-text-primary", children: [
127
+ "API key",
128
+ !requireApiKey ? /* @__PURE__ */ jsx("span", { className: "font-normal text-text-secondary", children: " (optional)" }) : null
129
+ ] }),
130
+ /* @__PURE__ */ jsx(
131
+ "input",
132
+ {
133
+ id: "sandbox-api-key",
134
+ type: "password",
135
+ required: requireApiKey,
136
+ value: apiKey,
137
+ onChange: (event) => {
138
+ setApiKey(event.target.value);
139
+ },
140
+ placeholder: requireApiKey ? "dtn_..." : "Leave blank to keep existing",
141
+ autoFocus: true,
142
+ className: inputClassName
143
+ }
144
+ )
145
+ ] }),
146
+ /* @__PURE__ */ jsxs(
147
+ Accordion,
148
+ {
149
+ expanded: advancedOpen,
150
+ onChange: (_event, next) => setAdvancedOpen(next),
151
+ className: "rounded-md border border-border",
152
+ children: [
153
+ /* @__PURE__ */ jsx(AccordionSummary, { className: "px-3 py-2.5", children: /* @__PURE__ */ jsxs("span", { className: "flex w-full items-center justify-between text-sm font-medium text-text-primary", children: [
154
+ "Advanced settings",
155
+ /* @__PURE__ */ jsx(
156
+ Icon,
157
+ {
158
+ name: "chevron-down",
159
+ className: cn(
160
+ "size-4 shrink-0 text-text-secondary transition-transform duration-200",
161
+ advancedOpen ? "rotate-0" : "-rotate-90"
162
+ )
163
+ }
164
+ )
165
+ ] }) }),
166
+ /* @__PURE__ */ jsxs(AccordionDetails, { className: "space-y-4 border-t border-border px-3 pb-3 pt-4", children: [
167
+ /* @__PURE__ */ jsxs("div", { children: [
168
+ /* @__PURE__ */ jsx("label", { htmlFor: "sandbox-exec-timeout", className: "mb-1.5 block text-sm font-medium text-text-primary", children: "Exec timeout (ms)" }),
169
+ /* @__PURE__ */ jsx(
170
+ "input",
171
+ {
172
+ id: "sandbox-exec-timeout",
173
+ type: "number",
174
+ min: 0,
175
+ required: true,
176
+ value: execTimeoutMs,
177
+ onChange: (event) => {
178
+ setExecTimeoutMs(event.target.value);
179
+ },
180
+ placeholder: "300000",
181
+ className: inputClassName
182
+ }
183
+ )
184
+ ] }),
185
+ /* @__PURE__ */ jsxs("div", { children: [
186
+ /* @__PURE__ */ jsx("label", { htmlFor: "sandbox-auto-stop", className: "mb-1.5 block text-sm font-medium text-text-primary", children: "Auto-stop interval (minutes)" }),
187
+ /* @__PURE__ */ jsx(
188
+ "input",
189
+ {
190
+ id: "sandbox-auto-stop",
191
+ type: "number",
192
+ min: 0,
193
+ required: true,
194
+ value: autoStopIntervalInMinutes,
195
+ onChange: (event) => {
196
+ setAutoStopIntervalInMinutes(event.target.value);
197
+ },
198
+ placeholder: "15",
199
+ className: inputClassName
200
+ }
201
+ )
202
+ ] }),
203
+ /* @__PURE__ */ jsxs("div", { children: [
204
+ /* @__PURE__ */ jsx("label", { htmlFor: "sandbox-auto-archive", className: "mb-1.5 block text-sm font-medium text-text-primary", children: "Auto-archive interval (minutes)" }),
205
+ /* @__PURE__ */ jsx(
206
+ "input",
207
+ {
208
+ id: "sandbox-auto-archive",
209
+ type: "number",
210
+ min: 0,
211
+ required: true,
212
+ value: autoArchiveIntervalInMinutes,
213
+ onChange: (event) => {
214
+ setAutoArchiveIntervalInMinutes(event.target.value);
215
+ },
216
+ placeholder: "10080",
217
+ className: inputClassName
218
+ }
219
+ )
220
+ ] }),
221
+ /* @__PURE__ */ jsxs("div", { children: [
222
+ /* @__PURE__ */ jsx("label", { htmlFor: "sandbox-auto-delete", className: "mb-1.5 block text-sm font-medium text-text-primary", children: "Auto-delete interval (minutes)" }),
223
+ /* @__PURE__ */ jsx(
224
+ "input",
225
+ {
226
+ id: "sandbox-auto-delete",
227
+ type: "number",
228
+ min: 0,
229
+ required: true,
230
+ value: autoDeleteIntervalInMinutes,
231
+ onChange: (event) => {
232
+ setAutoDeleteIntervalInMinutes(event.target.value);
233
+ },
234
+ placeholder: "43200",
235
+ className: inputClassName
236
+ }
237
+ )
238
+ ] })
239
+ ] })
240
+ ]
241
+ }
242
+ )
243
+ ] }),
244
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-3", children: [
245
+ error ? /* @__PURE__ */ jsx("p", { className: "text-failure-bg text-sm", children: error }) : null,
246
+ /* @__PURE__ */ jsx(Button, { type: "submit", size: "lg", disabled: !isValid || busy, className: "w-full shrink-0", children: "Save" })
247
+ ] })
248
+ ] })
249
+ }
250
+ );
251
+ };
252
+ var ConfigureSandboxForm_default = ConfigureSandboxForm;
253
+
254
+ // src/containers/SettingsBuilder/SandboxSettings.tsx
255
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
256
+ var configFrom = ({
257
+ snapshotName,
258
+ execTimeoutMs,
259
+ autoStopIntervalInMinutes,
260
+ autoArchiveIntervalInMinutes,
261
+ autoDeleteIntervalInMinutes
262
+ }) => ({
263
+ snapshotName,
264
+ execTimeoutMs,
265
+ autoStopIntervalInMinutes,
266
+ autoArchiveIntervalInMinutes,
267
+ autoDeleteIntervalInMinutes
268
+ });
269
+ var SandboxSettings = () => {
270
+ const { sandboxCatalog } = useCatalogServer();
271
+ const toaster = useToasterOptional();
272
+ const [providers, setProviders] = useState2([]);
273
+ const [catalog, setCatalog] = useState2([]);
274
+ const [loading, setLoading] = useState2(true);
275
+ const [error, setError] = useState2(null);
276
+ const [formError, setFormError] = useState2(null);
277
+ const [busy, setBusy] = useState2(false);
278
+ const [createEntry, setCreateEntry] = useState2(null);
279
+ const [updateProvider, setUpdateProvider] = useState2(null);
280
+ const refresh = useCallback(
281
+ async ({ quiet = false } = {}) => {
282
+ if (!sandboxCatalog) return;
283
+ if (!quiet) setLoading(true);
284
+ setError(null);
285
+ try {
286
+ const [listed, available] = await Promise.all([
287
+ sandboxCatalog.listSandboxProviders(),
288
+ sandboxCatalog.getSandboxProviderCatalog()
289
+ ]);
290
+ setProviders(listed);
291
+ setCatalog(available);
292
+ } catch (err) {
293
+ setError(getErrorMessage(err, "Failed to load sandbox providers"));
294
+ } finally {
295
+ if (!quiet) setLoading(false);
296
+ }
297
+ },
298
+ [sandboxCatalog]
299
+ );
300
+ useEffect2(() => {
301
+ void refresh();
302
+ }, [refresh]);
303
+ const hasConfiguredProvider = providers.length > 0;
304
+ const availableEntries = useMemo(() => {
305
+ if (hasConfiguredProvider) return [];
306
+ const connectedCatalogIds = new Set(providers.map((provider) => provider.catalogId));
307
+ return catalog.filter((entry) => !connectedCatalogIds.has(entry.id));
308
+ }, [catalog, providers, hasConfiguredProvider]);
309
+ const formInitialConfig = useMemo(
310
+ () => updateProvider ? configFrom(updateProvider) : createEntry ? configFrom(createEntry) : null,
311
+ [updateProvider, createEntry]
312
+ );
313
+ if (!sandboxCatalog) {
314
+ return /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary", children: "Sandbox provider catalog is not available." });
315
+ }
316
+ const runMutation = async (fn, setMutationError = setError) => {
317
+ setBusy(true);
318
+ setError(null);
319
+ try {
320
+ await fn();
321
+ await refresh({ quiet: true });
322
+ } catch (err) {
323
+ setMutationError(getErrorMessage(err, "Request failed"));
324
+ throw err;
325
+ } finally {
326
+ setBusy(false);
327
+ }
328
+ };
329
+ const handleCreate = async (draft) => {
330
+ if (!createEntry) return;
331
+ setFormError(null);
332
+ await runMutation(async () => {
333
+ await sandboxCatalog.createSandboxProvider({
334
+ catalogId: createEntry.id,
335
+ name: createEntry.name,
336
+ type: createEntry.type,
337
+ ...configFrom(draft),
338
+ apiKey: draft.apiKey
339
+ });
340
+ }, setFormError);
341
+ setCreateEntry(null);
342
+ setTimeout(() => {
343
+ toaster?.showSuccess({ title: `${createEntry.name} configured` });
344
+ }, 0);
345
+ };
346
+ const handleUpdate = async (draft) => {
347
+ if (!updateProvider) return;
348
+ setFormError(null);
349
+ await runMutation(async () => {
350
+ await sandboxCatalog.updateSandboxProvider({
351
+ id: updateProvider.id,
352
+ ...configFrom(draft),
353
+ ...draft.apiKey ? { apiKey: draft.apiKey } : {}
354
+ });
355
+ }, setFormError);
356
+ setUpdateProvider(null);
357
+ setTimeout(() => {
358
+ toaster?.showSuccess({ title: `${updateProvider.name} updated` });
359
+ }, 0);
360
+ };
361
+ const handleRemove = (provider) => {
362
+ const deleteSandboxProvider = sandboxCatalog.deleteSandboxProvider;
363
+ if (!deleteSandboxProvider) return;
364
+ void runMutation(async () => {
365
+ await deleteSandboxProvider({ id: provider.id });
366
+ }).catch(() => {
367
+ });
368
+ };
369
+ const formOpen = createEntry != null || updateProvider != null;
370
+ const isUpdate = updateProvider != null;
371
+ const formTitle = updateProvider ? `Update ${updateProvider.name}` : createEntry ? `Configure ${createEntry.name}` : "Configure sandbox provider";
372
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
373
+ /* @__PURE__ */ jsx2("h3", { className: "text-xl font-semibold tracking-tight text-text-primary", children: "Sandbox providers" }),
374
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-text-secondary", children: "Choose a provider that runs sandboxes for code, files and shell commands. Only one can be active at a time." }),
375
+ error ? /* @__PURE__ */ jsx2("p", { className: "mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg", children: error }) : null,
376
+ /* @__PURE__ */ jsx2("div", { className: "mt-4 flex-1 overflow-y-auto", children: loading ? /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary", children: "Loading sandbox providers\u2026" }) : /* @__PURE__ */ jsxs2("div", { className: "space-y-6", children: [
377
+ providers.length > 0 ? /* @__PURE__ */ jsxs2("section", { children: [
378
+ /* @__PURE__ */ jsxs2("h4", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary", children: [
379
+ "Configured \xB7 ",
380
+ providers.length
381
+ ] }),
382
+ /* @__PURE__ */ jsx2("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: providers.map((provider) => /* @__PURE__ */ jsxs2(
383
+ "article",
384
+ {
385
+ className: "flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center",
386
+ children: [
387
+ /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
388
+ /* @__PURE__ */ jsx2(
389
+ "span",
390
+ {
391
+ className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary",
392
+ "aria-hidden": true,
393
+ children: /* @__PURE__ */ jsx2(Icon, { name: "cube", className: "size-4.5" })
394
+ }
395
+ ),
396
+ /* @__PURE__ */ jsx2("div", { className: "min-w-0", children: /* @__PURE__ */ jsx2("h5", { className: "truncate text-sm font-medium text-text-primary", children: provider.name }) })
397
+ ] }),
398
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center gap-2.5 sm:justify-end", children: [
399
+ provider.isConnected ? /* @__PURE__ */ jsxs2("span", { className: "flex items-center gap-1.5 rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium text-success-bg", children: [
400
+ /* @__PURE__ */ jsx2("span", { className: "h-1.5 w-1.5 rounded-full bg-success-bg" }),
401
+ "Connected"
402
+ ] }) : null,
403
+ /* @__PURE__ */ jsx2(
404
+ Button,
405
+ {
406
+ variant: "secondary",
407
+ size: "sm",
408
+ type: "button",
409
+ disabled: busy,
410
+ onClick: () => {
411
+ setFormError(null);
412
+ setCreateEntry(null);
413
+ setUpdateProvider(provider);
414
+ },
415
+ children: "Update"
416
+ }
417
+ ),
418
+ sandboxCatalog.deleteSandboxProvider ? /* @__PURE__ */ jsx2(
419
+ Button,
420
+ {
421
+ variant: "ghost",
422
+ size: "sm",
423
+ className: "text-text-secondary",
424
+ type: "button",
425
+ disabled: busy,
426
+ onClick: () => {
427
+ handleRemove(provider);
428
+ },
429
+ children: "Remove"
430
+ }
431
+ ) : null
432
+ ] })
433
+ ]
434
+ },
435
+ provider.id
436
+ )) })
437
+ ] }) : null,
438
+ !hasConfiguredProvider ? /* @__PURE__ */ jsxs2("section", { children: [
439
+ /* @__PURE__ */ jsxs2("h4", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary", children: [
440
+ "Available \xB7 ",
441
+ availableEntries.length
442
+ ] }),
443
+ availableEntries.length === 0 ? /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary", children: catalog.length > 0 ? "All catalog providers are configured." : "No sandbox providers in the catalog." }) : /* @__PURE__ */ jsx2("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: availableEntries.map((entry) => /* @__PURE__ */ jsxs2(
444
+ "article",
445
+ {
446
+ className: "flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center",
447
+ children: [
448
+ /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
449
+ /* @__PURE__ */ jsx2(
450
+ "span",
451
+ {
452
+ className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary",
453
+ "aria-hidden": true,
454
+ children: /* @__PURE__ */ jsx2(Icon, { name: "cube", className: "size-4.5" })
455
+ }
456
+ ),
457
+ /* @__PURE__ */ jsx2("div", { className: "min-w-0", children: /* @__PURE__ */ jsx2("h5", { className: "truncate text-sm font-medium text-text-primary", children: entry.name }) })
458
+ ] }),
459
+ /* @__PURE__ */ jsx2(
460
+ Button,
461
+ {
462
+ variant: "secondary",
463
+ type: "button",
464
+ disabled: busy,
465
+ onClick: () => {
466
+ setFormError(null);
467
+ setUpdateProvider(null);
468
+ setCreateEntry(entry);
469
+ },
470
+ children: "Configure"
471
+ }
472
+ )
473
+ ]
474
+ },
475
+ entry.id
476
+ )) })
477
+ ] }) : null
478
+ ] }) }),
479
+ /* @__PURE__ */ jsx2(
480
+ ConfigureSandboxForm_default,
481
+ {
482
+ open: formOpen,
483
+ onOpenChange: (open) => {
484
+ if (!open) {
485
+ setFormError(null);
486
+ setCreateEntry(null);
487
+ setUpdateProvider(null);
488
+ }
489
+ },
490
+ onSave: isUpdate ? handleUpdate : handleCreate,
491
+ title: formTitle,
492
+ description: isUpdate ? "Update this sandbox provider. Leave API key blank to keep the existing key." : "Configure this sandbox provider. API key is never stored in the catalog.",
493
+ initialConfig: formInitialConfig,
494
+ requireApiKey: !isUpdate,
495
+ busy,
496
+ error: formError
497
+ }
498
+ )
499
+ ] });
500
+ };
501
+ var SandboxSettings_default = SandboxSettings;
502
+ export {
503
+ SandboxSettings_default as default
504
+ };
505
+ //# sourceMappingURL=SandboxSettings-S5XGZWOL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/containers/SettingsBuilder/SandboxSettings.tsx","../src/containers/SettingsBuilder/ConfigureSandboxForm.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { Icon } from '../../icons/Icon.js';\nimport { useCatalogServer } from '../../server/ServerContext.js';\nimport type { SandboxProviderBase, SandboxProviderCatalogEntry, SandboxProviderConfig } from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\nimport { useToasterOptional } from '../ToasterContainer.js';\nimport ConfigureSandboxForm, { type SandboxConfigDraft } from './ConfigureSandboxForm.js';\n\nconst configFrom = ({\n snapshotName,\n execTimeoutMs,\n autoStopIntervalInMinutes,\n autoArchiveIntervalInMinutes,\n autoDeleteIntervalInMinutes,\n}: SandboxProviderConfig): SandboxProviderConfig => ({\n snapshotName,\n execTimeoutMs,\n autoStopIntervalInMinutes,\n autoArchiveIntervalInMinutes,\n autoDeleteIntervalInMinutes,\n});\n\nconst SandboxSettings = () => {\n const { sandboxCatalog } = useCatalogServer();\n const toaster = useToasterOptional();\n\n const [providers, setProviders] = useState<SandboxProviderBase[]>([]);\n const [catalog, setCatalog] = useState<SandboxProviderCatalogEntry[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n const [createEntry, setCreateEntry] = useState<SandboxProviderCatalogEntry | null>(null);\n const [updateProvider, setUpdateProvider] = useState<SandboxProviderBase | null>(null);\n\n const refresh = useCallback(\n async ({ quiet = false }: { quiet?: boolean } = {}) => {\n if (!sandboxCatalog) return;\n if (!quiet) setLoading(true);\n setError(null);\n try {\n const [listed, available] = await Promise.all([\n sandboxCatalog.listSandboxProviders(),\n sandboxCatalog.getSandboxProviderCatalog(),\n ]);\n setProviders(listed);\n setCatalog(available);\n } catch (err) {\n setError(getErrorMessage(err, 'Failed to load sandbox providers'));\n } finally {\n if (!quiet) setLoading(false);\n }\n },\n [sandboxCatalog],\n );\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n // Tenant/UI-wide: only one sandbox provider may be configured at a time.\n const hasConfiguredProvider = providers.length > 0;\n const availableEntries = useMemo(() => {\n if (hasConfiguredProvider) return [];\n const connectedCatalogIds = new Set(providers.map(provider => provider.catalogId));\n return catalog.filter(entry => !connectedCatalogIds.has(entry.id));\n }, [catalog, providers, hasConfiguredProvider]);\n\n const formInitialConfig = useMemo(\n () => (updateProvider ? configFrom(updateProvider) : createEntry ? configFrom(createEntry) : null),\n [updateProvider, createEntry],\n );\n\n if (!sandboxCatalog) {\n return <p className=\"text-sm text-text-secondary\">Sandbox provider catalog is not available.</p>;\n }\n\n const runMutation = async (fn: () => Promise<void>, setMutationError = setError) => {\n setBusy(true);\n setError(null);\n try {\n await fn();\n await refresh({ quiet: true });\n } catch (err) {\n setMutationError(getErrorMessage(err, 'Request failed'));\n throw err;\n } finally {\n setBusy(false);\n }\n };\n\n const handleCreate = async (draft: SandboxConfigDraft) => {\n if (!createEntry) return;\n setFormError(null);\n await runMutation(async () => {\n await sandboxCatalog.createSandboxProvider({\n catalogId: createEntry.id,\n name: createEntry.name,\n type: createEntry.type,\n ...configFrom(draft),\n apiKey: draft.apiKey,\n });\n }, setFormError);\n setCreateEntry(null);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${createEntry.name} configured` });\n }, 0);\n };\n\n const handleUpdate = async (draft: SandboxConfigDraft) => {\n if (!updateProvider) return;\n setFormError(null);\n await runMutation(async () => {\n await sandboxCatalog.updateSandboxProvider({\n id: updateProvider.id,\n ...configFrom(draft),\n ...(draft.apiKey ? { apiKey: draft.apiKey } : {}),\n });\n }, setFormError);\n setUpdateProvider(null);\n setTimeout(() => {\n toaster?.showSuccess({ title: `${updateProvider.name} updated` });\n }, 0);\n };\n\n const handleRemove = (provider: SandboxProviderBase) => {\n const deleteSandboxProvider = sandboxCatalog.deleteSandboxProvider;\n if (!deleteSandboxProvider) return;\n void runMutation(async () => {\n await deleteSandboxProvider({ id: provider.id });\n }).catch(() => {});\n };\n\n const formOpen = createEntry != null || updateProvider != null;\n const isUpdate = updateProvider != null;\n const formTitle = updateProvider\n ? `Update ${updateProvider.name}`\n : createEntry\n ? `Configure ${createEntry.name}`\n : 'Configure sandbox provider';\n\n return (\n <>\n <h3 className=\"text-xl font-semibold tracking-tight text-text-primary\">Sandbox providers</h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Choose a provider that runs sandboxes for code, files and shell commands. Only one can be active at a time.\n </p>\n\n {error ? (\n <p className=\"mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg\">\n {error}\n </p>\n ) : null}\n\n <div className=\"mt-4 flex-1 overflow-y-auto\">\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading sandbox providers…</p>\n ) : (\n <div className=\"space-y-6\">\n {providers.length > 0 ? (\n <section>\n <h4 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Configured · {providers.length}\n </h4>\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {providers.map(provider => (\n <article\n key={provider.id}\n className=\"flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center\"\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-4.5\" />\n </span>\n <div className=\"min-w-0\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{provider.name}</h5>\n </div>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2.5 sm:justify-end\">\n {provider.isConnected ? (\n <span className=\"flex items-center gap-1.5 rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium text-success-bg\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-success-bg\"></span>\n Connected\n </span>\n ) : null}\n <Button\n variant=\"secondary\"\n size=\"sm\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setCreateEntry(null);\n setUpdateProvider(provider);\n }}\n >\n Update\n </Button>\n {sandboxCatalog.deleteSandboxProvider ? (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-text-secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n handleRemove(provider);\n }}\n >\n Remove\n </Button>\n ) : null}\n </div>\n </article>\n ))}\n </div>\n </section>\n ) : null}\n\n {!hasConfiguredProvider ? (\n <section>\n <h4 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Available · {availableEntries.length}\n </h4>\n {availableEntries.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {catalog.length > 0\n ? 'All catalog providers are configured.'\n : 'No sandbox providers in the catalog.'}\n </p>\n ) : (\n <div className=\"overflow-hidden rounded-xl border border-border bg-card-bg\">\n {availableEntries.map(entry => (\n <article\n key={entry.id}\n className=\"flex flex-col gap-3 border-b border-border p-3 last:border-b-0 sm:flex-row sm:items-center\"\n >\n <div className=\"flex min-w-0 flex-1 items-center gap-3\">\n <span\n className=\"flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-4.5\" />\n </span>\n <div className=\"min-w-0\">\n <h5 className=\"truncate text-sm font-medium text-text-primary\">{entry.name}</h5>\n </div>\n </div>\n\n <Button\n variant=\"secondary\"\n type=\"button\"\n disabled={busy}\n onClick={() => {\n setFormError(null);\n setUpdateProvider(null);\n setCreateEntry(entry);\n }}\n >\n Configure\n </Button>\n </article>\n ))}\n </div>\n )}\n </section>\n ) : null}\n </div>\n )}\n </div>\n\n <ConfigureSandboxForm\n open={formOpen}\n onOpenChange={open => {\n if (!open) {\n setFormError(null);\n setCreateEntry(null);\n setUpdateProvider(null);\n }\n }}\n onSave={isUpdate ? handleUpdate : handleCreate}\n title={formTitle}\n description={\n isUpdate\n ? 'Update this sandbox provider. Leave API key blank to keep the existing key.'\n : 'Configure this sandbox provider. API key is never stored in the catalog.'\n }\n initialConfig={formInitialConfig}\n requireApiKey={!isUpdate}\n busy={busy}\n error={formError}\n />\n </>\n );\n};\n\nexport default SandboxSettings;\n","'use client';\n\nimport { useEffect, useState, type FormEvent } from 'react';\n\nimport { cn } from '../../atoms/lib/cn.js';\nimport { auiInputClass } from '../../atoms/lib/inputClasses.js';\nimport { Accordion, AccordionDetails, AccordionSummary } from '../../atoms/primitives/Accordion.js';\nimport { Button } from '../../atoms/primitives/Button.js';\nimport { CenteredModal } from '../../atoms/primitives/CenteredModal.js';\nimport { Icon } from '../../icons/Icon.js';\nimport type { SandboxProviderConfig } from '../../server/types.js';\n\nexport type SandboxConfigDraft = SandboxProviderConfig & {\n apiKey: string;\n};\n\ntype ConfigureSandboxFormProps = {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onSave: (draft: SandboxConfigDraft) => void | Promise<void>;\n title: string;\n description?: string;\n /** Prefills config fields; apiKey is never autofilled. */\n initialConfig?: SandboxProviderConfig | null;\n /** When false (updates), empty apiKey means keep the existing key. */\n requireApiKey?: boolean;\n busy?: boolean;\n error?: string | null;\n};\n\n/** Sensible defaults so the advanced fields are never blank, even without a catalog preset. */\nconst EMPTY_CONFIG: SandboxProviderConfig = {\n // Snapshot/image is release-owned now; kept only to satisfy the external SandboxProviderConfig type.\n snapshotName: '',\n execTimeoutMs: 300000,\n autoStopIntervalInMinutes: 15,\n autoArchiveIntervalInMinutes: 10080,\n autoDeleteIntervalInMinutes: 43200,\n};\n\nconst inputClassName = auiInputClass('h-11 shadow-sm');\n\nfunction parseNonNegInt(raw: string): number | null {\n if (raw.trim() === '') return null;\n const n = Number(raw);\n if (!Number.isFinite(n) || n < 0) return null;\n return n;\n}\n\nconst ConfigureSandboxForm = ({\n open,\n onOpenChange,\n onSave,\n title,\n description,\n initialConfig = null,\n requireApiKey = true,\n busy = false,\n error,\n}: ConfigureSandboxFormProps) => {\n const [execTimeoutMs, setExecTimeoutMs] = useState('');\n const [autoStopIntervalInMinutes, setAutoStopIntervalInMinutes] = useState('');\n const [autoArchiveIntervalInMinutes, setAutoArchiveIntervalInMinutes] = useState('');\n const [autoDeleteIntervalInMinutes, setAutoDeleteIntervalInMinutes] = useState('');\n const [apiKey, setApiKey] = useState('');\n const [advancedOpen, setAdvancedOpen] = useState(false);\n\n const resetForm = () => {\n setExecTimeoutMs('');\n setAutoStopIntervalInMinutes('');\n setAutoArchiveIntervalInMinutes('');\n setAutoDeleteIntervalInMinutes('');\n setApiKey('');\n setAdvancedOpen(false);\n };\n\n useEffect(() => {\n if (!open) return;\n const config = initialConfig ?? EMPTY_CONFIG;\n setExecTimeoutMs(String(config.execTimeoutMs));\n setAutoStopIntervalInMinutes(String(config.autoStopIntervalInMinutes));\n setAutoArchiveIntervalInMinutes(String(config.autoArchiveIntervalInMinutes));\n setAutoDeleteIntervalInMinutes(String(config.autoDeleteIntervalInMinutes));\n setApiKey('');\n setAdvancedOpen(false);\n }, [open, initialConfig]);\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!nextOpen) resetForm();\n onOpenChange(nextOpen);\n };\n\n const execTimeout = parseNonNegInt(execTimeoutMs);\n const autoStop = parseNonNegInt(autoStopIntervalInMinutes);\n const autoArchive = parseNonNegInt(autoArchiveIntervalInMinutes);\n const autoDelete = parseNonNegInt(autoDeleteIntervalInMinutes);\n const trimmedKey = apiKey.trim();\n\n const isValid =\n (!requireApiKey || !!trimmedKey) &&\n execTimeout != null &&\n autoStop != null &&\n autoArchive != null &&\n autoDelete != null;\n\n const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n if (!isValid || busy || execTimeout == null || autoStop == null || autoArchive == null || autoDelete == null) {\n return;\n }\n\n try {\n await onSave({\n // Snapshot/image is release-owned; the field is retained only for the external type.\n snapshotName: '',\n execTimeoutMs: execTimeout,\n autoStopIntervalInMinutes: autoStop,\n autoArchiveIntervalInMinutes: autoArchive,\n autoDeleteIntervalInMinutes: autoDelete,\n apiKey: trimmedKey,\n });\n resetForm();\n onOpenChange(false);\n } catch {\n // Parent surfaces error; keep form open.\n }\n };\n\n return (\n <CenteredModal\n open={open}\n onOpenChange={handleOpenChange}\n title={title}\n description={description}\n contentSized\n headerIcon={\n <span\n className=\"flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary\"\n aria-hidden\n >\n <Icon name=\"cube\" className=\"size-6\" />\n </span>\n }\n >\n <form className=\"flex flex-col overflow-y-auto p-5 md:p-6\" onSubmit={handleSubmit}>\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"sandbox-api-key\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n API key\n {!requireApiKey ? <span className=\"font-normal text-text-secondary\"> (optional)</span> : null}\n </label>\n <input\n id=\"sandbox-api-key\"\n type=\"password\"\n required={requireApiKey}\n value={apiKey}\n onChange={event => {\n setApiKey(event.target.value);\n }}\n placeholder={requireApiKey ? 'dtn_...' : 'Leave blank to keep existing'}\n autoFocus\n className={inputClassName}\n />\n </div>\n\n <Accordion\n expanded={advancedOpen}\n onChange={(_event, next) => setAdvancedOpen(next)}\n className=\"rounded-md border border-border\"\n >\n <AccordionSummary className=\"px-3 py-2.5\">\n <span className=\"flex w-full items-center justify-between text-sm font-medium text-text-primary\">\n Advanced settings\n <Icon\n name=\"chevron-down\"\n className={cn(\n 'size-4 shrink-0 text-text-secondary transition-transform duration-200',\n advancedOpen ? 'rotate-0' : '-rotate-90',\n )}\n />\n </span>\n </AccordionSummary>\n <AccordionDetails className=\"space-y-4 border-t border-border px-3 pb-3 pt-4\">\n <div>\n <label htmlFor=\"sandbox-exec-timeout\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Exec timeout (ms)\n </label>\n <input\n id=\"sandbox-exec-timeout\"\n type=\"number\"\n min={0}\n required\n value={execTimeoutMs}\n onChange={event => {\n setExecTimeoutMs(event.target.value);\n }}\n placeholder=\"300000\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-stop\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-stop interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-stop\"\n type=\"number\"\n min={0}\n required\n value={autoStopIntervalInMinutes}\n onChange={event => {\n setAutoStopIntervalInMinutes(event.target.value);\n }}\n placeholder=\"15\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-archive\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-archive interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-archive\"\n type=\"number\"\n min={0}\n required\n value={autoArchiveIntervalInMinutes}\n onChange={event => {\n setAutoArchiveIntervalInMinutes(event.target.value);\n }}\n placeholder=\"10080\"\n className={inputClassName}\n />\n </div>\n\n <div>\n <label htmlFor=\"sandbox-auto-delete\" className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Auto-delete interval (minutes)\n </label>\n <input\n id=\"sandbox-auto-delete\"\n type=\"number\"\n min={0}\n required\n value={autoDeleteIntervalInMinutes}\n onChange={event => {\n setAutoDeleteIntervalInMinutes(event.target.value);\n }}\n placeholder=\"43200\"\n className={inputClassName}\n />\n </div>\n </AccordionDetails>\n </Accordion>\n </div>\n\n <div className=\"mt-6 space-y-3\">\n {error ? <p className=\"text-failure-bg text-sm\">{error}</p> : null}\n <Button type=\"submit\" size=\"lg\" disabled={!isValid || busy} className=\"w-full shrink-0\">\n Save\n </Button>\n </div>\n </form>\n </CenteredModal>\n );\n};\n\nexport default ConfigureSandboxForm;\n"],"mappings":"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","names":["useEffect","useState","jsx","jsxs","useState","useEffect"]}