@epam/ai-dial-toolset-editor 1.1.0-dev.465

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 (32) hide show
  1. package/components/AuthSection/AuthSection.d.ts +5 -0
  2. package/components/AuthSection/AuthSection.d.ts.map +1 -0
  3. package/components/ConnectMcpUrlContent/ConnectMcpUrlContent.d.ts +12 -0
  4. package/components/ConnectMcpUrlContent/ConnectMcpUrlContent.d.ts.map +1 -0
  5. package/components/GeneralForm/GeneralForm.d.ts +5 -0
  6. package/components/GeneralForm/GeneralForm.d.ts.map +1 -0
  7. package/components/SettingsForm/SettingsForm.d.ts +5 -0
  8. package/components/SettingsForm/SettingsForm.d.ts.map +1 -0
  9. package/components/ToolsetEditor/ToolsetEditor.d.ts +5 -0
  10. package/components/ToolsetEditor/ToolsetEditor.d.ts.map +1 -0
  11. package/constants/toolsets.d.ts +15 -0
  12. package/constants/toolsets.d.ts.map +1 -0
  13. package/index.d.ts +12 -0
  14. package/index.d.ts.map +1 -0
  15. package/index.js +741 -0
  16. package/models/auth-section-props.d.ts +110 -0
  17. package/models/auth-section-props.d.ts.map +1 -0
  18. package/models/general-form-props.d.ts +42 -0
  19. package/models/general-form-props.d.ts.map +1 -0
  20. package/models/settings-form-props.d.ts +79 -0
  21. package/models/settings-form-props.d.ts.map +1 -0
  22. package/models/toolset-editor-props.d.ts +134 -0
  23. package/models/toolset-editor-props.d.ts.map +1 -0
  24. package/models/toolset-form.d.ts +112 -0
  25. package/models/toolset-form.d.ts.map +1 -0
  26. package/models/toolset-oauth-login.d.ts +60 -0
  27. package/models/toolset-oauth-login.d.ts.map +1 -0
  28. package/package.json +31 -0
  29. package/test-setup.d.ts +1 -0
  30. package/test-setup.d.ts.map +1 -0
  31. package/utils/toolsets.d.ts +33 -0
  32. package/utils/toolsets.d.ts.map +1 -0
package/index.js ADDED
@@ -0,0 +1,741 @@
1
+ import { AvatarPickerModal as e, DeploymentCreationFieldErrorCode as t, DeploymentCreationForm as n, EditorLayout as r, EditorSection as i, validateDeploymentCreationFields as a } from "@epam/ai-dial-builder-form";
2
+ import { ToolsetAuthTypes as o, ToolsetCredentialsLevel as s, WithLogin as c, dialFileToAttachment as l, getApiErrorDetails as u } from "@epam/ai-dial-chat-hooks";
3
+ import { ConfirmationPopup as d, ConfirmationPopupVariant as f, DIAL_ICON_SIZE as p, DIAL_KIT_ICON_STROKE as m, Input as h, NeutralButton as g, PrimaryButton as _, Radio as v, RadioGroup as y, SegmentedControl as b, Select as x, TagInput as S } from "@epam/ai-dial-ui-kit";
4
+ import { memo as C, useCallback as w, useEffect as T, useMemo as E, useRef as D, useState as O } from "react";
5
+ import { IconBrandOauth as k, IconKey as A, IconLockOff as j, IconLogin as ee, IconLogout as te } from "@tabler/icons-react";
6
+ import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
7
+ import { CopyButton as F, TAG_INPUT_TAG_CLASS_NAME as I, mergeClasses as L, useCodeCopy as R } from "@epam/ai-dial-chat-shared";
8
+ //#region src/constants/toolsets.ts
9
+ var z = /* @__PURE__ */ function(e) {
10
+ return e.Http = "HTTP", e.Sse = "SSE", e;
11
+ }({}), B = "New toolset", V = "0.0.1", H = {
12
+ [o.OAuth]: k,
13
+ [o.ApiKey]: A,
14
+ [o.None]: j
15
+ }, U = ({ defaultName: e = B, existingNames: t }) => {
16
+ let n = new Set(t);
17
+ if (!n.has(e)) return e;
18
+ let r = 1;
19
+ for (; n.has(`${e} ${r}`);) r += 1;
20
+ return `${e} ${r}`;
21
+ }, W = () => ({
22
+ authenticationType: o.None,
23
+ withLogin: c.WithoutLogin,
24
+ isLoggedIn: !1
25
+ }), G = (e = []) => ({
26
+ name: U({ existingNames: e }),
27
+ version: V,
28
+ iconUrl: "",
29
+ description: "",
30
+ topics: [],
31
+ otherLocales: [],
32
+ endpoint: "",
33
+ protocol: z.Http,
34
+ allowedTools: [],
35
+ auth: W()
36
+ }), K = (e) => {
37
+ if (!/^(https?|sse):\/\//.test(e) || e.endsWith(".") || e.endsWith("//")) return !1;
38
+ try {
39
+ return !!new URL(e);
40
+ } catch {
41
+ return !1;
42
+ }
43
+ }, q = (e) => K(e.trim()), J = (e) => e.replace(/^(https?|sse):\/([^/])/, "$1://$2"), Y = (e) => {
44
+ let t = e?.trim() ?? "";
45
+ if (!t || K(t)) return t;
46
+ let n = [t];
47
+ try {
48
+ let e = decodeURIComponent(t);
49
+ e !== t && n.push(e);
50
+ } catch {}
51
+ for (let e of n) {
52
+ let t = J(e);
53
+ if (K(t)) return t;
54
+ }
55
+ return t;
56
+ }, X = (e) => !e?.trim() || q(e), Z = (e, t = !1) => e.isLoggedIn ? !0 : e.authenticationType === o.ApiKey ? e.keyHeader?.trim() ? e.withLogin === c.WithoutLogin ? !0 : !!(e.keyHeader?.trim() && e.apiKey?.trim()) : !1 : e.authenticationType === o.OAuth && e.withLogin === c.WithConfig ? !!e.clientId?.trim() && (t || !!e.clientSecret?.trim()) && X(e.authorizationEndpoint) && X(e.tokenEndpoint) : !0, ne = (e, t = !1) => Object.keys(a(e, { validateVersionPattern: !0 })).length === 0 && q(e.endpoint) && Z(e.auth, t), re = {
57
+ name: {
58
+ label: "Name",
59
+ placeholder: "Enter name"
60
+ },
61
+ description: {
62
+ label: "Description",
63
+ placeholder: "Describe what this toolset does"
64
+ },
65
+ iconUrl: {
66
+ label: "Avatar",
67
+ addAvatarLabel: "Add avatar",
68
+ captionText: "PNG, JPG or SVG (max 1 MB)"
69
+ },
70
+ version: {
71
+ label: "Version",
72
+ placeholder: "e.g. 1.0.0"
73
+ },
74
+ topics: {
75
+ label: "Tags",
76
+ placeholder: "Add tags, comma separated"
77
+ },
78
+ otherLocales: {
79
+ summaryLabel: "Locales",
80
+ addLabel: "Add locales",
81
+ editLabel: "Edit locales",
82
+ popupTitle: "Add locale",
83
+ addLocaleLabel: "Add locale",
84
+ localeRowLabel: "Locale",
85
+ languageLabel: "Language",
86
+ nameLabel: "Name",
87
+ namePlaceholder: "Enter name",
88
+ descriptionLabel: "About",
89
+ descriptionPlaceholder: "Enter brief description",
90
+ deleteAriaLabel: "Delete locale",
91
+ cancelLabel: "Cancel",
92
+ saveLabel: "Save"
93
+ },
94
+ ariaLabel: "General"
95
+ }, ie = {
96
+ title: "Add avatar",
97
+ attachLabel: "Attach",
98
+ emptyTitle: "This folder is empty",
99
+ emptyDescription: "",
100
+ errorMessage: "Failed to load files",
101
+ retryLabel: "Retry",
102
+ hiddenFilesLabel: "Hidden files",
103
+ showHiddenFilesLabel: "Show hidden files",
104
+ hideHiddenFilesLabel: "Hide hidden files",
105
+ getSelectionLabel: (e) => e === 1 ? `${e} item selected` : `${e} items selected`,
106
+ uploadFilesLabel: "Upload files",
107
+ newFolderLabel: "New folder",
108
+ downloadLabel: "Download",
109
+ downloadingLabel: "Preparing download…",
110
+ deleteLabel: "Delete",
111
+ deletingLabel: "Deleting…",
112
+ deleteConfirmTitleSingle: "Confirm deleting",
113
+ deleteConfirmTitleMultiple: "Confirm deleting items",
114
+ deleteConfirmSingleText: "Are you sure you want to delete",
115
+ deleteConfirmMultipleText: "Do you want to delete following",
116
+ deleteConfirmItemsLabel: "items?",
117
+ deleteConfirmLabel: "Delete",
118
+ deleteCancelLabel: "Cancel",
119
+ uploadProgressTitle: "Uploading files",
120
+ cancelLabel: "Cancel"
121
+ }, ae = ({ form: t, errors: r, bucket: i, FileManagerModal: a, resolveIconUrl: o, allowedMimeTypes: s, maxFileSizeBytes: c, availableLocaleOptions: u, onChange: d, onNameBlur: f, onVersionBlur: p, labels: m }) => {
122
+ let [h, g] = O(!1), _ = m?.form ?? re, v = m?.avatarPicker ?? ie, y = E(() => o(t.iconUrl), [t.iconUrl, o]);
123
+ return /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(n, {
124
+ values: {
125
+ name: t.name,
126
+ description: t.description,
127
+ iconUrl: t.iconUrl,
128
+ version: t.version,
129
+ topics: t.topics,
130
+ otherLocales: t.otherLocales
131
+ },
132
+ errors: r,
133
+ onChange: d,
134
+ onNameBlur: f,
135
+ onVersionBlur: p,
136
+ iconPreviewUrl: y,
137
+ onAddAvatarClick: () => g(!0),
138
+ labels: _,
139
+ availableLocaleOptions: u
140
+ }), /* @__PURE__ */ N(e, {
141
+ isOpen: h,
142
+ onClose: () => g(!1),
143
+ onAttach: (e) => {
144
+ let [t] = e.files, n = t ? l(t, i, { resolvePreviewUrl: o }) : null;
145
+ n?.url && d({ iconUrl: n.url }), g(!1);
146
+ },
147
+ bucket: i,
148
+ FileManagerModal: a,
149
+ allowedMimeTypes: s,
150
+ maxFileSizeBytes: c,
151
+ labels: v
152
+ })] });
153
+ }, Q = /* @__PURE__ */ function(e) {
154
+ return e.Success = "success", e.Cancelled = "cancelled", e.PopupBlocked = "popup-blocked", e.InvalidConfig = "invalid-config", e.Failed = "failed", e;
155
+ }({}), oe = (e, t) => e === o.None ? c.WithoutLogin : e === o.OAuth && !t ? c.WithConfig : c.WithLogin, se = (e, t) => e === o.None ? t?.typeNone ?? "Open access" : e === o.OAuth ? t?.typeOAuth ?? "OAuth" : t?.typeApiKey ?? "API Key", $ = ({ auth: e, errors: t, isSaving: n, toolsetId: r, isEditMode: i, endpoint: a, authActions: l, onOAuthLogin: _, onNotifySuccess: y, onNotifyError: x, onAuthChange: C, onEnsureSaved: w, labels: T }) => {
156
+ let [E, D] = O(!1), [k, A] = O(!1), j = e.isLoggedIn || n || E, M = q(a) && Z(e, i) && !j, F = (t) => {
157
+ j || t === e.authenticationType || C({
158
+ authenticationType: t,
159
+ withLogin: oe(t, !!e.clientId?.trim())
160
+ });
161
+ }, L = (e) => {
162
+ C({ withLogin: e });
163
+ }, R = (e) => {
164
+ switch (e.auth != null && C(e.auth), e.status) {
165
+ case Q.Success:
166
+ C({ isLoggedIn: !0 }), y(T?.loginSuccessMessage ?? "Successfully logged in.");
167
+ return;
168
+ case Q.PopupBlocked:
169
+ x(T?.errorPopupBlocked ?? "The login popup was blocked by your browser. Please allow popups for this site and try again.");
170
+ return;
171
+ case Q.InvalidConfig:
172
+ x(T?.errorOAuthConfigMissing ?? "The OAuth provider did not return a valid client configuration. Please check the endpoint or contact your administrator.");
173
+ return;
174
+ case Q.Failed:
175
+ x(T?.errorLoginFailed ?? "Failed to log in. Please check your credentials and try again.", e.traceId);
176
+ return;
177
+ case Q.Cancelled: return;
178
+ }
179
+ }, z = async () => {
180
+ if (!M) return;
181
+ if (e.authenticationType === o.OAuth) {
182
+ D(!0);
183
+ try {
184
+ R(await _({
185
+ auth: e,
186
+ ensureSaved: w
187
+ }));
188
+ } finally {
189
+ D(!1);
190
+ }
191
+ return;
192
+ }
193
+ let t = await w();
194
+ if (t) {
195
+ D(!0);
196
+ try {
197
+ let n = {
198
+ url: t,
199
+ credentialsLevel: s.User,
200
+ authenticationType: e.authenticationType,
201
+ apiKey: e.apiKey?.trim()
202
+ };
203
+ await l.login(t, n), C({ isLoggedIn: !0 }), y(T?.loginSuccessMessage ?? "Successfully logged in.");
204
+ } catch (e) {
205
+ let { traceId: t } = await u(e);
206
+ x(T?.errorLoginFailed ?? "Failed to log in. Please check your credentials and try again.", t);
207
+ } finally {
208
+ D(!1);
209
+ }
210
+ }
211
+ }, B = async () => {
212
+ D(!0);
213
+ try {
214
+ let t = {
215
+ url: r,
216
+ credentialsLevel: s.User,
217
+ authenticationType: e.authenticationType
218
+ };
219
+ await l.logout(r, t), C({ isLoggedIn: !1 }), A(!1), y(T?.logoutSuccessMessage ?? "Successfully logged out.");
220
+ } catch (e) {
221
+ let { traceId: t } = await u(e);
222
+ x(T?.errorLogoutFailed ?? "Failed to log out. Please try again.", t);
223
+ } finally {
224
+ D(!1);
225
+ }
226
+ }, V = () => e.isLoggedIn ? /* @__PURE__ */ N("div", {
227
+ className: "flex",
228
+ children: /* @__PURE__ */ N(g, {
229
+ label: T?.logOutLabel ?? "Log out",
230
+ iconBefore: /* @__PURE__ */ N(te, {
231
+ size: p.MD,
232
+ stroke: m
233
+ }),
234
+ onClick: () => A(!0),
235
+ disabled: n || E
236
+ })
237
+ }) : /* @__PURE__ */ N("div", {
238
+ className: "flex",
239
+ children: /* @__PURE__ */ N(g, {
240
+ label: T?.logInLabel ?? "Log in",
241
+ iconBefore: /* @__PURE__ */ N(ee, {
242
+ size: p.MD,
243
+ stroke: m
244
+ }),
245
+ onClick: z,
246
+ disabled: !M
247
+ })
248
+ });
249
+ return /* @__PURE__ */ P("section", {
250
+ className: "flex flex-col gap-2",
251
+ children: [
252
+ /* @__PURE__ */ N("h3", {
253
+ className: "dial-h3-text",
254
+ children: T?.sectionTitle ?? "Authentication"
255
+ }),
256
+ /* @__PURE__ */ N(b, {
257
+ "aria-label": T?.sectionTitle ?? "Authentication",
258
+ value: e.authenticationType,
259
+ onChange: (e) => F(e),
260
+ segmentClassName: "px-2",
261
+ items: [
262
+ o.None,
263
+ o.OAuth,
264
+ o.ApiKey
265
+ ].map((t) => {
266
+ let n = H[t];
267
+ return {
268
+ value: t,
269
+ label: /* @__PURE__ */ P("div", {
270
+ className: "flex items-center gap-2",
271
+ children: [/* @__PURE__ */ N(n, {
272
+ className: "shrink-0",
273
+ size: p.SM,
274
+ stroke: m,
275
+ "aria-hidden": !0
276
+ }), /* @__PURE__ */ N("span", {
277
+ className: "sr-only desktop:not-sr-only",
278
+ children: se(t, T)
279
+ })]
280
+ }),
281
+ disabled: j && e.authenticationType !== t
282
+ };
283
+ })
284
+ }),
285
+ e.authenticationType === o.None && /* @__PURE__ */ N("p", {
286
+ className: "dial-small-text pt-2 text-secondary",
287
+ children: T?.openAccessDescription ?? "Open endpoint, no credentials"
288
+ }),
289
+ e.authenticationType === o.OAuth && /* @__PURE__ */ P("div", {
290
+ className: "flex flex-col gap-3 pt-2",
291
+ children: [
292
+ /* @__PURE__ */ P("div", {
293
+ className: "flex flex-col gap-2",
294
+ children: [/* @__PURE__ */ N(v, {
295
+ name: "oauth-login-mode",
296
+ id: "oauth-with-login",
297
+ value: c.WithLogin,
298
+ labelProps: { label: T?.withLoginOAuthLabel ?? "Standard login" },
299
+ isSelected: e.withLogin === c.WithLogin,
300
+ disabled: j,
301
+ onChange: L
302
+ }), /* @__PURE__ */ N(v, {
303
+ name: "oauth-login-mode",
304
+ id: "oauth-with-config",
305
+ value: c.WithConfig,
306
+ labelProps: { label: T?.withConfigOAuthLabel ?? "Custom login" },
307
+ isSelected: e.withLogin === c.WithConfig,
308
+ disabled: j,
309
+ onChange: L
310
+ })]
311
+ }),
312
+ e.withLogin === c.WithConfig && /* @__PURE__ */ P("div", {
313
+ className: "flex flex-col gap-3",
314
+ children: [
315
+ /* @__PURE__ */ N(h, {
316
+ id: "toolset-client-id",
317
+ value: e.clientId ?? "",
318
+ onChange: (e) => C({ clientId: e ?? "" }),
319
+ labelProps: {
320
+ label: T?.clientIdLabel ?? "Client ID",
321
+ required: !0
322
+ },
323
+ placeholder: T?.clientIdPlaceholder ?? "Enter client ID",
324
+ error: t.clientId || void 0,
325
+ invalid: !!t.clientId,
326
+ disabled: j
327
+ }),
328
+ /* @__PURE__ */ N(h, {
329
+ id: "toolset-client-secret",
330
+ value: e.clientSecret ?? "",
331
+ onChange: (e) => C({ clientSecret: e ?? "" }),
332
+ labelProps: {
333
+ label: T?.clientSecretLabel ?? "Client secret",
334
+ required: !i
335
+ },
336
+ placeholder: T?.clientSecretPlaceholder ?? "Enter client secret",
337
+ error: t.clientSecret || void 0,
338
+ invalid: !!t.clientSecret,
339
+ disabled: j
340
+ }),
341
+ /* @__PURE__ */ N(h, {
342
+ id: "toolset-authorization-endpoint",
343
+ value: e.authorizationEndpoint ?? "",
344
+ onChange: (e) => C({ authorizationEndpoint: e ?? "" }),
345
+ labelProps: { label: T?.authorizationEndpointLabel ?? "Authorization endpoint" },
346
+ placeholder: T?.authorizationEndpointPlaceholder ?? "Enter authorization endpoint",
347
+ error: t.authorizationEndpoint || void 0,
348
+ invalid: !!t.authorizationEndpoint,
349
+ disabled: j
350
+ }),
351
+ /* @__PURE__ */ N(h, {
352
+ id: "toolset-token-endpoint",
353
+ value: e.tokenEndpoint ?? "",
354
+ onChange: (e) => C({ tokenEndpoint: e ?? "" }),
355
+ labelProps: { label: T?.tokenEndpointLabel ?? "Token endpoint" },
356
+ placeholder: T?.tokenEndpointPlaceholder ?? "Enter token endpoint",
357
+ error: t.tokenEndpoint || void 0,
358
+ invalid: !!t.tokenEndpoint,
359
+ disabled: j
360
+ }),
361
+ /* @__PURE__ */ N(S, {
362
+ id: "toolset-scopes",
363
+ labelProps: { label: T?.scopesLabel ?? "Scopes" },
364
+ placeholder: T?.scopesPlaceholder ?? "Enter scopes",
365
+ value: e.scopes ?? [],
366
+ onChange: (e) => C({ scopes: e }),
367
+ disabled: j,
368
+ tagClassName: I
369
+ })
370
+ ]
371
+ }),
372
+ V()
373
+ ]
374
+ }),
375
+ e.authenticationType === o.ApiKey && /* @__PURE__ */ P("div", {
376
+ className: "flex flex-col gap-3 pt-2",
377
+ children: [
378
+ /* @__PURE__ */ P("div", {
379
+ className: "flex flex-col gap-2",
380
+ children: [/* @__PURE__ */ N(v, {
381
+ name: "apikey-login-mode",
382
+ id: "apikey-with-login",
383
+ value: c.WithLogin,
384
+ labelProps: { label: T?.withLoginLabel ?? "With login" },
385
+ isSelected: e.withLogin === c.WithLogin,
386
+ disabled: j,
387
+ onChange: L
388
+ }), /* @__PURE__ */ N(v, {
389
+ name: "apikey-login-mode",
390
+ id: "apikey-without-login",
391
+ value: c.WithoutLogin,
392
+ labelProps: { label: T?.withoutLoginLabel ?? "Without login" },
393
+ isSelected: e.withLogin === c.WithoutLogin,
394
+ disabled: j,
395
+ onChange: L
396
+ })]
397
+ }),
398
+ /* @__PURE__ */ P("div", {
399
+ className: "flex flex-col gap-3",
400
+ children: [/* @__PURE__ */ N(h, {
401
+ id: "toolset-key-header",
402
+ value: e.keyHeader ?? "",
403
+ onChange: (e) => C({ keyHeader: e ?? "" }),
404
+ labelProps: {
405
+ label: T?.keyHeaderLabel ?? "API Key parameter name",
406
+ required: !0
407
+ },
408
+ placeholder: T?.keyHeaderPlaceholder ?? "Enter API key parameter name",
409
+ error: t.keyHeader || void 0,
410
+ invalid: !!t.keyHeader,
411
+ disabled: j
412
+ }), e.withLogin === c.WithLogin && /* @__PURE__ */ N(h, {
413
+ id: "toolset-api-key",
414
+ value: e.apiKey ?? "",
415
+ onChange: (e) => C({ apiKey: e ?? "" }),
416
+ labelProps: {
417
+ label: T?.apiKeyLabel ?? "API key",
418
+ required: !0
419
+ },
420
+ placeholder: T?.apiKeyPlaceholder ?? "Enter API key",
421
+ error: t.apiKey || void 0,
422
+ invalid: !!t.apiKey,
423
+ disabled: j
424
+ })]
425
+ }),
426
+ e.withLogin !== c.WithoutLogin && V()
427
+ ]
428
+ }),
429
+ k && /* @__PURE__ */ N(d, {
430
+ open: k,
431
+ header: T?.logoutConfirmTitle ?? "Log out?",
432
+ description: T?.logoutConfirmDescription ?? "Are you sure you want to log out? You will need to re-enter your credentials to use this toolset again.",
433
+ confirmLabel: T?.logOutLabel ?? "Log out",
434
+ cancelLabel: T?.cancelLabel ?? "Cancel",
435
+ variant: f.Danger,
436
+ isLoading: E,
437
+ disableConfirmButton: E,
438
+ onConfirm: B,
439
+ onCancel: () => A(!1),
440
+ onClose: () => A(!1)
441
+ })
442
+ ]
443
+ });
444
+ }, ce = C(({ url: e, className: t, labels: n }) => {
445
+ let { isCopied: r, copy: i } = R(e), a = n?.copiedLabel ?? "Copied!";
446
+ return /* @__PURE__ */ P("div", {
447
+ className: L("flex flex-col gap-3", t),
448
+ children: [
449
+ /* @__PURE__ */ P("div", {
450
+ className: "flex flex-col gap-1",
451
+ children: [/* @__PURE__ */ N("p", {
452
+ className: "dial-body-semi-text text-start text-primary",
453
+ children: n?.title ?? "Connect toolset"
454
+ }), /* @__PURE__ */ N("p", {
455
+ className: "dial-small-text text-start text-secondary",
456
+ children: n?.description ?? "Copy endpoint URL to easily integrate toolset into your workflows"
457
+ })]
458
+ }),
459
+ /* @__PURE__ */ N("div", { children: /* @__PURE__ */ N(F, {
460
+ copiedLabel: a,
461
+ copyLabel: n?.copyLabel ?? "Copy URL",
462
+ isCopied: r,
463
+ onClick: i
464
+ }) }),
465
+ /* @__PURE__ */ N("span", {
466
+ role: "status",
467
+ "aria-live": "polite",
468
+ className: "sr-only",
469
+ children: r ? a : ""
470
+ })
471
+ ]
472
+ });
473
+ }), le = ({ form: e, errors: t, isSaving: n, toolsetId: r, isEditMode: i, connectUrl: a, listToolNames: o, authActions: s, onOAuthLogin: c, onNotifySuccess: l, onNotifyError: u, onChange: d, onAuthChange: f, onEnsureSaved: p, labels: m }) => {
474
+ let [g, _] = O(null), v = !!a && !!r, b = E(() => [{
475
+ value: z.Http,
476
+ label: "HTTP"
477
+ }, {
478
+ value: z.Sse,
479
+ label: "SSE"
480
+ }], []);
481
+ return T(() => {
482
+ if (!r || !o || !Z(e.auth, i)) {
483
+ _(null);
484
+ return;
485
+ }
486
+ let t = !1;
487
+ return (async () => {
488
+ try {
489
+ let e = await o(r);
490
+ t || _(e.length > 0 ? e : null);
491
+ } catch {
492
+ t || _(null);
493
+ }
494
+ })(), () => {
495
+ t = !0;
496
+ };
497
+ }, [
498
+ r,
499
+ i,
500
+ e.auth,
501
+ e.endpoint,
502
+ o
503
+ ]), /* @__PURE__ */ P("div", {
504
+ className: "flex max-w-[1060px] flex-col gap-4",
505
+ children: [
506
+ /* @__PURE__ */ N(h, {
507
+ id: "toolset-endpoint",
508
+ value: e.endpoint,
509
+ onChange: (e) => d({ endpoint: e ?? "" }),
510
+ labelProps: {
511
+ label: m?.endpointLabel ?? "Endpoint",
512
+ required: !0
513
+ },
514
+ placeholder: m?.endpointPlaceholder ?? "https://...",
515
+ caption: m?.endpointCaption ?? "The HTTPS address where the server accepts MCP requests.",
516
+ error: t.endpoint || void 0,
517
+ invalid: !!t.endpoint
518
+ }),
519
+ /* @__PURE__ */ N(y, {
520
+ labelProps: {
521
+ label: m?.protocolLabel ?? "Protocol",
522
+ required: !0
523
+ },
524
+ id: "toolset-protocol",
525
+ items: b,
526
+ value: e.protocol,
527
+ onChange: (e) => {
528
+ d({ protocol: e });
529
+ }
530
+ }),
531
+ g ? /* @__PURE__ */ N(x, {
532
+ id: "toolset-allowed-tools",
533
+ multiple: !0,
534
+ searchable: !0,
535
+ selectAll: !0,
536
+ labelProps: { label: m?.allowedToolsLabel ?? "Allowed tools" },
537
+ placeholder: m?.allowedToolsSelectPlaceholder ?? "Select allowed tools",
538
+ options: g.map((e) => ({
539
+ value: e,
540
+ label: e
541
+ })),
542
+ value: e.allowedTools,
543
+ onChange: (e) => d({ allowedTools: e })
544
+ }) : /* @__PURE__ */ N(S, {
545
+ id: "toolset-allowed-tools",
546
+ labelProps: { label: m?.allowedToolsLabel ?? "Allowed tools" },
547
+ placeholder: m?.allowedToolsPlaceholder ?? "Add tools, comma separated",
548
+ value: e.allowedTools,
549
+ onChange: (e) => d({ allowedTools: e }),
550
+ tagClassName: I
551
+ }),
552
+ /* @__PURE__ */ N($, {
553
+ auth: e.auth,
554
+ errors: t,
555
+ isSaving: n,
556
+ toolsetId: r,
557
+ isEditMode: i,
558
+ endpoint: e.endpoint,
559
+ authActions: s,
560
+ onOAuthLogin: c,
561
+ onNotifySuccess: l,
562
+ onNotifyError: u,
563
+ onAuthChange: f,
564
+ onEnsureSaved: p,
565
+ labels: m?.auth
566
+ }),
567
+ v && /* @__PURE__ */ N(ce, {
568
+ url: a ?? "",
569
+ labels: m?.connect,
570
+ className: "border-t border-tertiary pt-4"
571
+ })
572
+ ]
573
+ });
574
+ }, ue = [
575
+ "keyHeader",
576
+ "apiKey",
577
+ "clientId",
578
+ "clientSecret",
579
+ "authorizationEndpoint",
580
+ "tokenEndpoint"
581
+ ], de = [
582
+ "name",
583
+ "version",
584
+ "endpoint",
585
+ ...ue
586
+ ], fe = new Set(de), pe = (e) => {
587
+ let t = {};
588
+ for (let n of Object.keys(e)) fe.has(n) && (t[n] = !0);
589
+ return t;
590
+ }, me = ({ initialForm: e, toolsetId: n, onPersist: s, onPostSaveLogin: l, onToolsetsChanged: d, onSaveSuccess: f, onSaveComplete: p, onBack: m, buildMcpUrl: h, listToolNames: v, authActions: y, onOAuthLogin: b, onNotifySuccess: x, onNotifyError: S, bucket: C, FileManagerModal: k, resolveIconUrl: A, allowedMimeTypes: j, maxFileSizeBytes: ee, availableLocaleOptions: te, labels: F }) => {
591
+ let I = !!n, [L, R] = O(""), z = n || L, [B, V] = O(e), [H, U] = O(!1), [W, G] = O({}), [K, J] = O({}), Y = D(null);
592
+ T(() => {
593
+ V(e), Y.current = e, G({}), J({}), R("");
594
+ }, [e]);
595
+ let X = w((e) => {
596
+ V((t) => ({
597
+ ...t,
598
+ ...e
599
+ })), J((t) => ({
600
+ ...t,
601
+ ...pe(e)
602
+ })), G((t) => {
603
+ let n = { ...t };
604
+ for (let t of Object.keys(e)) delete n[t];
605
+ return n;
606
+ });
607
+ }, []), Z = w((e) => {
608
+ V((t) => ({
609
+ ...t,
610
+ auth: {
611
+ ...t.auth,
612
+ ...e
613
+ }
614
+ })), J((t) => ({
615
+ ...t,
616
+ ...pe(e)
617
+ })), G((t) => {
618
+ let n = { ...t };
619
+ if ("authenticationType" in e || "withLogin" in e || "isLoggedIn" in e) for (let e of ue) delete n[e];
620
+ else for (let t of Object.keys(e)) delete n[t];
621
+ return n;
622
+ }), "isLoggedIn" in e && d();
623
+ }, [d]), re = w(async () => {
624
+ if (z && Y.current != null && JSON.stringify(Y.current) === JSON.stringify(B)) return z;
625
+ U(!0);
626
+ try {
627
+ let e = await s(B, z);
628
+ return e ? (z || R(e), Y.current = B, await d(), e) : null;
629
+ } catch {
630
+ return null;
631
+ } finally {
632
+ U(!1);
633
+ }
634
+ }, [
635
+ B,
636
+ z,
637
+ s,
638
+ d
639
+ ]), ie = w(async () => await re() ?? !1, [re]), Q = w((e) => {
640
+ let n = F?.validation, r = {}, i = a(e, { validateVersionPattern: !0 });
641
+ return i.name === t.Required && (r.name = n?.nameRequired ?? "Name is required"), i.version === t.InvalidFormat && (r.version = n?.versionInvalid ?? "Version may only contain letters, digits, dots, underscores, and dashes"), e.endpoint.trim() ? q(e.endpoint) || (r.endpoint = n?.endpointInvalid ?? "Enter a valid http(s) or sse URL") : r.endpoint = n?.endpointRequired ?? "Endpoint is required", e.auth.isLoggedIn || (e.auth.authenticationType === o.ApiKey && (e.auth.keyHeader?.trim() || (r.keyHeader = n?.keyHeaderRequired ?? "Key name is required"), e.auth.withLogin === c.WithLogin && !e.auth.apiKey?.trim() && (r.apiKey = n?.apiKeyRequired ?? "API key is required")), e.auth.authenticationType === o.OAuth && e.auth.withLogin === c.WithConfig && (e.auth.clientId?.trim() || (r.clientId = n?.clientIdRequired ?? "Client ID is required"), !I && !e.auth.clientSecret?.trim() && (r.clientSecret = n?.clientSecretRequired ?? "Client secret is required"), e.auth.authorizationEndpoint?.trim() && !q(e.auth.authorizationEndpoint) && (r.authorizationEndpoint = n?.endpointInvalid ?? "Enter a valid http(s) or sse URL"), e.auth.tokenEndpoint?.trim() && !q(e.auth.tokenEndpoint) && (r.tokenEndpoint = n?.endpointInvalid ?? "Enter a valid http(s) or sse URL"))), r;
642
+ }, [F, I]), oe = w(async () => {
643
+ let e = Q(B);
644
+ if (Object.keys(e).length > 0) {
645
+ G(e);
646
+ return;
647
+ }
648
+ G({}), U(!0);
649
+ try {
650
+ let e = await s(B, z);
651
+ if (!e) return;
652
+ await d(), f(B);
653
+ try {
654
+ await l(e, B.auth), p();
655
+ } catch (e) {
656
+ let { traceId: t } = await u(e);
657
+ S(F?.settings?.auth?.errorLoginFailed ?? "Failed to log in. Please check your credentials and try again.", t);
658
+ }
659
+ } catch {} finally {
660
+ U(!1);
661
+ }
662
+ }, [
663
+ B,
664
+ Q,
665
+ z,
666
+ s,
667
+ d,
668
+ f,
669
+ p,
670
+ l,
671
+ S,
672
+ F
673
+ ]), se = E(() => !ne(B, I), [B, I]), $ = E(() => {
674
+ let e = Q(B), t = { ...W };
675
+ for (let n of de) {
676
+ if (!K[n]) continue;
677
+ let r = e[n];
678
+ r ? t[n] = r : delete t[n];
679
+ }
680
+ return t;
681
+ }, [
682
+ K,
683
+ W,
684
+ B,
685
+ Q
686
+ ]), ce = h && z ? h(z) : void 0;
687
+ return /* @__PURE__ */ N(r, {
688
+ title: I ? F?.layout?.editTitle ?? "Edit toolset" : F?.layout?.createTitle ?? "Create toolset",
689
+ onBack: m,
690
+ backAriaLabel: F?.layout?.backAriaLabel ?? "Back to catalog",
691
+ isSaving: H,
692
+ labels: { savingStatusLabel: F?.layout?.savingStatusLabel ?? "Saving" },
693
+ actions: /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ N(g, {
694
+ label: F?.layout?.cancelLabel ?? "Cancel",
695
+ onClick: m
696
+ }), /* @__PURE__ */ N(_, {
697
+ label: I ? F?.layout?.saveLabel ?? "Save" : F?.layout?.createLabel ?? "Create",
698
+ disabled: se,
699
+ onClick: oe
700
+ })] }),
701
+ leftContent: /* @__PURE__ */ N(i, {
702
+ title: F?.layout?.metadataSectionTitle ?? "Metadata",
703
+ className: "border-0 p-4 desktop:p-6",
704
+ children: /* @__PURE__ */ N(ae, {
705
+ form: B,
706
+ errors: $,
707
+ bucket: C,
708
+ FileManagerModal: k,
709
+ resolveIconUrl: A,
710
+ allowedMimeTypes: j,
711
+ maxFileSizeBytes: ee,
712
+ availableLocaleOptions: te,
713
+ onChange: X,
714
+ labels: F?.general
715
+ })
716
+ }),
717
+ rightContent: /* @__PURE__ */ N(i, {
718
+ title: F?.layout?.setupSectionTitle ?? "Setup",
719
+ className: "border-0 p-4 desktop:p-6",
720
+ children: /* @__PURE__ */ N(le, {
721
+ form: B,
722
+ errors: $,
723
+ isSaving: H,
724
+ toolsetId: z,
725
+ isEditMode: I,
726
+ connectUrl: ce,
727
+ listToolNames: v,
728
+ authActions: y,
729
+ onOAuthLogin: b,
730
+ onNotifySuccess: x,
731
+ onNotifyError: S,
732
+ onChange: X,
733
+ onAuthChange: Z,
734
+ onEnsureSaved: ie,
735
+ labels: F?.settings
736
+ })
737
+ })
738
+ });
739
+ };
740
+ //#endregion
741
+ export { H as AUTH_TYPE_ICONS, B as DEFAULT_TOOLSET_NAME, V as DEFAULT_TOOLSET_VERSION, ae as GeneralForm, me as ToolsetEditor, Q as ToolsetOAuthLoginStatus, z as ToolsetTransportType, G as getDefaultToolsetForm, U as getStorageSafeUniqueToolsetName, Z as isToolsetAuthValid, ne as isToolsetFormValid, q as isValidEndpointUrl, Y as normalizeReturnedEndpointUrl };