@datatechsolutions/ui 2.11.80 → 2.11.82

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 (57) hide show
  1. package/dist/astrlabe/contracts.d.mts +24 -1
  2. package/dist/astrlabe/contracts.d.ts +24 -1
  3. package/dist/astrlabe/index.d.mts +25 -84
  4. package/dist/astrlabe/index.d.ts +25 -84
  5. package/dist/astrlabe/index.js +175 -4570
  6. package/dist/astrlabe/index.js.map +1 -1
  7. package/dist/astrlabe/index.mjs +3 -4535
  8. package/dist/astrlabe/index.mjs.map +1 -1
  9. package/dist/astrlabe/workflow-canvas.d.mts +69 -5
  10. package/dist/astrlabe/workflow-canvas.d.ts +69 -5
  11. package/dist/chunk-6PBTB5ZX.js +165 -0
  12. package/dist/chunk-6PBTB5ZX.js.map +1 -0
  13. package/dist/chunk-HAZP5J67.mjs +4781 -0
  14. package/dist/chunk-HAZP5J67.mjs.map +1 -0
  15. package/dist/chunk-HZ4LOVHM.js +46 -0
  16. package/dist/chunk-HZ4LOVHM.js.map +1 -0
  17. package/dist/chunk-K4QJV3GC.js +4825 -0
  18. package/dist/chunk-K4QJV3GC.js.map +1 -0
  19. package/dist/chunk-UHHPBREK.mjs +135 -0
  20. package/dist/chunk-UHHPBREK.mjs.map +1 -0
  21. package/dist/chunk-ZJPNP2YW.mjs +44 -0
  22. package/dist/chunk-ZJPNP2YW.mjs.map +1 -0
  23. package/dist/{workflow-canvas-NSxfr5dy.d.ts → index-AioB90qq.d.mts} +2 -67
  24. package/dist/{workflow-canvas-D4928AfA.d.mts → index-D5ai0cGZ.d.ts} +2 -67
  25. package/dist/platform/index.d.mts +41 -0
  26. package/dist/platform/index.d.ts +41 -0
  27. package/dist/platform/index.js +237 -0
  28. package/dist/platform/index.js.map +1 -0
  29. package/dist/platform/index.mjs +109 -0
  30. package/dist/platform/index.mjs.map +1 -0
  31. package/dist/platform/pages/index.d.mts +272 -0
  32. package/dist/platform/pages/index.d.ts +272 -0
  33. package/dist/platform/pages/index.js +1793 -0
  34. package/dist/platform/pages/index.js.map +1 -0
  35. package/dist/platform/pages/index.mjs +1777 -0
  36. package/dist/platform/pages/index.mjs.map +1 -0
  37. package/dist/platform/rbac.d.mts +41 -0
  38. package/dist/platform/rbac.d.ts +41 -0
  39. package/dist/platform/rbac.js +13 -0
  40. package/dist/platform/rbac.js.map +1 -0
  41. package/dist/platform/rbac.mjs +4 -0
  42. package/dist/platform/rbac.mjs.map +1 -0
  43. package/dist/platform/utils/index.d.mts +32 -0
  44. package/dist/platform/utils/index.d.ts +32 -0
  45. package/dist/platform/utils/index.js +131 -0
  46. package/dist/platform/utils/index.js.map +1 -0
  47. package/dist/platform/utils/index.mjs +119 -0
  48. package/dist/platform/utils/index.mjs.map +1 -0
  49. package/dist/platform/windsock-admin-client.d.mts +57 -0
  50. package/dist/platform/windsock-admin-client.d.ts +57 -0
  51. package/dist/platform/windsock-admin-client.js +125 -0
  52. package/dist/platform/windsock-admin-client.js.map +1 -0
  53. package/dist/platform/windsock-admin-client.mjs +4 -0
  54. package/dist/platform/windsock-admin-client.mjs.map +1 -0
  55. package/dist/rule-form-F5jBOeqk.d.mts +79 -0
  56. package/dist/rule-form-F5jBOeqk.d.ts +79 -0
  57. package/package.json +28 -1
@@ -0,0 +1,1793 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunkK4QJV3GC_js = require('../../chunk-K4QJV3GC.js');
5
+ require('../../chunk-55H6WZQP.js');
6
+ require('../../chunk-5UU3RQRB.js');
7
+ require('../../chunk-M7P2TQ6X.js');
8
+ var chunkTUEYBNWL_js = require('../../chunk-TUEYBNWL.js');
9
+ require('../../chunk-YXN2K77G.js');
10
+ require('../../chunk-S7KHTUHA.js');
11
+ require('../../chunk-UZ3CMNUJ.js');
12
+ require('../../chunk-P4YYEM4B.js');
13
+ require('../../chunk-C7BI5LQ6.js');
14
+ var react = require('react');
15
+ var outline = require('@heroicons/react/24/outline');
16
+ var jsxRuntime = require('react/jsx-runtime');
17
+
18
+ var ROLE_OPTIONS = [
19
+ { value: "admin", label: "Admin" },
20
+ { value: "manager", label: "Manager" },
21
+ { value: "analyst", label: "Analyst" },
22
+ { value: "viewer", label: "Viewer" }
23
+ ];
24
+ function UsersPageView({ labels, users, onCreateUser, onUpdateRole }) {
25
+ const [createOpen, setCreateOpen] = react.useState(false);
26
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
27
+ /* @__PURE__ */ jsxRuntime.jsx(
28
+ chunkTUEYBNWL_js.HeroSection,
29
+ {
30
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.UserGroupIcon, { className: "h-5 w-5" }),
31
+ label: labels.title,
32
+ title: labels.title,
33
+ subtitle: labels.subtitle,
34
+ gradient: "from-violet-500 to-indigo-600",
35
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
36
+ chunkTUEYBNWL_js.CreateActionButton,
37
+ {
38
+ mode: "desktop",
39
+ label: labels.create,
40
+ onClick: () => setCreateOpen(true),
41
+ accent: "violet"
42
+ }
43
+ )
44
+ }
45
+ ),
46
+ /* @__PURE__ */ jsxRuntime.jsx(
47
+ chunkTUEYBNWL_js.CreateActionButton,
48
+ {
49
+ mode: "mobile",
50
+ label: labels.create,
51
+ onClick: () => setCreateOpen(true),
52
+ accent: "violet"
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
56
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: labels.list }),
57
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: users.map((user) => /* @__PURE__ */ jsxRuntime.jsx(
58
+ chunkTUEYBNWL_js.EntityCard,
59
+ {
60
+ accentGradient: "from-violet-500 to-indigo-700",
61
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-violet-500/10 text-violet-600 dark:bg-violet-500/20 dark:text-violet-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.UserGroupIcon, { className: "h-6 w-6" }) }),
62
+ title: user.name,
63
+ subtitle: user.email,
64
+ status: /* @__PURE__ */ jsxRuntime.jsx(
65
+ "span",
66
+ {
67
+ className: `shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold ${user.active ? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300" : "bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300"}`,
68
+ children: user.active ? labels.statusActive : labels.statusInactive
69
+ }
70
+ ),
71
+ footer: /* @__PURE__ */ jsxRuntime.jsx(
72
+ "form",
73
+ {
74
+ onSubmit: (event) => {
75
+ event.preventDefault();
76
+ const formData = new FormData(event.currentTarget);
77
+ const role = String(formData.get("role") ?? "viewer");
78
+ onUpdateRole({ email: user.email, role });
79
+ },
80
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.InlineForm, { children: [
81
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormSelect, { name: "role", options: ROLE_OPTIONS, defaultValue: user.role }),
82
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "submit", outline: true, size: "sm", children: labels.save })
83
+ ] })
84
+ }
85
+ )
86
+ },
87
+ user.email
88
+ )) })
89
+ ] }),
90
+ /* @__PURE__ */ jsxRuntime.jsx(
91
+ chunkTUEYBNWL_js.GlassModal,
92
+ {
93
+ open: createOpen,
94
+ onClose: () => setCreateOpen(false),
95
+ title: labels.create,
96
+ maxWidth: "lg",
97
+ showFormFooter: true,
98
+ cancelLabel: labels.list,
99
+ submitLabel: labels.add,
100
+ onSubmit: (event) => {
101
+ const formData = new FormData(event.currentTarget);
102
+ const name = String(formData.get("name") ?? "").trim();
103
+ const email = String(formData.get("email") ?? "").trim().toLowerCase();
104
+ const role = String(formData.get("role") ?? "viewer");
105
+ if (!name || !email) return;
106
+ onCreateUser({ name, email, role });
107
+ setCreateOpen(false);
108
+ },
109
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
110
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "name", label: labels.name, placeholder: labels.userNamePlaceholder, required: true }),
111
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "email", label: labels.email, placeholder: labels.userEmailPlaceholder, required: true, type: "email" }),
112
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormSelect, { name: "role", label: labels.role, options: ROLE_OPTIONS })
113
+ ] })
114
+ }
115
+ )
116
+ ] });
117
+ }
118
+ function AgentsModelsPageView({ labels, models, loading }) {
119
+ const hero = /* @__PURE__ */ jsxRuntime.jsx(
120
+ chunkTUEYBNWL_js.HeroSection,
121
+ {
122
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CubeTransparentIcon, { className: "h-5 w-5" }),
123
+ label: labels.title,
124
+ title: labels.title,
125
+ subtitle: labels.subtitle,
126
+ gradient: "from-emerald-500 to-teal-700"
127
+ }
128
+ );
129
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageLoadingState, {}) : models.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageEmptyState, { title: labels.empty, message: labels.subtitle, iconName: "folder-open" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: models.map((model) => /* @__PURE__ */ jsxRuntime.jsx(
130
+ chunkTUEYBNWL_js.EntityCard,
131
+ {
132
+ accentGradient: "from-emerald-500 to-teal-700",
133
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-emerald-500/10 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.CubeTransparentIcon, { className: "h-6 w-6" }) }),
134
+ title: model.name,
135
+ subtitle: `${labels.provider}: ${model.provider}`,
136
+ status: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Badge, { color: model.enabled ? "emerald" : "zinc", children: model.enabled ? labels.enabled : labels.disabled })
137
+ },
138
+ model.id
139
+ )) });
140
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.ManagementPageLayout, { hero, content });
141
+ }
142
+ function AgentsConfigPageView({ labels, agents, models, loading, onCreate, onUpdate, onDelete }) {
143
+ const [editing, setEditing] = react.useState(null);
144
+ const [createOpen, setCreateOpen] = react.useState(false);
145
+ const modelOptions = models.map((model) => ({ value: model.id, label: `${model.name} (${model.provider})` }));
146
+ const hero = /* @__PURE__ */ jsxRuntime.jsx(
147
+ chunkTUEYBNWL_js.HeroSection,
148
+ {
149
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CpuChipIcon, { className: "h-5 w-5" }),
150
+ label: labels.title,
151
+ title: labels.title,
152
+ subtitle: labels.subtitle,
153
+ gradient: "from-violet-500 to-indigo-700",
154
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
155
+ chunkTUEYBNWL_js.CreateActionButton,
156
+ {
157
+ mode: "desktop",
158
+ label: labels.addAgent,
159
+ onClick: () => setCreateOpen(true),
160
+ accent: "violet"
161
+ }
162
+ )
163
+ }
164
+ );
165
+ const mobileAction = /* @__PURE__ */ jsxRuntime.jsx(
166
+ chunkTUEYBNWL_js.CreateActionButton,
167
+ {
168
+ mode: "mobile",
169
+ label: labels.addAgent,
170
+ onClick: () => setCreateOpen(true),
171
+ accent: "violet"
172
+ }
173
+ );
174
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageLoadingState, {}) : agents.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageEmptyState, { title: labels.empty, message: labels.subtitle, iconName: "folder-open" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => {
175
+ const modelRecord = models.find((model) => model.id === String(agent.modelId ?? ""));
176
+ return /* @__PURE__ */ jsxRuntime.jsx(
177
+ chunkTUEYBNWL_js.EntityCard,
178
+ {
179
+ accentGradient: "from-violet-500 to-indigo-700",
180
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-violet-500/10 text-violet-600 dark:bg-violet-500/20 dark:text-violet-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.CpuChipIcon, { className: "h-6 w-6" }) }),
181
+ title: String(agent.name ?? ""),
182
+ subtitle: String(modelRecord?.name ?? agent.modelId ?? ""),
183
+ status: agent.activePromptVersion > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.Badge, { color: "emerald", children: [
184
+ "v",
185
+ agent.activePromptVersion
186
+ ] }) : null,
187
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
188
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", size: "sm", outline: true, onClick: () => setEditing(agent), children: labels.edit }),
189
+ /* @__PURE__ */ jsxRuntime.jsx(
190
+ chunkTUEYBNWL_js.Button,
191
+ {
192
+ type: "button",
193
+ size: "sm",
194
+ color: "rose",
195
+ onClick: () => {
196
+ if (window.confirm(labels.deleteConfirm)) onDelete(agent);
197
+ },
198
+ children: labels.delete
199
+ }
200
+ )
201
+ ] }),
202
+ children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
203
+ labels.activeVersion,
204
+ ": ",
205
+ agent.activePromptVersion,
206
+ " \xB7 Prompts: ",
207
+ agent.promptCount
208
+ ] })
209
+ },
210
+ String(agent.agentId ?? agent.id ?? agent.name)
211
+ );
212
+ }) });
213
+ const renderForm = (initial, onSubmit) => /* @__PURE__ */ jsxRuntime.jsx(
214
+ chunkTUEYBNWL_js.GlassModal,
215
+ {
216
+ open: true,
217
+ onClose: () => {
218
+ setEditing(null);
219
+ setCreateOpen(false);
220
+ },
221
+ title: initial.title,
222
+ maxWidth: "lg",
223
+ showFormFooter: true,
224
+ submitLabel: labels.save,
225
+ onSubmit: (event) => {
226
+ const form = new FormData(event.currentTarget);
227
+ onSubmit({
228
+ agentId: initial.agentId,
229
+ name: String(form.get("name") ?? "").trim(),
230
+ modelId: String(form.get("modelId") ?? ""),
231
+ systemPrompt: String(form.get("systemPrompt") ?? "").trim(),
232
+ maxTokens: Number(form.get("maxTokens") ?? 2048),
233
+ temperature: Number(form.get("temperature") ?? 0.2),
234
+ outputSchema: String(form.get("outputSchema") ?? "").trim() || void 0
235
+ });
236
+ },
237
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
238
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "name", label: labels.name, defaultValue: initial.name ?? "", required: true }),
239
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormSelect, { name: "modelId", label: labels.model, options: modelOptions, defaultValue: initial.modelId ?? modelOptions[0]?.value ?? "", required: true }),
240
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "maxTokens", label: String(labels.maxTokens), type: "number", defaultValue: String(initial.maxTokens ?? 2048) }),
241
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "temperature", label: labels.temperature, type: "number", step: 0.1, min: 0, max: 2, defaultValue: String(initial.temperature ?? 0.2) }),
242
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormTextarea, { name: "systemPrompt", label: labels.systemPrompt, defaultValue: initial.systemPrompt ?? "", rows: 4 }),
243
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormTextarea, { name: "outputSchema", label: labels.outputSchema, placeholder: labels.outputSchemaPlaceholder, defaultValue: initial.outputSchema ?? "", rows: 4 })
244
+ ] })
245
+ }
246
+ );
247
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
248
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.ManagementPageLayout, { hero, content, mobileAction }),
249
+ createOpen && renderForm({ title: labels.createTitle }, (input) => {
250
+ onCreate(input);
251
+ setCreateOpen(false);
252
+ }),
253
+ editing && renderForm(
254
+ {
255
+ title: labels.editTitle,
256
+ agentId: String(editing.agentId ?? editing.id ?? ""),
257
+ name: String(editing.name ?? ""),
258
+ modelId: String(editing.modelId ?? ""),
259
+ systemPrompt: String(editing.systemPrompt ?? ""),
260
+ maxTokens: Number(editing.maxTokens ?? 2048),
261
+ temperature: Number(editing.temperature ?? 0.2),
262
+ outputSchema: String(editing.outputSchema ?? "")
263
+ },
264
+ (input) => {
265
+ onUpdate(String(editing.agentId ?? editing.id ?? ""), input);
266
+ setEditing(null);
267
+ }
268
+ )
269
+ ] });
270
+ }
271
+ var LOCALE_OPTIONS = [
272
+ { value: "en", label: "English" },
273
+ { value: "pt-BR", label: "Portugu\xEAs (Brasil)" },
274
+ { value: "es", label: "Espa\xF1ol" },
275
+ { value: "fr", label: "Fran\xE7ais" },
276
+ { value: "de", label: "Deutsch" },
277
+ { value: "it", label: "Italiano" }
278
+ ];
279
+ function AgentsPromptsPageView({ labels, agents, prompts, loading, onCreate, onActivate, onDelete }) {
280
+ const [createOpen, setCreateOpen] = react.useState(false);
281
+ const agentOptions = react.useMemo(
282
+ () => agents.map((agent) => ({
283
+ value: String(agent.agentId ?? agent.id ?? ""),
284
+ label: String(agent.name ?? agent.agentId ?? agent.id ?? "")
285
+ })),
286
+ [agents]
287
+ );
288
+ const agentNameById = react.useMemo(() => {
289
+ const map = /* @__PURE__ */ new Map();
290
+ for (const agent of agents) {
291
+ const id = String(agent.agentId ?? agent.id ?? "");
292
+ if (id) map.set(id, String(agent.name ?? id));
293
+ }
294
+ return map;
295
+ }, [agents]);
296
+ const hero = /* @__PURE__ */ jsxRuntime.jsx(
297
+ chunkTUEYBNWL_js.HeroSection,
298
+ {
299
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.ChatBubbleLeftEllipsisIcon, { className: "h-5 w-5" }),
300
+ label: labels.title,
301
+ title: labels.title,
302
+ subtitle: labels.subtitle,
303
+ gradient: "from-sky-500 to-blue-700",
304
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
305
+ chunkTUEYBNWL_js.CreateActionButton,
306
+ {
307
+ mode: "desktop",
308
+ label: labels.addPrompt,
309
+ onClick: () => setCreateOpen(true),
310
+ accent: "sky"
311
+ }
312
+ )
313
+ }
314
+ );
315
+ const mobileAction = /* @__PURE__ */ jsxRuntime.jsx(
316
+ chunkTUEYBNWL_js.CreateActionButton,
317
+ {
318
+ mode: "mobile",
319
+ label: labels.addPrompt,
320
+ onClick: () => setCreateOpen(true),
321
+ accent: "sky"
322
+ }
323
+ );
324
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageLoadingState, {}) : prompts.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageEmptyState, { title: labels.empty, message: labels.subtitle, iconName: "folder-open" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: prompts.map((prompt) => {
325
+ const agentName = agentNameById.get(prompt.agentId) ?? prompt.agentId;
326
+ const key = `${prompt.agentId}:${prompt.locale}:${prompt.version}`;
327
+ return /* @__PURE__ */ jsxRuntime.jsx(
328
+ chunkTUEYBNWL_js.EntityCard,
329
+ {
330
+ accentGradient: "from-sky-500 to-blue-700",
331
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-sky-500/10 text-sky-600 dark:bg-sky-500/20 dark:text-sky-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.ChatBubbleLeftEllipsisIcon, { className: "h-6 w-6" }) }),
332
+ title: agentName,
333
+ subtitle: `${prompt.locale} \xB7 v${prompt.version}`,
334
+ status: prompt.isActive ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Badge, { color: "emerald", children: labels.isActive }) : null,
335
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
336
+ !prompt.isActive && /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", size: "sm", outline: true, onClick: () => onActivate(prompt), children: labels.activate }),
337
+ /* @__PURE__ */ jsxRuntime.jsx(
338
+ chunkTUEYBNWL_js.Button,
339
+ {
340
+ type: "button",
341
+ size: "sm",
342
+ color: "rose",
343
+ onClick: () => {
344
+ if (window.confirm(labels.deleteConfirm)) onDelete(prompt);
345
+ },
346
+ children: labels.delete
347
+ }
348
+ )
349
+ ] }),
350
+ children: prompt.prompt && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 line-clamp-3 text-xs text-slate-500 dark:text-slate-400", children: prompt.prompt })
351
+ },
352
+ key
353
+ );
354
+ }) });
355
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
356
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.ManagementPageLayout, { hero, content, mobileAction }),
357
+ /* @__PURE__ */ jsxRuntime.jsx(
358
+ chunkTUEYBNWL_js.GlassModal,
359
+ {
360
+ open: createOpen,
361
+ onClose: () => setCreateOpen(false),
362
+ title: labels.createTitle,
363
+ maxWidth: "2xl",
364
+ showFormFooter: true,
365
+ submitLabel: labels.save,
366
+ onSubmit: (event) => {
367
+ const form = new FormData(event.currentTarget);
368
+ const systemPrompt = String(form.get("systemPrompt") ?? "").trim();
369
+ const userTemplate = String(form.get("userTemplate") ?? "").trim();
370
+ const reason = String(form.get("reason") ?? "").trim();
371
+ onCreate({
372
+ agentId: String(form.get("agentId") ?? "").trim(),
373
+ locale: String(form.get("locale") ?? "en").trim(),
374
+ prompt: String(form.get("prompt") ?? "").trim(),
375
+ systemPrompt: systemPrompt || void 0,
376
+ userTemplate: userTemplate || void 0,
377
+ reason: reason || void 0,
378
+ isActive: String(form.get("isActive") ?? "true") === "true"
379
+ });
380
+ setCreateOpen(false);
381
+ },
382
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
383
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormSelect, { name: "agentId", label: labels.agent, options: agentOptions, required: true }),
384
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormSelect, { name: "locale", label: labels.locale, options: LOCALE_OPTIONS, defaultValue: "en" }),
385
+ /* @__PURE__ */ jsxRuntime.jsx(
386
+ chunkTUEYBNWL_js.FormSelect,
387
+ {
388
+ name: "isActive",
389
+ label: labels.isActive,
390
+ options: [{ value: "true", label: labels.isActive }, { value: "false", label: labels.isActive }],
391
+ defaultValue: "true"
392
+ }
393
+ ),
394
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "reason", label: labels.reason }),
395
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormTextarea, { name: "systemPrompt", label: labels.systemPrompt, rows: 3 }),
396
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormTextarea, { name: "userTemplate", label: labels.userTemplate, rows: 3 }),
397
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormTextarea, { name: "prompt", label: labels.prompt, rows: 6, required: true })
398
+ ] })
399
+ }
400
+ )
401
+ ] });
402
+ }
403
+ var TOOL_TYPES = [
404
+ "http",
405
+ "function",
406
+ "database_query",
407
+ "code_execution",
408
+ "api_call"
409
+ ];
410
+ var TOOL_TYPE_OPTIONS = [
411
+ { value: "http", label: "HTTP", description: "Call an HTTP endpoint with templated URL/body." },
412
+ { value: "function", label: "Function", description: "Invoke a pre-registered server-side implementation." },
413
+ { value: "database_query", label: "Database query", description: "Run a parameterized SELECT against a datasource." },
414
+ { value: "code_execution", label: "Code execution", description: "Run sandboxed code (JS/Python) \u2014 experimental." },
415
+ { value: "api_call", label: "API call", description: "Call a third-party API via stored credentials." }
416
+ ];
417
+ var PARAMETER_TYPE_OPTIONS = [
418
+ { value: "string", label: "string" },
419
+ { value: "number", label: "number" },
420
+ { value: "boolean", label: "boolean" },
421
+ { value: "array", label: "array" },
422
+ { value: "object", label: "object" }
423
+ ];
424
+ function AgentsToolDefinitionsPageView({ labels, tools, loading, onCreate, onUpdate, onDelete }) {
425
+ const [editing, setEditing] = react.useState(null);
426
+ const [createOpen, setCreateOpen] = react.useState(false);
427
+ const hero = /* @__PURE__ */ jsxRuntime.jsx(
428
+ chunkTUEYBNWL_js.HeroSection,
429
+ {
430
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.WrenchScrewdriverIcon, { className: "h-5 w-5" }),
431
+ label: labels.title,
432
+ title: labels.title,
433
+ subtitle: labels.subtitle,
434
+ gradient: "from-amber-500 to-orange-700",
435
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
436
+ chunkTUEYBNWL_js.CreateActionButton,
437
+ {
438
+ mode: "desktop",
439
+ label: labels.addTool,
440
+ onClick: () => setCreateOpen(true),
441
+ accent: "amber"
442
+ }
443
+ )
444
+ }
445
+ );
446
+ const mobileAction = /* @__PURE__ */ jsxRuntime.jsx(
447
+ chunkTUEYBNWL_js.CreateActionButton,
448
+ {
449
+ mode: "mobile",
450
+ label: labels.addTool,
451
+ onClick: () => setCreateOpen(true),
452
+ accent: "amber"
453
+ }
454
+ );
455
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageLoadingState, {}) : tools.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageEmptyState, { title: labels.empty, message: labels.subtitle, iconName: "folder-open" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: tools.map((tool) => /* @__PURE__ */ jsxRuntime.jsx(
456
+ chunkTUEYBNWL_js.EntityCard,
457
+ {
458
+ accentGradient: "from-amber-500 to-orange-700",
459
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-amber-500/10 text-amber-600 dark:bg-amber-500/20 dark:text-amber-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.WrenchScrewdriverIcon, { className: "h-6 w-6" }) }),
460
+ title: tool.name,
461
+ subtitle: toolTypeLabel(tool),
462
+ status: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Badge, { color: tool.enabled ? "emerald" : "zinc", children: tool.enabled ? labels.enabled : labels.disabled }),
463
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
464
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", size: "sm", outline: true, onClick: () => setEditing(tool), children: labels.edit }),
465
+ /* @__PURE__ */ jsxRuntime.jsx(
466
+ chunkTUEYBNWL_js.Button,
467
+ {
468
+ type: "button",
469
+ size: "sm",
470
+ color: "rose",
471
+ onClick: () => {
472
+ if (window.confirm(labels.deleteConfirm)) onDelete(tool);
473
+ },
474
+ children: labels.delete
475
+ }
476
+ )
477
+ ] }),
478
+ children: tool.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: tool.description })
479
+ },
480
+ tool.agentToolId
481
+ )) });
482
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
483
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.ManagementPageLayout, { hero, content, mobileAction }),
484
+ createOpen && /* @__PURE__ */ jsxRuntime.jsx(
485
+ ToolEditor,
486
+ {
487
+ title: labels.createTitle,
488
+ saveLabel: labels.save,
489
+ initial: defaultForm(),
490
+ onClose: () => setCreateOpen(false),
491
+ onSubmit: (input) => {
492
+ onCreate(input);
493
+ setCreateOpen(false);
494
+ }
495
+ }
496
+ ),
497
+ editing && /* @__PURE__ */ jsxRuntime.jsx(
498
+ ToolEditor,
499
+ {
500
+ title: labels.editTitle,
501
+ saveLabel: labels.save,
502
+ initial: toolToForm(editing),
503
+ onClose: () => setEditing(null),
504
+ onSubmit: (input) => {
505
+ onUpdate(editing.agentToolId, input);
506
+ setEditing(null);
507
+ }
508
+ }
509
+ )
510
+ ] });
511
+ }
512
+ function ToolEditor({
513
+ title,
514
+ saveLabel,
515
+ initial,
516
+ onSubmit,
517
+ onClose
518
+ }) {
519
+ const [value, setValue] = react.useState(initial);
520
+ const [error, setError] = react.useState(null);
521
+ const handleSubmit = () => {
522
+ if (!value.name.trim()) {
523
+ setError("Name is required");
524
+ return;
525
+ }
526
+ const names = value.parameters.map((p) => p.name.trim());
527
+ if (names.some((n) => n.length === 0)) {
528
+ setError("Every parameter must have a name");
529
+ return;
530
+ }
531
+ if (new Set(names).size !== names.length) {
532
+ setError("Parameter names must be unique");
533
+ return;
534
+ }
535
+ onSubmit(value);
536
+ };
537
+ const update = (key, next) => {
538
+ setValue((v) => ({ ...v, [key]: next }));
539
+ };
540
+ return /* @__PURE__ */ jsxRuntime.jsx(
541
+ chunkTUEYBNWL_js.GlassModal,
542
+ {
543
+ open: true,
544
+ onClose,
545
+ title,
546
+ maxWidth: "3xl",
547
+ showFormFooter: true,
548
+ submitLabel: saveLabel,
549
+ onSubmit: (event) => {
550
+ event.preventDefault();
551
+ handleSubmit();
552
+ },
553
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
554
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
555
+ /* @__PURE__ */ jsxRuntime.jsx(
556
+ chunkTUEYBNWL_js.FormInput,
557
+ {
558
+ label: "Name",
559
+ required: true,
560
+ value: value.name,
561
+ onValueChange: (name) => update("name", name),
562
+ placeholder: "get_station_prices"
563
+ }
564
+ ),
565
+ /* @__PURE__ */ jsxRuntime.jsx(
566
+ chunkTUEYBNWL_js.FormSelect,
567
+ {
568
+ label: "Tool type",
569
+ value: value.toolType,
570
+ options: TOOL_TYPE_OPTIONS.map((o) => ({ value: o.value, label: o.label })),
571
+ onValueChange: (v) => update("toolType", v),
572
+ hint: TOOL_TYPE_OPTIONS.find((o) => o.value === value.toolType)?.description
573
+ }
574
+ ),
575
+ /* @__PURE__ */ jsxRuntime.jsx(
576
+ chunkTUEYBNWL_js.FormSelect,
577
+ {
578
+ label: "Enabled",
579
+ value: value.enabled ? "true" : "false",
580
+ options: [{ value: "true", label: "Enabled" }, { value: "false", label: "Disabled" }],
581
+ onValueChange: (v) => update("enabled", v === "true")
582
+ }
583
+ ),
584
+ /* @__PURE__ */ jsxRuntime.jsx(
585
+ chunkTUEYBNWL_js.FormInput,
586
+ {
587
+ label: "Icon (optional)",
588
+ value: value.icon ?? "",
589
+ onValueChange: (icon) => update("icon", icon),
590
+ placeholder: "heroicons:wrench-screwdriver"
591
+ }
592
+ )
593
+ ] }),
594
+ /* @__PURE__ */ jsxRuntime.jsx(
595
+ chunkTUEYBNWL_js.FormTextarea,
596
+ {
597
+ label: "Description",
598
+ rows: 2,
599
+ value: value.description ?? "",
600
+ onValueChange: (description) => update("description", description),
601
+ placeholder: "One-sentence summary shown to the agent when it picks tools."
602
+ }
603
+ ),
604
+ /* @__PURE__ */ jsxRuntime.jsx(
605
+ ParametersEditor,
606
+ {
607
+ parameters: value.parameters,
608
+ onChange: (parameters) => update("parameters", parameters)
609
+ }
610
+ ),
611
+ /* @__PURE__ */ jsxRuntime.jsx(
612
+ HandlerConfigEditor,
613
+ {
614
+ toolType: value.toolType,
615
+ config: value.handlerConfig,
616
+ onChange: (handlerConfig) => update("handlerConfig", handlerConfig)
617
+ }
618
+ ),
619
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rounded-lg border border-red-400/40 bg-red-500/10 p-2 text-xs text-red-600 dark:text-red-300", children: error })
620
+ ] })
621
+ }
622
+ );
623
+ }
624
+ function ParametersEditor({
625
+ parameters,
626
+ onChange
627
+ }) {
628
+ const update = (index, patch) => {
629
+ onChange(parameters.map((p, i) => i === index ? { ...p, ...patch } : p));
630
+ };
631
+ const remove = (index) => {
632
+ onChange(parameters.filter((_, i) => i !== index));
633
+ };
634
+ const add = () => {
635
+ onChange([...parameters, { name: "", type: "string", description: "", required: false }]);
636
+ };
637
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
638
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "Parameters" }),
639
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "The agent gets these as a JSON Schema. Any parameter marked required must be supplied for the LLM to call the tool." }),
640
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
641
+ parameters.map((param, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_160px_1fr_110px_auto] items-end gap-2", children: [
642
+ /* @__PURE__ */ jsxRuntime.jsx(
643
+ chunkTUEYBNWL_js.FormInput,
644
+ {
645
+ label: "Name",
646
+ value: param.name,
647
+ onValueChange: (name) => update(index, { name }),
648
+ placeholder: "station_id"
649
+ }
650
+ ),
651
+ /* @__PURE__ */ jsxRuntime.jsx(
652
+ chunkTUEYBNWL_js.FormSelect,
653
+ {
654
+ label: "Type",
655
+ value: param.type,
656
+ options: PARAMETER_TYPE_OPTIONS,
657
+ onValueChange: (t) => update(index, { type: t })
658
+ }
659
+ ),
660
+ /* @__PURE__ */ jsxRuntime.jsx(
661
+ chunkTUEYBNWL_js.FormInput,
662
+ {
663
+ label: "Description",
664
+ value: param.description,
665
+ onValueChange: (description) => update(index, { description })
666
+ }
667
+ ),
668
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 pb-2 text-xs text-gray-700 dark:text-gray-300", children: [
669
+ /* @__PURE__ */ jsxRuntime.jsx(
670
+ "input",
671
+ {
672
+ type: "checkbox",
673
+ checked: param.required,
674
+ onChange: (event) => update(index, { required: event.target.checked }),
675
+ className: "h-4 w-4 rounded border-gray-300"
676
+ }
677
+ ),
678
+ "Required"
679
+ ] }),
680
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", plain: true, onClick: () => remove(index), children: "Remove" })
681
+ ] }, index)),
682
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", outline: true, onClick: add, children: "+ Add parameter" })
683
+ ] })
684
+ ] });
685
+ }
686
+ function HandlerConfigEditor({
687
+ toolType,
688
+ config,
689
+ onChange
690
+ }) {
691
+ const set = (key, value) => onChange({ ...config, [key]: value });
692
+ if (toolType === "http") {
693
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
694
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "HTTP handler" }),
695
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
696
+ /* @__PURE__ */ jsxRuntime.jsx(
697
+ chunkTUEYBNWL_js.FormSelect,
698
+ {
699
+ label: "Method",
700
+ value: stringProp(config, "method", "GET"),
701
+ options: ["GET", "POST", "PUT", "PATCH", "DELETE"].map((m) => ({ value: m, label: m })),
702
+ onValueChange: (m) => set("method", m)
703
+ }
704
+ ),
705
+ /* @__PURE__ */ jsxRuntime.jsx(
706
+ chunkTUEYBNWL_js.FormInput,
707
+ {
708
+ label: "URL template",
709
+ value: stringProp(config, "url"),
710
+ onValueChange: (u) => set("url", u),
711
+ placeholder: "https://api.example.com/stations/{{ station_id }}"
712
+ }
713
+ )
714
+ ] }),
715
+ /* @__PURE__ */ jsxRuntime.jsx(
716
+ chunkTUEYBNWL_js.FormTextarea,
717
+ {
718
+ label: "Headers (JSON)",
719
+ rows: 3,
720
+ value: jsonProp(config, "headers"),
721
+ onValueChange: (raw) => setFromJson(set, "headers", raw),
722
+ placeholder: '{ "Authorization": "Bearer {{ apiKey }}" }'
723
+ }
724
+ ),
725
+ /* @__PURE__ */ jsxRuntime.jsx(
726
+ chunkTUEYBNWL_js.FormTextarea,
727
+ {
728
+ label: "Body template",
729
+ rows: 3,
730
+ value: stringProp(config, "bodyTemplate"),
731
+ onValueChange: (b) => set("bodyTemplate", b),
732
+ placeholder: '{"query": "{{ search }}"}'
733
+ }
734
+ )
735
+ ] });
736
+ }
737
+ if (toolType === "function") {
738
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
739
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "Function handler" }),
740
+ /* @__PURE__ */ jsxRuntime.jsx(
741
+ chunkTUEYBNWL_js.FormInput,
742
+ {
743
+ label: "Implementation key",
744
+ value: stringProp(config, "implementationKey"),
745
+ onValueChange: (k) => set("implementationKey", k),
746
+ placeholder: "fuel.get_station_prices",
747
+ hint: "Must match a pre-registered handler on the server side."
748
+ }
749
+ )
750
+ ] });
751
+ }
752
+ if (toolType === "database_query") {
753
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
754
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "Database query handler" }),
755
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
756
+ /* @__PURE__ */ jsxRuntime.jsx(
757
+ chunkTUEYBNWL_js.FormInput,
758
+ {
759
+ label: "Datasource ID",
760
+ value: stringProp(config, "datasourceId"),
761
+ onValueChange: (v) => set("datasourceId", v),
762
+ placeholder: "UUID from /datasources"
763
+ }
764
+ ),
765
+ /* @__PURE__ */ jsxRuntime.jsx(
766
+ chunkTUEYBNWL_js.FormInput,
767
+ {
768
+ label: "Max rows",
769
+ type: "number",
770
+ value: numberProp(config, "maxRows", 100),
771
+ onValueChange: (v) => set("maxRows", Number(v) || 100)
772
+ }
773
+ )
774
+ ] }),
775
+ /* @__PURE__ */ jsxRuntime.jsx(
776
+ chunkTUEYBNWL_js.FormTextarea,
777
+ {
778
+ label: "Query template",
779
+ rows: 4,
780
+ value: stringProp(config, "queryTemplate"),
781
+ onValueChange: (v) => set("queryTemplate", v),
782
+ placeholder: "SELECT id, current_price FROM current_prices WHERE station_id = {{ station_id }}"
783
+ }
784
+ )
785
+ ] });
786
+ }
787
+ if (toolType === "code_execution") {
788
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
789
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "Code execution handler" }),
790
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 text-xs text-amber-600 dark:text-amber-400", children: "Experimental \u2014 sandbox is not yet enforced. Only enable for trusted tools." }),
791
+ /* @__PURE__ */ jsxRuntime.jsx(
792
+ chunkTUEYBNWL_js.FormSelect,
793
+ {
794
+ label: "Language",
795
+ value: stringProp(config, "language", "javascript"),
796
+ options: [
797
+ { value: "javascript", label: "JavaScript" },
798
+ { value: "python", label: "Python" }
799
+ ],
800
+ onValueChange: (v) => set("language", v)
801
+ }
802
+ ),
803
+ /* @__PURE__ */ jsxRuntime.jsx(
804
+ chunkTUEYBNWL_js.FormTextarea,
805
+ {
806
+ label: "Code",
807
+ rows: 6,
808
+ value: stringProp(config, "code"),
809
+ onValueChange: (v) => set("code", v),
810
+ placeholder: "// return value becomes the tool output\nreturn { price: inputs.x * 1.08 }"
811
+ }
812
+ )
813
+ ] });
814
+ }
815
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "rounded-xl border border-slate-200 bg-slate-50/60 p-3 dark:border-slate-700 dark:bg-slate-900/40", children: [
816
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-2 text-sm font-semibold text-slate-700 dark:text-slate-200", children: "API call handler" }),
817
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
818
+ /* @__PURE__ */ jsxRuntime.jsx(
819
+ chunkTUEYBNWL_js.FormInput,
820
+ {
821
+ label: "URL",
822
+ value: stringProp(config, "url"),
823
+ onValueChange: (v) => set("url", v)
824
+ }
825
+ ),
826
+ /* @__PURE__ */ jsxRuntime.jsx(
827
+ chunkTUEYBNWL_js.FormSelect,
828
+ {
829
+ label: "Auth",
830
+ value: stringProp(config, "authType", "bearer"),
831
+ options: [
832
+ { value: "none", label: "None" },
833
+ { value: "bearer", label: "Bearer token" },
834
+ { value: "api_key", label: "API key header" },
835
+ { value: "basic", label: "Basic auth" }
836
+ ],
837
+ onValueChange: (v) => set("authType", v)
838
+ }
839
+ ),
840
+ /* @__PURE__ */ jsxRuntime.jsx(
841
+ chunkTUEYBNWL_js.FormInput,
842
+ {
843
+ label: "Credential secret id",
844
+ value: stringProp(config, "credentialRef"),
845
+ onValueChange: (v) => set("credentialRef", v),
846
+ placeholder: "UUID from vault",
847
+ hint: "Leave blank if Auth is None."
848
+ }
849
+ )
850
+ ] })
851
+ ] });
852
+ }
853
+ function parametersToJsonSchema(params) {
854
+ const properties = {};
855
+ const required = [];
856
+ for (const param of params) {
857
+ if (!param.name.trim()) continue;
858
+ properties[param.name] = {
859
+ type: param.type,
860
+ ...param.description ? { description: param.description } : {}
861
+ };
862
+ if (param.required) required.push(param.name);
863
+ }
864
+ const schema = { type: "object", properties };
865
+ if (required.length > 0) schema.required = required;
866
+ return schema;
867
+ }
868
+ function jsonSchemaToParameters(schema) {
869
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) return [];
870
+ const root = schema;
871
+ const properties = root.properties;
872
+ if (!properties || typeof properties !== "object" || Array.isArray(properties)) return [];
873
+ const required = Array.isArray(root.required) ? root.required.filter((r) => typeof r === "string") : [];
874
+ const entries = Object.entries(properties);
875
+ return entries.map(([name, raw]) => {
876
+ const def = raw ?? {};
877
+ const rawType = def.type;
878
+ const type = isParameterType(rawType) ? rawType : "string";
879
+ return {
880
+ name,
881
+ type,
882
+ description: typeof def.description === "string" ? def.description : "",
883
+ required: required.includes(name)
884
+ };
885
+ });
886
+ }
887
+ function isParameterType(v) {
888
+ return v === "string" || v === "number" || v === "boolean" || v === "array" || v === "object";
889
+ }
890
+ function defaultForm() {
891
+ return {
892
+ name: "",
893
+ description: "",
894
+ toolType: "http",
895
+ parameters: [],
896
+ handlerConfig: { method: "GET" },
897
+ enabled: true
898
+ };
899
+ }
900
+ function toolToForm(tool) {
901
+ const raw = tool;
902
+ const implRaw = raw.implementationKey ?? raw.implementation_key;
903
+ let handlerConfig = {};
904
+ if (typeof implRaw === "string") {
905
+ try {
906
+ const parsed = JSON.parse(implRaw);
907
+ if (parsed && typeof parsed === "object") {
908
+ const inner = parsed.handlerConfig ?? parsed.handler_config;
909
+ if (inner && typeof inner === "object" && !Array.isArray(inner)) {
910
+ handlerConfig = inner;
911
+ }
912
+ }
913
+ } catch {
914
+ handlerConfig = { implementationKey: implRaw };
915
+ }
916
+ }
917
+ const toolTypeRaw = raw.toolType ?? raw.tool_type ?? raw.category;
918
+ const toolType = TOOL_TYPES.includes(String(toolTypeRaw)) ? toolTypeRaw : "function";
919
+ const parameters = jsonSchemaToParameters(raw.parameters ?? raw.inputSchema ?? raw.input_schema);
920
+ return {
921
+ agentToolId: tool.agentToolId,
922
+ name: tool.name,
923
+ description: tool.description,
924
+ toolType,
925
+ parameters,
926
+ handlerConfig,
927
+ enabled: tool.enabled,
928
+ icon: tool.icon
929
+ };
930
+ }
931
+ function toolTypeLabel(tool) {
932
+ const raw = tool;
933
+ const t = raw.toolType ?? raw.tool_type ?? tool.category;
934
+ const entry = TOOL_TYPE_OPTIONS.find((o) => o.value === t);
935
+ return entry?.label ?? (typeof t === "string" ? t : "tool");
936
+ }
937
+ function stringProp(obj, key, fallback = "") {
938
+ const value = obj[key];
939
+ return typeof value === "string" ? value : fallback;
940
+ }
941
+ function numberProp(obj, key, fallback) {
942
+ const value = obj[key];
943
+ return typeof value === "number" && Number.isFinite(value) ? String(value) : String(fallback);
944
+ }
945
+ function jsonProp(obj, key) {
946
+ const value = obj[key];
947
+ if (!value) return "";
948
+ if (typeof value === "string") return value;
949
+ try {
950
+ return JSON.stringify(value, null, 2);
951
+ } catch {
952
+ return "";
953
+ }
954
+ }
955
+ function setFromJson(set, key, raw) {
956
+ if (!raw.trim()) {
957
+ set(key, void 0);
958
+ return;
959
+ }
960
+ try {
961
+ set(key, JSON.parse(raw));
962
+ } catch {
963
+ set(key, raw);
964
+ }
965
+ }
966
+ function RulesPageView({ labels, rules, loading, onCreate, onUpdate, onDelete }) {
967
+ const [createOpen, setCreateOpen] = react.useState(false);
968
+ const [editing, setEditing] = react.useState(null);
969
+ const hero = /* @__PURE__ */ jsxRuntime.jsx(
970
+ chunkTUEYBNWL_js.HeroSection,
971
+ {
972
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.AdjustmentsHorizontalIcon, { className: "h-5 w-5" }),
973
+ label: labels.title,
974
+ title: labels.title,
975
+ subtitle: labels.subtitle,
976
+ gradient: "from-fuchsia-500 to-purple-700",
977
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
978
+ chunkTUEYBNWL_js.CreateActionButton,
979
+ {
980
+ mode: "desktop",
981
+ label: labels.addRule,
982
+ onClick: () => setCreateOpen(true),
983
+ accent: "fuchsia"
984
+ }
985
+ )
986
+ }
987
+ );
988
+ const mobileAction = /* @__PURE__ */ jsxRuntime.jsx(
989
+ chunkTUEYBNWL_js.CreateActionButton,
990
+ {
991
+ mode: "mobile",
992
+ label: labels.addRule,
993
+ onClick: () => setCreateOpen(true),
994
+ accent: "fuchsia"
995
+ }
996
+ );
997
+ const content = loading ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageLoadingState, {}) : rules.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.PageEmptyState, { title: labels.empty, message: labels.subtitle, iconName: "folder-open" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: rules.map((rule) => /* @__PURE__ */ jsxRuntime.jsx(
998
+ chunkTUEYBNWL_js.EntityCard,
999
+ {
1000
+ accentGradient: "from-fuchsia-500 to-purple-700",
1001
+ icon: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-fuchsia-500/10 text-fuchsia-600 dark:bg-fuchsia-500/20 dark:text-fuchsia-400", children: /* @__PURE__ */ jsxRuntime.jsx(outline.AdjustmentsHorizontalIcon, { className: "h-6 w-6" }) }),
1002
+ title: rule.name,
1003
+ subtitle: `${labels.order}: ${rule.order ?? 0}`,
1004
+ status: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Badge, { color: rule.enabled ? "emerald" : "zinc", children: rule.enabled ? labels.enabled : labels.disabled }),
1005
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1006
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "button", size: "sm", outline: true, onClick: () => setEditing(rule), children: labels.edit }),
1007
+ /* @__PURE__ */ jsxRuntime.jsx(
1008
+ chunkTUEYBNWL_js.Button,
1009
+ {
1010
+ type: "button",
1011
+ size: "sm",
1012
+ color: "rose",
1013
+ onClick: () => {
1014
+ if (window.confirm(labels.deleteConfirm)) onDelete(rule);
1015
+ },
1016
+ children: labels.delete
1017
+ }
1018
+ )
1019
+ ] }),
1020
+ children: rule.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: rule.description })
1021
+ },
1022
+ rule.ruleId
1023
+ )) });
1024
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1025
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.ManagementPageLayout, { hero, content, mobileAction }),
1026
+ createOpen && /* @__PURE__ */ jsxRuntime.jsx(
1027
+ RuleEditor,
1028
+ {
1029
+ title: labels.createTitle,
1030
+ saveLabel: labels.save,
1031
+ initial: chunkK4QJV3GC_js.defaultRuleForm(),
1032
+ onClose: () => setCreateOpen(false),
1033
+ onSubmit: (value) => {
1034
+ onCreate(value);
1035
+ setCreateOpen(false);
1036
+ }
1037
+ }
1038
+ ),
1039
+ editing && /* @__PURE__ */ jsxRuntime.jsx(
1040
+ RuleEditor,
1041
+ {
1042
+ title: labels.editTitle,
1043
+ saveLabel: labels.save,
1044
+ initial: ruleToFormValue(editing),
1045
+ onClose: () => setEditing(null),
1046
+ onSubmit: (value) => {
1047
+ onUpdate(editing.ruleId, value);
1048
+ setEditing(null);
1049
+ }
1050
+ }
1051
+ )
1052
+ ] });
1053
+ }
1054
+ function RuleEditor({
1055
+ title,
1056
+ saveLabel,
1057
+ initial,
1058
+ onSubmit,
1059
+ onClose
1060
+ }) {
1061
+ const [value, setValue] = react.useState(initial);
1062
+ return /* @__PURE__ */ jsxRuntime.jsx(
1063
+ chunkTUEYBNWL_js.GlassModal,
1064
+ {
1065
+ open: true,
1066
+ onClose,
1067
+ title,
1068
+ maxWidth: "3xl",
1069
+ showFormFooter: true,
1070
+ submitLabel: saveLabel,
1071
+ onSubmit: (event) => {
1072
+ event.preventDefault();
1073
+ onSubmit(value);
1074
+ },
1075
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkK4QJV3GC_js.RuleForm, { value, onChange: setValue })
1076
+ }
1077
+ );
1078
+ }
1079
+ function ruleToFormValue(rule) {
1080
+ const base = chunkK4QJV3GC_js.defaultRuleForm();
1081
+ const rawCondition = rule.condition ?? rule.conditions;
1082
+ const rawAction = pickAction(rule);
1083
+ return {
1084
+ ...base,
1085
+ ruleId: rule.ruleId,
1086
+ name: rule.name ?? "",
1087
+ description: rule.description ?? "",
1088
+ enabled: rule.enabled,
1089
+ priority: typeof rule.order === "number" ? rule.order : typeof rule.priority === "number" ? rule.priority : 0,
1090
+ condition: rawCondition && typeof rawCondition === "object" ? rawCondition : base.condition,
1091
+ action: rawAction ?? base.action,
1092
+ status: typeof rule.status === "string" ? rule.status : base.status,
1093
+ validFrom: typeof rule.validFrom === "string" ? rule.validFrom : base.validFrom,
1094
+ validUntil: typeof rule.validUntil === "string" ? rule.validUntil : base.validUntil,
1095
+ tags: Array.isArray(rule.tags) ? rule.tags.filter((tag) => typeof tag === "string") : base.tags
1096
+ };
1097
+ }
1098
+ function pickAction(rule) {
1099
+ const singular = rule.action;
1100
+ if (singular && typeof singular === "object" && "type" in singular) {
1101
+ return singular;
1102
+ }
1103
+ if (Array.isArray(rule.actions) && rule.actions.length > 0) {
1104
+ const first = rule.actions[0];
1105
+ if (first && typeof first === "object" && "type" in first) {
1106
+ return first;
1107
+ }
1108
+ }
1109
+ return void 0;
1110
+ }
1111
+ var DIALECT_CATEGORIES = [
1112
+ {
1113
+ id: "relational",
1114
+ labelKey: "categoryRelational",
1115
+ icon: outline.CircleStackIcon,
1116
+ gradient: "from-blue-500 to-indigo-600",
1117
+ dialects: [
1118
+ { value: "postgres", label: "PostgreSQL", defaultPort: 5432, formType: "standard" },
1119
+ { value: "mysql", label: "MySQL", defaultPort: 3306, formType: "standard" },
1120
+ { value: "mariadb", label: "MariaDB", defaultPort: 3306, formType: "standard" },
1121
+ { value: "mssql", label: "SQL Server", defaultPort: 1433, formType: "standard" },
1122
+ { value: "oracle", label: "Oracle", defaultPort: 1521, formType: "standard" },
1123
+ { value: "db2", label: "IBM Db2", defaultPort: 5e4, formType: "standard" },
1124
+ { value: "cockroachdb", label: "CockroachDB", defaultPort: 26257, formType: "standard" },
1125
+ { value: "timescaledb", label: "TimescaleDB", defaultPort: 5432, formType: "standard" },
1126
+ { value: "sqlite", label: "SQLite", formType: "connection-string" },
1127
+ { value: "duckdb", label: "DuckDB", formType: "connection-string" }
1128
+ ]
1129
+ },
1130
+ {
1131
+ id: "nosql",
1132
+ labelKey: "categoryNoSql",
1133
+ icon: outline.ServerStackIcon,
1134
+ gradient: "from-emerald-500 to-teal-600",
1135
+ dialects: [
1136
+ { value: "mongodb", label: "MongoDB", defaultPort: 27017, formType: "connection-string" },
1137
+ { value: "cassandra", label: "Cassandra", defaultPort: 9042, formType: "standard" },
1138
+ { value: "scylladb", label: "ScyllaDB", defaultPort: 9042, formType: "standard" },
1139
+ { value: "dynamodb", label: "DynamoDB", formType: "cloud-key" },
1140
+ { value: "cosmosdb", label: "CosmosDB", formType: "connection-string" },
1141
+ { value: "arangodb", label: "ArangoDB", defaultPort: 8529, formType: "standard" }
1142
+ ]
1143
+ },
1144
+ {
1145
+ id: "warehouse",
1146
+ labelKey: "categoryWarehouse",
1147
+ icon: outline.CloudIcon,
1148
+ gradient: "from-purple-500 to-violet-600",
1149
+ dialects: [
1150
+ { value: "bigquery", label: "BigQuery", formType: "cloud-bigquery" },
1151
+ { value: "snowflake", label: "Snowflake", formType: "cloud-snowflake" },
1152
+ { value: "clickhouse", label: "ClickHouse", defaultPort: 8123, formType: "standard" }
1153
+ ]
1154
+ },
1155
+ {
1156
+ id: "timeseries",
1157
+ labelKey: "categoryTimeSeries",
1158
+ icon: outline.ClockIcon,
1159
+ gradient: "from-sky-500 to-cyan-600",
1160
+ dialects: [
1161
+ { value: "influxdb", label: "InfluxDB", formType: "cloud-key" },
1162
+ { value: "timestream", label: "Timestream", formType: "cloud-key" }
1163
+ ]
1164
+ },
1165
+ {
1166
+ id: "graph",
1167
+ labelKey: "categoryGraph",
1168
+ icon: outline.ShareIcon,
1169
+ gradient: "from-pink-500 to-rose-600",
1170
+ dialects: [
1171
+ { value: "neo4j", label: "Neo4j", defaultPort: 7687, formType: "standard" },
1172
+ { value: "neptune", label: "Neptune", formType: "connection-string" }
1173
+ ]
1174
+ },
1175
+ {
1176
+ id: "keyvalue",
1177
+ labelKey: "categoryKeyValue",
1178
+ icon: outline.KeyIcon,
1179
+ gradient: "from-red-500 to-orange-600",
1180
+ dialects: [
1181
+ { value: "redis", label: "Redis", defaultPort: 6379, formType: "standard" }
1182
+ ]
1183
+ },
1184
+ {
1185
+ id: "search",
1186
+ labelKey: "categorySearch",
1187
+ icon: outline.MagnifyingGlassIcon,
1188
+ gradient: "from-amber-500 to-yellow-600",
1189
+ dialects: [
1190
+ { value: "elasticsearch", label: "Elasticsearch", defaultPort: 9200, formType: "standard" },
1191
+ { value: "opensearch", label: "OpenSearch", defaultPort: 9200, formType: "standard" },
1192
+ { value: "pinecone", label: "Pinecone", formType: "vector-key" },
1193
+ { value: "qdrant", label: "Qdrant", defaultPort: 6333, formType: "standard" },
1194
+ { value: "weaviate", label: "Weaviate", defaultPort: 8080, formType: "standard" },
1195
+ { value: "milvus", label: "Milvus", defaultPort: 19530, formType: "standard" },
1196
+ { value: "chromadb", label: "ChromaDB", defaultPort: 8e3, formType: "standard" }
1197
+ ]
1198
+ }
1199
+ ];
1200
+ function findDialect(value) {
1201
+ for (const category of DIALECT_CATEGORIES) {
1202
+ const found = category.dialects.find((d) => d.value === value);
1203
+ if (found) return found;
1204
+ }
1205
+ return void 0;
1206
+ }
1207
+ function findCategory(dialectValue) {
1208
+ return DIALECT_CATEGORIES.find((c) => c.dialects.some((d) => d.value === dialectValue));
1209
+ }
1210
+ function DialectPicker({
1211
+ labels,
1212
+ onSelect
1213
+ }) {
1214
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
1215
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: labels.stepSelectType }),
1216
+ DIALECT_CATEGORIES.map((category) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1217
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-2 flex items-center gap-2", children: [
1218
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-7 w-7 items-center justify-center rounded-lg bg-gradient-to-br ${category.gradient}`, children: /* @__PURE__ */ jsxRuntime.jsx(category.icon, { className: "h-4 w-4 text-white" }) }),
1219
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-700 dark:text-gray-200", children: labels[category.labelKey] ?? category.id })
1220
+ ] }),
1221
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-3", children: category.dialects.map((dialect) => /* @__PURE__ */ jsxRuntime.jsxs(
1222
+ "button",
1223
+ {
1224
+ type: "button",
1225
+ onClick: () => onSelect(dialect.value),
1226
+ className: "group flex items-center gap-2 rounded-xl border border-gray-200/60 bg-white/60 px-3 py-2.5 text-left text-sm font-medium text-gray-700 transition-all hover:border-amber-400/60 hover:bg-amber-50/50 hover:text-amber-700 active:scale-[0.97] dark:border-white/10 dark:bg-white/5 dark:text-gray-300 dark:hover:border-amber-400/40 dark:hover:bg-amber-500/10 dark:hover:text-amber-300",
1227
+ children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-4 w-4 shrink-0 text-gray-400 transition-colors group-hover:text-amber-500 dark:text-gray-500" }),
1229
+ dialect.label
1230
+ ]
1231
+ },
1232
+ dialect.value
1233
+ )) })
1234
+ ] }, category.id))
1235
+ ] });
1236
+ }
1237
+ function ConnectionForm({
1238
+ dialect,
1239
+ labels,
1240
+ onBack,
1241
+ onSubmit
1242
+ }) {
1243
+ const [testStatus, setTestStatus] = react.useState("idle");
1244
+ const category = findCategory(dialect.value);
1245
+ function handleSubmit(event) {
1246
+ event.preventDefault();
1247
+ const formData = new FormData(event.currentTarget);
1248
+ const data = {
1249
+ name: String(formData.get("name") ?? "").trim(),
1250
+ dialect: dialect.value
1251
+ };
1252
+ for (const key of ["host", "database", "username", "password", "schema", "connectionString", "projectId", "dataset", "keyFile", "account", "warehouse", "region", "bucket", "token", "apiKey", "environment", "index", "url"]) {
1253
+ const val = String(formData.get(key) ?? "").trim();
1254
+ if (val) data[key] = val;
1255
+ }
1256
+ const port = String(formData.get("port") ?? "").trim();
1257
+ if (port) data.port = Number(port);
1258
+ data.ssl = formData.get("ssl") === "on";
1259
+ data.readOnly = formData.get("readOnly") === "on";
1260
+ const maxPoolSize = String(formData.get("maxPoolSize") ?? "").trim();
1261
+ if (maxPoolSize) {
1262
+ const parsed = Number(maxPoolSize);
1263
+ if (Number.isFinite(parsed) && parsed > 0) data.maxPoolSize = parsed;
1264
+ }
1265
+ const timeoutMs = String(formData.get("timeoutMs") ?? "").trim();
1266
+ if (timeoutMs) {
1267
+ const parsed = Number(timeoutMs);
1268
+ if (Number.isFinite(parsed) && parsed > 0) data.timeoutMs = parsed;
1269
+ }
1270
+ const allowedTables = splitList(String(formData.get("allowedTables") ?? ""));
1271
+ if (allowedTables.length > 0) data.allowedTables = allowedTables;
1272
+ const blockedColumns = splitList(String(formData.get("blockedColumns") ?? ""));
1273
+ if (blockedColumns.length > 0) data.blockedColumns = blockedColumns;
1274
+ onSubmit(data);
1275
+ }
1276
+ function handleTestConnection() {
1277
+ setTestStatus("testing");
1278
+ setTimeout(() => {
1279
+ setTestStatus("success");
1280
+ setTimeout(() => setTestStatus("idle"), 3e3);
1281
+ }, 1500);
1282
+ }
1283
+ function renderFields() {
1284
+ switch (dialect.formType) {
1285
+ case "standard":
1286
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1287
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "host", label: labels.fieldHost, placeholder: labels.fieldHostPlaceholder, required: true }),
1288
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "port", label: labels.fieldPort, type: "number", defaultValue: dialect.defaultPort }),
1289
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "database", label: labels.fieldDatabase, placeholder: labels.fieldDatabasePlaceholder, required: true }),
1290
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "username", label: labels.fieldUsername, placeholder: labels.fieldUsernamePlaceholder }),
1291
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "password", label: labels.fieldPassword, type: "password", placeholder: labels.fieldPasswordPlaceholder }),
1292
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "schema", label: labels.fieldSchema, placeholder: labels.fieldSchemaPlaceholder })
1293
+ ] });
1294
+ case "connection-string":
1295
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "connectionString", label: labels.fieldConnectionString, placeholder: labels.fieldConnectionStringPlaceholder, required: true }) });
1296
+ case "cloud-bigquery":
1297
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1298
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "projectId", label: labels.fieldProjectId, placeholder: labels.fieldProjectIdPlaceholder, required: true }),
1299
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "dataset", label: labels.fieldDataset, placeholder: labels.fieldDatasetPlaceholder, required: true }),
1300
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-full", children: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "keyFile", label: labels.fieldKeyFile, placeholder: labels.fieldKeyFilePlaceholder }) })
1301
+ ] });
1302
+ case "cloud-snowflake":
1303
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1304
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "account", label: labels.fieldAccount, placeholder: labels.fieldAccountPlaceholder, required: true }),
1305
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "warehouse", label: labels.fieldWarehouse, placeholder: labels.fieldWarehousePlaceholder, required: true }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "database", label: labels.fieldDatabase, placeholder: labels.fieldDatabasePlaceholder, required: true }),
1307
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "username", label: labels.fieldUsername, placeholder: labels.fieldUsernamePlaceholder, required: true }),
1308
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "password", label: labels.fieldPassword, type: "password", placeholder: labels.fieldPasswordPlaceholder }),
1309
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "schema", label: labels.fieldSchema, placeholder: labels.fieldSchemaPlaceholder })
1310
+ ] });
1311
+ case "cloud-key":
1312
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1313
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "region", label: labels.fieldRegion, placeholder: labels.fieldRegionPlaceholder, required: true }),
1314
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "token", label: labels.fieldToken, type: "password", placeholder: labels.fieldTokenPlaceholder, required: true }),
1315
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "bucket", label: labels.fieldBucket, placeholder: labels.fieldBucketPlaceholder })
1316
+ ] });
1317
+ case "vector-key":
1318
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1319
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "apiKey", label: labels.fieldApiKey, type: "password", placeholder: labels.fieldApiKeyPlaceholder, required: true }),
1320
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "environment", label: labels.fieldEnvironment, placeholder: labels.fieldEnvironmentPlaceholder, required: true }),
1321
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "index", label: labels.fieldIndex, placeholder: labels.fieldIndexPlaceholder })
1322
+ ] });
1323
+ }
1324
+ }
1325
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1327
+ /* @__PURE__ */ jsxRuntime.jsx(
1328
+ "button",
1329
+ {
1330
+ type: "button",
1331
+ onClick: onBack,
1332
+ className: "flex h-8 w-8 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-white/10 dark:hover:text-gray-300",
1333
+ children: /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowLeftIcon, { className: "h-4 w-4" })
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1337
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-8 w-8 items-center justify-center rounded-lg bg-gradient-to-br ${category?.gradient ?? "from-gray-400 to-gray-500"}`, children: category ? /* @__PURE__ */ jsxRuntime.jsx(category.icon, { className: "h-4 w-4 text-white" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-4 w-4 text-white" }) }),
1338
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1339
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: dialect.label }),
1340
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-xs text-gray-400", children: labels[category?.labelKey ?? ""] ?? "" })
1341
+ ] })
1342
+ ] })
1343
+ ] }),
1344
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormInput, { name: "name", label: labels.fieldName, placeholder: labels.fieldNamePlaceholder, required: true }),
1345
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.FormGrid, { children: renderFields() }),
1346
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-6 pt-2", children: [
1347
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
1348
+ /* @__PURE__ */ jsxRuntime.jsx(
1349
+ "input",
1350
+ {
1351
+ type: "checkbox",
1352
+ name: "ssl",
1353
+ defaultChecked: true,
1354
+ className: "h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500 dark:border-gray-600 dark:bg-gray-800"
1355
+ }
1356
+ ),
1357
+ labels.fieldSsl
1358
+ ] }),
1359
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
1360
+ /* @__PURE__ */ jsxRuntime.jsx(
1361
+ "input",
1362
+ {
1363
+ type: "checkbox",
1364
+ name: "readOnly",
1365
+ defaultChecked: true,
1366
+ className: "h-4 w-4 rounded border-gray-300 text-amber-600 focus:ring-amber-500 dark:border-gray-600 dark:bg-gray-800"
1367
+ }
1368
+ ),
1369
+ labels.fieldReadOnly
1370
+ ] })
1371
+ ] }),
1372
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldReadOnlyHelp }),
1373
+ /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "rounded-xl border border-gray-200/60 bg-white/40 p-3 dark:border-white/10 dark:bg-white/5", children: [
1374
+ /* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.advancedToggle ?? "Governance & performance" }),
1375
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-3", children: [
1376
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkTUEYBNWL_js.FormGrid, { children: [
1377
+ /* @__PURE__ */ jsxRuntime.jsx(
1378
+ chunkTUEYBNWL_js.FormInput,
1379
+ {
1380
+ name: "maxPoolSize",
1381
+ label: labels.fieldMaxPoolSize ?? "Max pool size",
1382
+ type: "number",
1383
+ min: 1,
1384
+ max: 100,
1385
+ placeholder: "5"
1386
+ }
1387
+ ),
1388
+ /* @__PURE__ */ jsxRuntime.jsx(
1389
+ chunkTUEYBNWL_js.FormInput,
1390
+ {
1391
+ name: "timeoutMs",
1392
+ label: labels.fieldTimeoutMs ?? "Timeout (ms)",
1393
+ type: "number",
1394
+ min: 100,
1395
+ placeholder: "5000"
1396
+ }
1397
+ )
1398
+ ] }),
1399
+ /* @__PURE__ */ jsxRuntime.jsx(
1400
+ chunkTUEYBNWL_js.FormInput,
1401
+ {
1402
+ name: "allowedTables",
1403
+ label: labels.fieldAllowedTables ?? "Allowed tables (comma-separated)",
1404
+ placeholder: "stations, current_prices, competitor_prices"
1405
+ }
1406
+ ),
1407
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldAllowedTablesHelp ?? "Leave blank to allow every table the credential can see. Otherwise only the listed tables are queryable from workflows." }),
1408
+ /* @__PURE__ */ jsxRuntime.jsx(
1409
+ chunkTUEYBNWL_js.FormInput,
1410
+ {
1411
+ name: "blockedColumns",
1412
+ label: labels.fieldBlockedColumns ?? "Blocked columns (comma-separated)",
1413
+ placeholder: "customers.ssn, employees.salary"
1414
+ }
1415
+ ),
1416
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: labels.fieldBlockedColumnsHelp ?? "Columns the driver must never surface, even if referenced by a workflow. Use table.column notation for specificity." })
1417
+ ] })
1418
+ ] }),
1419
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 border-t border-gray-200/60 pt-5 dark:border-white/10", children: [
1420
+ /* @__PURE__ */ jsxRuntime.jsx(
1421
+ chunkTUEYBNWL_js.Button,
1422
+ {
1423
+ type: "button",
1424
+ size: "sm",
1425
+ color: "zinc",
1426
+ onClick: handleTestConnection,
1427
+ disabled: testStatus === "testing",
1428
+ children: testStatus === "testing" ? labels.testing : labels.testConnection
1429
+ }
1430
+ ),
1431
+ testStatus === "success" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-400", children: [
1432
+ /* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "h-4 w-4" }),
1433
+ labels.connectionSuccess
1434
+ ] }),
1435
+ testStatus === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-xs font-medium text-red-600 dark:text-red-400", children: [
1436
+ /* @__PURE__ */ jsxRuntime.jsx(outline.XCircleIcon, { className: "h-4 w-4" }),
1437
+ labels.connectionFailed
1438
+ ] }),
1439
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Button, { type: "submit", size: "sm", color: "amber", children: labels.save })
1441
+ ] })
1442
+ ] });
1443
+ }
1444
+ function DatasourceFormModal({ open, onClose, labels, onSave }) {
1445
+ const [selectedDialect, setSelectedDialect] = react.useState(null);
1446
+ const dialect = selectedDialect ? findDialect(selectedDialect) : null;
1447
+ function handleClose() {
1448
+ setSelectedDialect(null);
1449
+ onClose();
1450
+ }
1451
+ function handleSave(data) {
1452
+ onSave(data);
1453
+ handleClose();
1454
+ }
1455
+ return /* @__PURE__ */ jsxRuntime.jsx(
1456
+ chunkTUEYBNWL_js.GlassModal,
1457
+ {
1458
+ open,
1459
+ onClose: handleClose,
1460
+ title: labels.createTitle,
1461
+ subtitle: dialect ? labels.stepConfigure : labels.stepSelectType,
1462
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-5 w-5" }),
1463
+ gradient: "from-amber-500 to-orange-600",
1464
+ maxWidth: "3xl",
1465
+ children: dialect ? /* @__PURE__ */ jsxRuntime.jsx(
1466
+ ConnectionForm,
1467
+ {
1468
+ dialect,
1469
+ labels,
1470
+ onBack: () => setSelectedDialect(null),
1471
+ onSubmit: handleSave
1472
+ }
1473
+ ) : /* @__PURE__ */ jsxRuntime.jsx(DialectPicker, { labels, onSelect: setSelectedDialect })
1474
+ }
1475
+ );
1476
+ }
1477
+ function DatasourceModal({ open, onClose, labels, onSave }) {
1478
+ const [selectedDialect, setSelectedDialect] = react.useState(null);
1479
+ const dialect = selectedDialect ? findDialect(selectedDialect) : null;
1480
+ function handleClose() {
1481
+ setSelectedDialect(null);
1482
+ onClose();
1483
+ }
1484
+ function handleSave(data) {
1485
+ onSave(data);
1486
+ handleClose();
1487
+ }
1488
+ return /* @__PURE__ */ jsxRuntime.jsx(
1489
+ chunkTUEYBNWL_js.GlassModal,
1490
+ {
1491
+ open,
1492
+ onClose: handleClose,
1493
+ title: labels.createTitle,
1494
+ subtitle: dialect ? labels.stepConfigure : labels.stepSelectType,
1495
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-5 w-5" }),
1496
+ gradient: "from-amber-500 to-orange-600",
1497
+ maxWidth: "3xl",
1498
+ children: dialect ? /* @__PURE__ */ jsxRuntime.jsx(
1499
+ ConnectionForm,
1500
+ {
1501
+ dialect,
1502
+ labels,
1503
+ onBack: () => setSelectedDialect(null),
1504
+ onSubmit: handleSave
1505
+ }
1506
+ ) : /* @__PURE__ */ jsxRuntime.jsx(DialectPicker, { labels, onSelect: setSelectedDialect })
1507
+ }
1508
+ );
1509
+ }
1510
+ function splitList(raw) {
1511
+ return raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
1512
+ }
1513
+ var SAMPLE_DATASOURCES = [
1514
+ {
1515
+ id: "ds_bigquery_analytics",
1516
+ organizationId: "org_demo",
1517
+ name: "BigQuery Analytics",
1518
+ dialect: "bigquery",
1519
+ credentials: null,
1520
+ readOnly: true,
1521
+ maxPoolSize: null,
1522
+ timeoutMs: 3e4,
1523
+ allowedTables: null,
1524
+ blockedColumns: null,
1525
+ enabled: true,
1526
+ createdAt: "2026-03-20T10:00:00Z",
1527
+ updatedAt: "2026-03-20T10:00:00Z",
1528
+ slug: "bigquery-analytics"
1529
+ },
1530
+ {
1531
+ id: "ds_postgres_prod",
1532
+ organizationId: "org_demo",
1533
+ name: "Production PostgreSQL",
1534
+ dialect: "postgres",
1535
+ credentials: null,
1536
+ readOnly: true,
1537
+ maxPoolSize: 10,
1538
+ timeoutMs: 15e3,
1539
+ allowedTables: null,
1540
+ blockedColumns: null,
1541
+ enabled: true,
1542
+ createdAt: "2026-03-18T08:30:00Z",
1543
+ updatedAt: "2026-03-22T14:00:00Z",
1544
+ slug: "production-postgresql"
1545
+ },
1546
+ {
1547
+ id: "ds_snowflake_dw",
1548
+ organizationId: "org_demo",
1549
+ name: "Snowflake Data Warehouse",
1550
+ dialect: "snowflake",
1551
+ credentials: null,
1552
+ readOnly: true,
1553
+ maxPoolSize: null,
1554
+ timeoutMs: 3e4,
1555
+ allowedTables: null,
1556
+ blockedColumns: null,
1557
+ enabled: true,
1558
+ createdAt: "2026-03-15T09:00:00Z",
1559
+ updatedAt: "2026-03-21T11:00:00Z",
1560
+ slug: "snowflake-data-warehouse"
1561
+ },
1562
+ {
1563
+ id: "ds_mongodb_events",
1564
+ organizationId: "org_demo",
1565
+ name: "Event Store (MongoDB)",
1566
+ dialect: "mongodb",
1567
+ credentials: null,
1568
+ readOnly: true,
1569
+ maxPoolSize: 5,
1570
+ timeoutMs: 1e4,
1571
+ allowedTables: null,
1572
+ blockedColumns: null,
1573
+ enabled: false,
1574
+ createdAt: "2026-03-10T12:00:00Z",
1575
+ updatedAt: "2026-03-19T16:00:00Z",
1576
+ slug: "event-store-mongodb"
1577
+ },
1578
+ {
1579
+ id: "ds_redis_cache",
1580
+ organizationId: "org_demo",
1581
+ name: "Redis Cache Layer",
1582
+ dialect: "redis",
1583
+ credentials: null,
1584
+ readOnly: false,
1585
+ maxPoolSize: 20,
1586
+ timeoutMs: 5e3,
1587
+ allowedTables: null,
1588
+ blockedColumns: null,
1589
+ enabled: true,
1590
+ createdAt: "2026-03-12T07:00:00Z",
1591
+ updatedAt: "2026-03-23T09:00:00Z",
1592
+ slug: "redis-cache-layer"
1593
+ },
1594
+ {
1595
+ id: "ds_pinecone_vectors",
1596
+ organizationId: "org_demo",
1597
+ name: "Pinecone Embeddings",
1598
+ dialect: "pinecone",
1599
+ credentials: null,
1600
+ readOnly: true,
1601
+ maxPoolSize: null,
1602
+ timeoutMs: 2e4,
1603
+ allowedTables: null,
1604
+ blockedColumns: null,
1605
+ enabled: true,
1606
+ createdAt: "2026-03-22T15:00:00Z",
1607
+ updatedAt: "2026-03-25T10:00:00Z",
1608
+ slug: "pinecone-embeddings"
1609
+ }
1610
+ ];
1611
+ function getDialectLabel(dialect) {
1612
+ if (!dialect) return "Unknown";
1613
+ for (const category of DIALECT_CATEGORIES) {
1614
+ const found = category.dialects.find((d) => d.value === dialect);
1615
+ if (found) return found.label;
1616
+ }
1617
+ return dialect;
1618
+ }
1619
+ function getDialectGradient(dialect) {
1620
+ if (!dialect) return "from-gray-400 to-gray-500";
1621
+ const category = findCategory(dialect);
1622
+ return category?.gradient ?? "from-gray-400 to-gray-500";
1623
+ }
1624
+ function getDialectIcon(dialect) {
1625
+ if (!dialect) return outline.CircleStackIcon;
1626
+ const category = findCategory(dialect);
1627
+ return category?.icon ?? outline.CircleStackIcon;
1628
+ }
1629
+ var DIALECT_LOGO = {
1630
+ bigquery: "/logos/datasources/bigquery.svg",
1631
+ postgres: "/logos/datasources/postgres.svg",
1632
+ postgresql: "/logos/datasources/postgres.svg",
1633
+ mysql: "/logos/datasources/mysql.svg",
1634
+ mariadb: "/logos/datasources/mariadb.svg",
1635
+ snowflake: "/logos/datasources/snowflake.svg",
1636
+ mongodb: "/logos/datasources/mongodb.svg",
1637
+ redis: "/logos/datasources/redis.svg",
1638
+ clickhouse: "/logos/datasources/clickhouse.svg",
1639
+ elasticsearch: "/logos/datasources/elasticsearch.svg",
1640
+ duckdb: "/logos/datasources/duckdb.svg",
1641
+ sqlite: "/logos/datasources/sqlite.svg",
1642
+ oracle: "/logos/datasources/oracle.svg",
1643
+ mssql: "/logos/datasources/mssql.svg",
1644
+ sqlserver: "/logos/datasources/mssql.svg",
1645
+ cassandra: "/logos/datasources/cassandra.svg",
1646
+ dynamodb: "/logos/datasources/dynamodb.svg",
1647
+ cockroach: "/logos/datasources/cockroachdb.svg",
1648
+ cockroachdb: "/logos/datasources/cockroachdb.svg",
1649
+ supabase: "/logos/datasources/supabase.svg",
1650
+ firebase: "/logos/datasources/firebase.svg",
1651
+ neo4j: "/logos/datasources/neo4j.svg"
1652
+ };
1653
+ function getDialectLogoSrc(dialect) {
1654
+ if (!dialect) return null;
1655
+ return DIALECT_LOGO[dialect.toLowerCase()] ?? null;
1656
+ }
1657
+ function DatasourcesPageView({
1658
+ labels,
1659
+ datasources: externalDatasources,
1660
+ useSampleData = false,
1661
+ onCreate
1662
+ }) {
1663
+ const [modalOpen, setModalOpen] = react.useState(false);
1664
+ const [localDatasources, setLocalDatasources] = react.useState(
1665
+ useSampleData ? SAMPLE_DATASOURCES : []
1666
+ );
1667
+ const datasources = externalDatasources ?? localDatasources;
1668
+ const isEmpty = datasources.length === 0;
1669
+ function handleCreate(data) {
1670
+ if (onCreate) {
1671
+ onCreate(data);
1672
+ return;
1673
+ }
1674
+ const newDs = {
1675
+ id: `ds_${Date.now()}`,
1676
+ organizationId: "org_demo",
1677
+ name: data.name,
1678
+ dialect: data.dialect,
1679
+ credentials: null,
1680
+ readOnly: data.readOnly ?? true,
1681
+ maxPoolSize: null,
1682
+ timeoutMs: 3e4,
1683
+ allowedTables: null,
1684
+ blockedColumns: null,
1685
+ enabled: true,
1686
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1687
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1688
+ slug: data.name.toLowerCase().replace(/\s+/g, "-")
1689
+ };
1690
+ setLocalDatasources((previous) => [...previous, newDs]);
1691
+ }
1692
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1693
+ /* @__PURE__ */ jsxRuntime.jsx(
1694
+ chunkTUEYBNWL_js.HeroSection,
1695
+ {
1696
+ icon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-5 w-5" }),
1697
+ label: labels.title,
1698
+ title: labels.title,
1699
+ subtitle: labels.subtitle,
1700
+ gradient: "from-amber-500 to-orange-600",
1701
+ toolbar: /* @__PURE__ */ jsxRuntime.jsx(
1702
+ chunkTUEYBNWL_js.CreateActionButton,
1703
+ {
1704
+ mode: "desktop",
1705
+ label: labels.addDatasource,
1706
+ onClick: () => setModalOpen(true),
1707
+ accent: "amber"
1708
+ }
1709
+ )
1710
+ }
1711
+ ),
1712
+ /* @__PURE__ */ jsxRuntime.jsx(
1713
+ chunkTUEYBNWL_js.CreateActionButton,
1714
+ {
1715
+ mode: "mobile",
1716
+ label: labels.addDatasource,
1717
+ onClick: () => setModalOpen(true),
1718
+ accent: "amber"
1719
+ }
1720
+ ),
1721
+ isEmpty ? /* @__PURE__ */ jsxRuntime.jsx(
1722
+ chunkTUEYBNWL_js.PageEmptyState,
1723
+ {
1724
+ title: labels.emptyTitle,
1725
+ message: labels.emptyDescription,
1726
+ iconName: "link",
1727
+ customIcon: /* @__PURE__ */ jsxRuntime.jsx(outline.CircleStackIcon, { className: "h-10 w-10 text-amber-500 dark:text-amber-400" })
1728
+ }
1729
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: datasources.map((ds) => {
1730
+ const Icon = getDialectIcon(ds.dialect);
1731
+ const gradient = getDialectGradient(ds.dialect);
1732
+ const dialectLabel = getDialectLabel(ds.dialect);
1733
+ const logoSrc = getDialectLogoSrc(ds.dialect);
1734
+ const iconElement = logoSrc ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-white shadow-sm ring-1 ring-black/5 dark:bg-white/10 dark:ring-white/10", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoSrc, alt: dialectLabel, className: "h-7 w-7 object-contain" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-11 w-11 items-center justify-center rounded-lg bg-gradient-to-br ${gradient} shadow-lg`, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-6 w-6 text-white" }) });
1735
+ return /* @__PURE__ */ jsxRuntime.jsx(
1736
+ chunkTUEYBNWL_js.EntityCard,
1737
+ {
1738
+ accentGradient: gradient,
1739
+ icon: iconElement,
1740
+ title: ds.name ?? ds.id,
1741
+ subtitle: dialectLabel,
1742
+ status: /* @__PURE__ */ jsxRuntime.jsx(chunkTUEYBNWL_js.Badge, { color: ds.enabled ? "emerald" : "zinc", children: ds.enabled ? labels.enabled : labels.disabled }),
1743
+ footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-400 dark:text-gray-500", children: [
1744
+ ds.readOnly && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-blue-100 px-2 py-0.5 text-[10px] font-semibold text-blue-700 dark:bg-blue-900/30 dark:text-blue-300", children: "Read-only" }),
1745
+ ds.timeoutMs && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1746
+ ds.timeoutMs / 1e3,
1747
+ "s timeout"
1748
+ ] })
1749
+ ] }),
1750
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: [
1751
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1752
+ labels.dialect,
1753
+ ": ",
1754
+ dialectLabel
1755
+ ] }),
1756
+ ds.slug && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "truncate text-gray-400", children: [
1757
+ "/",
1758
+ ds.slug
1759
+ ] })
1760
+ ] })
1761
+ },
1762
+ ds.id
1763
+ );
1764
+ }) }),
1765
+ /* @__PURE__ */ jsxRuntime.jsx(
1766
+ DatasourceModal,
1767
+ {
1768
+ open: modalOpen,
1769
+ onClose: () => setModalOpen(false),
1770
+ labels,
1771
+ onSave: handleCreate
1772
+ }
1773
+ )
1774
+ ] });
1775
+ }
1776
+
1777
+ exports.AgentsConfigPageView = AgentsConfigPageView;
1778
+ exports.AgentsModelsPageView = AgentsModelsPageView;
1779
+ exports.AgentsPromptsPageView = AgentsPromptsPageView;
1780
+ exports.AgentsToolDefinitionsPageView = AgentsToolDefinitionsPageView;
1781
+ exports.DIALECT_CATEGORIES = DIALECT_CATEGORIES;
1782
+ exports.DatasourceFormModal = DatasourceFormModal;
1783
+ exports.DatasourceModal = DatasourceModal;
1784
+ exports.DatasourcesPageView = DatasourcesPageView;
1785
+ exports.RulesPageView = RulesPageView;
1786
+ exports.TOOL_TYPES = TOOL_TYPES;
1787
+ exports.UsersPageView = UsersPageView;
1788
+ exports.findCategory = findCategory;
1789
+ exports.findDialect = findDialect;
1790
+ exports.jsonSchemaToParameters = jsonSchemaToParameters;
1791
+ exports.parametersToJsonSchema = parametersToJsonSchema;
1792
+ //# sourceMappingURL=index.js.map
1793
+ //# sourceMappingURL=index.js.map