@truefoundry/trueforge-ui 0.0.0 → 0.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +340 -0
- package/LICENSE +21 -0
- package/NOTICE +17 -0
- package/README.md +640 -3
- package/dist/ConnectorSettings-CLBEWGQJ.js +898 -0
- package/dist/ConnectorSettings-CLBEWGQJ.js.map +1 -0
- package/dist/DockLayout-WRF7EQLD.js +35 -0
- package/dist/DockLayout-WRF7EQLD.js.map +1 -0
- package/dist/DrawerLayout-X2UXYTOS.js +156 -0
- package/dist/DrawerLayout-X2UXYTOS.js.map +1 -0
- package/dist/ModelSettings-IJ55QJQO.js +1082 -0
- package/dist/ModelSettings-IJ55QJQO.js.map +1 -0
- package/dist/OpenUiFenceBlock-SLLZSTMJ.js +9 -0
- package/dist/OpenUiFenceBlock-SLLZSTMJ.js.map +1 -0
- package/dist/SandboxSettings-S5XGZWOL.js +505 -0
- package/dist/SandboxSettings-S5XGZWOL.js.map +1 -0
- package/dist/SettingsBuilder-64Y33NP3.js +128 -0
- package/dist/SettingsBuilder-64Y33NP3.js.map +1 -0
- package/dist/SidebarLayout-M7HEOZVK.js +236 -0
- package/dist/SidebarLayout-M7HEOZVK.js.map +1 -0
- package/dist/SkillSettings-MXK4ZEI7.js +389 -0
- package/dist/SkillSettings-MXK4ZEI7.js.map +1 -0
- package/dist/WidgetLayout-7MDOKLHU.js +101 -0
- package/dist/WidgetLayout-7MDOKLHU.js.map +1 -0
- package/dist/assistant-ui.d.ts +1 -0
- package/dist/assistant-ui.js +9 -0
- package/dist/assistant-ui.js.map +1 -0
- package/dist/chunk-42GF723P.js +24 -0
- package/dist/chunk-42GF723P.js.map +1 -0
- package/dist/chunk-CFLVPV5M.js +29 -0
- package/dist/chunk-CFLVPV5M.js.map +1 -0
- package/dist/chunk-M6MHLVSO.js +8 -0
- package/dist/chunk-M6MHLVSO.js.map +1 -0
- package/dist/chunk-NBMP2XNL.js +89 -0
- package/dist/chunk-NBMP2XNL.js.map +1 -0
- package/dist/chunk-UBOFEI77.js +567 -0
- package/dist/chunk-UBOFEI77.js.map +1 -0
- package/dist/chunk-UHGSHDBM.js +633 -0
- package/dist/chunk-UHGSHDBM.js.map +1 -0
- package/dist/chunk-UXZOL5GO.js +2088 -0
- package/dist/chunk-UXZOL5GO.js.map +1 -0
- package/dist/chunk-WFC3W4C3.js +73 -0
- package/dist/chunk-WFC3W4C3.js.map +1 -0
- package/dist/chunk-XSHXH6EI.js +6800 -0
- package/dist/chunk-XSHXH6EI.js.map +1 -0
- package/dist/createTrueFoundryServer-B72bU-J7.d.ts +28 -0
- package/dist/index.d.ts +1569 -0
- package/dist/index.js +781 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +479 -0
- package/dist/plugins/trueforge-agent-server-adapter/index.js +830 -0
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +129 -6
- package/index.js +0 -1
|
@@ -0,0 +1,898 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
CatalogLogo,
|
|
5
|
+
CenteredModal,
|
|
6
|
+
SearchInput_default,
|
|
7
|
+
auiInputClass,
|
|
8
|
+
getErrorMessage,
|
|
9
|
+
useMCPAuth,
|
|
10
|
+
useToasterOptional
|
|
11
|
+
} from "./chunk-XSHXH6EI.js";
|
|
12
|
+
import {
|
|
13
|
+
Icon,
|
|
14
|
+
useCatalogServer
|
|
15
|
+
} from "./chunk-UHGSHDBM.js";
|
|
16
|
+
import "./chunk-42GF723P.js";
|
|
17
|
+
import {
|
|
18
|
+
cn
|
|
19
|
+
} from "./chunk-UBOFEI77.js";
|
|
20
|
+
|
|
21
|
+
// src/containers/SettingsBuilder/ConnectorSettings.tsx
|
|
22
|
+
import { useCallback, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
|
|
23
|
+
|
|
24
|
+
// src/containers/SettingsBuilder/AddMcpServerForm.tsx
|
|
25
|
+
import { useState } from "react";
|
|
26
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
27
|
+
var AUTH_OPTIONS = [
|
|
28
|
+
{ value: "dcr", label: "OAuth" },
|
|
29
|
+
{ value: "none", label: "None" },
|
|
30
|
+
{ value: "header", label: "API Key" }
|
|
31
|
+
];
|
|
32
|
+
var inputClassName = auiInputClass("h-11 shadow-sm");
|
|
33
|
+
var RequiredMark = () => /* @__PURE__ */ jsx("span", { className: "ml-0.5 text-failure-bg", "aria-hidden": true, children: "*" });
|
|
34
|
+
var AddMcpServerForm = ({ open, onOpenChange, onAdd, busy = false, error }) => {
|
|
35
|
+
const [name, setName] = useState("");
|
|
36
|
+
const [url, setUrl] = useState("");
|
|
37
|
+
const [authType, setAuthType] = useState("dcr");
|
|
38
|
+
const [apiKey, setApiKey] = useState("");
|
|
39
|
+
const [headerName, setHeaderName] = useState("");
|
|
40
|
+
const resetForm = () => {
|
|
41
|
+
setName("");
|
|
42
|
+
setUrl("");
|
|
43
|
+
setAuthType("dcr");
|
|
44
|
+
setApiKey("");
|
|
45
|
+
setHeaderName("");
|
|
46
|
+
};
|
|
47
|
+
const handleOpenChange = (nextOpen) => {
|
|
48
|
+
if (!nextOpen) resetForm();
|
|
49
|
+
onOpenChange(nextOpen);
|
|
50
|
+
};
|
|
51
|
+
const isValid = !!name.trim() && !!url.trim() && (authType !== "header" || !!apiKey.trim());
|
|
52
|
+
const handleSubmit = async (event) => {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
if (!isValid || busy) return;
|
|
55
|
+
const auth = authType === "header" ? {
|
|
56
|
+
type: "header",
|
|
57
|
+
apiKey: apiKey.trim(),
|
|
58
|
+
...headerName.trim() ? { headerName: headerName.trim() } : {}
|
|
59
|
+
} : { type: authType };
|
|
60
|
+
try {
|
|
61
|
+
await onAdd({
|
|
62
|
+
name: name.trim(),
|
|
63
|
+
url: url.trim(),
|
|
64
|
+
auth
|
|
65
|
+
});
|
|
66
|
+
resetForm();
|
|
67
|
+
onOpenChange(false);
|
|
68
|
+
} catch {
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
CenteredModal,
|
|
73
|
+
{
|
|
74
|
+
open,
|
|
75
|
+
onOpenChange: handleOpenChange,
|
|
76
|
+
title: "Add MCP server",
|
|
77
|
+
description: "Point at a remote MCP endpoint. It then behaves like any other connector.",
|
|
78
|
+
contentSized: true,
|
|
79
|
+
headerIcon: /* @__PURE__ */ jsx(
|
|
80
|
+
"span",
|
|
81
|
+
{
|
|
82
|
+
className: "flex size-11 shrink-0 items-center justify-center rounded-lg border border-border bg-secondary-bg text-text-primary",
|
|
83
|
+
"aria-hidden": true,
|
|
84
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "mcp-server", className: "size-6" })
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
children: /* @__PURE__ */ jsxs("form", { className: "flex flex-col overflow-y-auto p-5 md:p-6", onSubmit: (e) => void handleSubmit(e), children: [
|
|
88
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
89
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
90
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "mcp-server-name", className: "mb-1.5 block text-sm font-medium text-text-primary", children: [
|
|
91
|
+
"Name",
|
|
92
|
+
/* @__PURE__ */ jsx(RequiredMark, {})
|
|
93
|
+
] }),
|
|
94
|
+
/* @__PURE__ */ jsx(
|
|
95
|
+
"input",
|
|
96
|
+
{
|
|
97
|
+
id: "mcp-server-name",
|
|
98
|
+
type: "text",
|
|
99
|
+
required: true,
|
|
100
|
+
value: name,
|
|
101
|
+
onChange: (event) => {
|
|
102
|
+
setName(event.target.value);
|
|
103
|
+
},
|
|
104
|
+
placeholder: "analytics-postgres-mcp",
|
|
105
|
+
autoFocus: true,
|
|
106
|
+
className: inputClassName
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
] }),
|
|
110
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
111
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "mcp-server-url", className: "mb-1.5 block text-sm font-medium text-text-primary", children: [
|
|
112
|
+
"URL",
|
|
113
|
+
/* @__PURE__ */ jsx(RequiredMark, {})
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ jsx(
|
|
116
|
+
"input",
|
|
117
|
+
{
|
|
118
|
+
id: "mcp-server-url",
|
|
119
|
+
type: "url",
|
|
120
|
+
required: true,
|
|
121
|
+
value: url,
|
|
122
|
+
onChange: (event) => {
|
|
123
|
+
setUrl(event.target.value);
|
|
124
|
+
},
|
|
125
|
+
placeholder: "https://mcp.example.com/mcp",
|
|
126
|
+
className: inputClassName
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] }),
|
|
130
|
+
/* @__PURE__ */ jsxs("fieldset", { children: [
|
|
131
|
+
/* @__PURE__ */ jsxs("legend", { className: "mb-1.5 text-sm font-medium text-text-primary", children: [
|
|
132
|
+
"Auth type",
|
|
133
|
+
/* @__PURE__ */ jsx(RequiredMark, {})
|
|
134
|
+
] }),
|
|
135
|
+
/* @__PURE__ */ jsx("div", { className: "flex w-full flex-row rounded-md border border-border bg-secondary-bg/40 p-1", children: AUTH_OPTIONS.map((option) => /* @__PURE__ */ jsxs(
|
|
136
|
+
"label",
|
|
137
|
+
{
|
|
138
|
+
className: `flex h-8 flex-1 cursor-pointer items-center justify-center rounded-sm text-sm font-medium transition-colors ${authType === option.value ? "bg-dropdown-selected-item-bg text-dropdown-selected-item-text shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
|
|
139
|
+
children: [
|
|
140
|
+
/* @__PURE__ */ jsx(
|
|
141
|
+
"input",
|
|
142
|
+
{
|
|
143
|
+
type: "radio",
|
|
144
|
+
name: "mcp-auth-type",
|
|
145
|
+
value: option.value,
|
|
146
|
+
checked: authType === option.value,
|
|
147
|
+
onChange: () => {
|
|
148
|
+
setAuthType(option.value);
|
|
149
|
+
},
|
|
150
|
+
className: "sr-only"
|
|
151
|
+
}
|
|
152
|
+
),
|
|
153
|
+
option.label
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
option.value
|
|
157
|
+
)) })
|
|
158
|
+
] }),
|
|
159
|
+
authType === "dcr" ? /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 bg-secondary-bg/40 p-2 rounded-md", children: [
|
|
160
|
+
/* @__PURE__ */ jsx(Icon, { name: "info", className: "size-3.5 mt-1 text-text-secondary" }),
|
|
161
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary leading-5.5", children: "Sign-in only \u2014 the server must support dynamic client registration. Manual OAuth (client ID / secret) isn't supported yet." })
|
|
162
|
+
] }) : null,
|
|
163
|
+
authType === "header" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
165
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "mcp-server-api-key", className: "mb-1.5 block text-sm font-medium text-text-primary", children: [
|
|
166
|
+
"API key",
|
|
167
|
+
/* @__PURE__ */ jsx(RequiredMark, {})
|
|
168
|
+
] }),
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
"input",
|
|
171
|
+
{
|
|
172
|
+
id: "mcp-server-api-key",
|
|
173
|
+
type: "password",
|
|
174
|
+
required: true,
|
|
175
|
+
value: apiKey,
|
|
176
|
+
onChange: (event) => {
|
|
177
|
+
setApiKey(event.target.value);
|
|
178
|
+
},
|
|
179
|
+
placeholder: "Paste the server token",
|
|
180
|
+
className: inputClassName
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
] }),
|
|
184
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
185
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "mcp-server-header-name", className: "mb-1.5 block text-sm font-medium text-text-primary", children: [
|
|
186
|
+
"Header name ",
|
|
187
|
+
/* @__PURE__ */ jsx("span", { className: "font-normal text-text-secondary", children: "(optional)" })
|
|
188
|
+
] }),
|
|
189
|
+
/* @__PURE__ */ jsx(
|
|
190
|
+
"input",
|
|
191
|
+
{
|
|
192
|
+
id: "mcp-server-header-name",
|
|
193
|
+
type: "text",
|
|
194
|
+
value: headerName,
|
|
195
|
+
onChange: (event) => {
|
|
196
|
+
setHeaderName(event.target.value);
|
|
197
|
+
},
|
|
198
|
+
placeholder: "Authorization",
|
|
199
|
+
className: inputClassName
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
] })
|
|
203
|
+
] }) : null
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-3", children: [
|
|
206
|
+
error ? /* @__PURE__ */ jsx("p", { className: "text-failure-bg text-sm", children: error }) : null,
|
|
207
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", size: "lg", disabled: !isValid || busy, className: "w-full shrink-0", children: "Add" })
|
|
208
|
+
] })
|
|
209
|
+
] })
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
};
|
|
213
|
+
var AddMcpServerForm_default = AddMcpServerForm;
|
|
214
|
+
|
|
215
|
+
// src/containers/SettingsBuilder/authTypeLabels.ts
|
|
216
|
+
var AUTH_TYPE_LABELS = {
|
|
217
|
+
dcr: "OAuth2",
|
|
218
|
+
header: "API Key",
|
|
219
|
+
none: "No Auth"
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// src/containers/SettingsBuilder/ConnectorDetails.tsx
|
|
223
|
+
import { useEffect, useLayoutEffect, useRef, useState as useState2 } from "react";
|
|
224
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
225
|
+
function ExpandableDescription({ text }) {
|
|
226
|
+
const contentRef = useRef(null);
|
|
227
|
+
const [expanded, setExpanded] = useState2(false);
|
|
228
|
+
const [canExpand, setCanExpand] = useState2(false);
|
|
229
|
+
const [maxHeight, setMaxHeight] = useState2(16);
|
|
230
|
+
useLayoutEffect(() => {
|
|
231
|
+
setExpanded(false);
|
|
232
|
+
setMaxHeight(16);
|
|
233
|
+
}, [text]);
|
|
234
|
+
useLayoutEffect(() => {
|
|
235
|
+
const el = contentRef.current;
|
|
236
|
+
if (!el) return;
|
|
237
|
+
if (!expanded) {
|
|
238
|
+
setMaxHeight(16);
|
|
239
|
+
setCanExpand(el.scrollWidth > el.clientWidth + 1);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
setMaxHeight(16);
|
|
243
|
+
const frame = requestAnimationFrame(() => {
|
|
244
|
+
setMaxHeight(el.scrollHeight);
|
|
245
|
+
});
|
|
246
|
+
return () => cancelAnimationFrame(frame);
|
|
247
|
+
}, [text, expanded]);
|
|
248
|
+
if (!text) return null;
|
|
249
|
+
return /* @__PURE__ */ jsxs2("div", { className: "relative min-w-0", children: [
|
|
250
|
+
/* @__PURE__ */ jsxs2(
|
|
251
|
+
"p",
|
|
252
|
+
{
|
|
253
|
+
ref: contentRef,
|
|
254
|
+
style: { maxHeight },
|
|
255
|
+
className: cn(
|
|
256
|
+
"mt-0.5 overflow-hidden font-mono text-xs leading-4 text-text-secondary transition-[max-height] duration-300 ease-in-out",
|
|
257
|
+
!expanded && "whitespace-nowrap",
|
|
258
|
+
!expanded && canExpand && "pr-[5.75rem]"
|
|
259
|
+
),
|
|
260
|
+
children: [
|
|
261
|
+
text,
|
|
262
|
+
expanded && canExpand ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
263
|
+
" ",
|
|
264
|
+
/* @__PURE__ */ jsx2(
|
|
265
|
+
"button",
|
|
266
|
+
{
|
|
267
|
+
type: "button",
|
|
268
|
+
className: "cursor-pointer font-mono text-xs font-medium text-text-primary/80 hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring",
|
|
269
|
+
"aria-expanded": true,
|
|
270
|
+
onClick: () => setExpanded(false),
|
|
271
|
+
children: "Show less"
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
] }) : null
|
|
275
|
+
]
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
!expanded && canExpand ? /* @__PURE__ */ jsxs2(
|
|
279
|
+
"button",
|
|
280
|
+
{
|
|
281
|
+
type: "button",
|
|
282
|
+
className: "absolute top-0.5 right-0 cursor-pointer bg-card-bg pl-1.5 font-mono text-xs font-medium leading-4 text-text-primary/80 hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring",
|
|
283
|
+
"aria-expanded": false,
|
|
284
|
+
onClick: () => setExpanded(true),
|
|
285
|
+
children: [
|
|
286
|
+
/* @__PURE__ */ jsx2("span", { "aria-hidden": true, className: "text-text-secondary", children: "\u2026" }),
|
|
287
|
+
/* @__PURE__ */ jsx2("span", { className: "ml-1", children: "Read more" })
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
) : null
|
|
291
|
+
] });
|
|
292
|
+
}
|
|
293
|
+
var ConnectorDetails = ({
|
|
294
|
+
connector,
|
|
295
|
+
onBack,
|
|
296
|
+
onConnectorRefreshed,
|
|
297
|
+
onDisconnect,
|
|
298
|
+
busy = false
|
|
299
|
+
}) => {
|
|
300
|
+
const { connectorCatalog } = useCatalogServer();
|
|
301
|
+
const { handleAuthorize, isOAuthLoading } = useMCPAuth();
|
|
302
|
+
const [tools, setTools] = useState2([]);
|
|
303
|
+
const [toolsLoading, setToolsLoading] = useState2(true);
|
|
304
|
+
const [toolsError, setToolsError] = useState2(null);
|
|
305
|
+
const [refreshingAfterAuth, setRefreshingAfterAuth] = useState2(false);
|
|
306
|
+
useEffect(() => {
|
|
307
|
+
let cancelled = false;
|
|
308
|
+
setTools([]);
|
|
309
|
+
setToolsError(null);
|
|
310
|
+
setToolsLoading(true);
|
|
311
|
+
void connectorCatalog.getToolsByConnectorId({ id: connector.id }).then((result) => {
|
|
312
|
+
if (!cancelled) setTools(result);
|
|
313
|
+
}).catch((err) => {
|
|
314
|
+
if (!cancelled) {
|
|
315
|
+
setToolsError(getErrorMessage(err, "Failed to load connector tools"));
|
|
316
|
+
}
|
|
317
|
+
}).finally(() => {
|
|
318
|
+
if (!cancelled) setToolsLoading(false);
|
|
319
|
+
});
|
|
320
|
+
return () => {
|
|
321
|
+
cancelled = true;
|
|
322
|
+
};
|
|
323
|
+
}, [connector.authenticated, connector.id, connectorCatalog]);
|
|
324
|
+
const refreshAfterAuthentication = async () => {
|
|
325
|
+
setRefreshingAfterAuth(true);
|
|
326
|
+
setToolsError(null);
|
|
327
|
+
try {
|
|
328
|
+
const refreshedConnector = await connectorCatalog.getConnector({ id: connector.id });
|
|
329
|
+
onConnectorRefreshed(refreshedConnector);
|
|
330
|
+
} catch (err) {
|
|
331
|
+
setToolsError(getErrorMessage(err, "Failed to refresh connector details"));
|
|
332
|
+
} finally {
|
|
333
|
+
setRefreshingAfterAuth(false);
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const connecting = isOAuthLoading || refreshingAfterAuth;
|
|
337
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-full flex-col overflow-hidden", children: [
|
|
338
|
+
/* @__PURE__ */ jsxs2(
|
|
339
|
+
"button",
|
|
340
|
+
{
|
|
341
|
+
type: "button",
|
|
342
|
+
onClick: onBack,
|
|
343
|
+
className: "mb-3 inline-flex w-fit items-center gap-1 rounded-md py-1 pr-2 text-sm text-text-secondary hover:text-text-primary focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring",
|
|
344
|
+
children: [
|
|
345
|
+
/* @__PURE__ */ jsx2(Icon, { name: "chevron-left", className: "size-3.5" }),
|
|
346
|
+
"Connectors"
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
),
|
|
350
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col overflow-y-auto pb-1", children: [
|
|
351
|
+
/* @__PURE__ */ jsxs2("header", { className: "flex items-start gap-3", children: [
|
|
352
|
+
/* @__PURE__ */ jsx2(
|
|
353
|
+
"span",
|
|
354
|
+
{
|
|
355
|
+
className: "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg",
|
|
356
|
+
"aria-hidden": true,
|
|
357
|
+
children: /* @__PURE__ */ jsx2(Icon, { name: "mcp-server", className: "size-5 text-text-primary" })
|
|
358
|
+
}
|
|
359
|
+
),
|
|
360
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
|
|
361
|
+
/* @__PURE__ */ jsx2("h4", { className: "text-lg font-semibold text-text-primary", children: connector.name }),
|
|
362
|
+
/* @__PURE__ */ jsxs2("div", { className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-1 text-sm", children: [
|
|
363
|
+
/* @__PURE__ */ jsxs2(
|
|
364
|
+
"span",
|
|
365
|
+
{
|
|
366
|
+
className: cn(
|
|
367
|
+
"flex items-center gap-1.5 text-xs font-medium",
|
|
368
|
+
connector.authenticated ? "text-success-bg" : "text-text-primary"
|
|
369
|
+
),
|
|
370
|
+
children: [
|
|
371
|
+
/* @__PURE__ */ jsx2(
|
|
372
|
+
"span",
|
|
373
|
+
{
|
|
374
|
+
className: cn(
|
|
375
|
+
"h-1.5 w-1.5 rounded-full",
|
|
376
|
+
connector.authenticated ? "bg-success-bg" : "bg-primary-button-bg"
|
|
377
|
+
)
|
|
378
|
+
}
|
|
379
|
+
),
|
|
380
|
+
connector.authenticated ? "Connected" : "Not authenticated"
|
|
381
|
+
]
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
/* @__PURE__ */ jsxs2("span", { className: "text-text-secondary", children: [
|
|
385
|
+
"\xB7 ",
|
|
386
|
+
connector.description
|
|
387
|
+
] })
|
|
388
|
+
] }),
|
|
389
|
+
/* @__PURE__ */ jsx2("span", { className: "mt-2 inline-flex items-center rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium text-text-secondary", children: AUTH_TYPE_LABELS[connector.auth.type] ?? AUTH_TYPE_LABELS.none })
|
|
390
|
+
] }),
|
|
391
|
+
connector.auth.type === "dcr" && !connector.authenticated ? /* @__PURE__ */ jsx2(
|
|
392
|
+
Button,
|
|
393
|
+
{
|
|
394
|
+
variant: "outline",
|
|
395
|
+
size: "sm",
|
|
396
|
+
type: "button",
|
|
397
|
+
disabled: busy || connecting,
|
|
398
|
+
onClick: () => {
|
|
399
|
+
void handleAuthorize(connector.id, (isSuccess) => {
|
|
400
|
+
if (isSuccess) void refreshAfterAuthentication();
|
|
401
|
+
});
|
|
402
|
+
},
|
|
403
|
+
children: connecting ? "Connecting\u2026" : "Connect"
|
|
404
|
+
}
|
|
405
|
+
) : connector.auth.type === "dcr" && !connector.requiresAuth ? /* @__PURE__ */ jsx2(Button, { variant: "outline", size: "sm", type: "button", disabled: busy, onClick: onDisconnect, children: "Disconnect" }) : null
|
|
406
|
+
] }),
|
|
407
|
+
/* @__PURE__ */ jsx2("section", { className: "mt-6", "aria-labelledby": "connector-tools-heading", children: toolsLoading ? /* @__PURE__ */ jsx2("div", { className: "rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary", children: "Loading tools\u2026" }) : toolsError ? /* @__PURE__ */ jsxs2("div", { className: "rounded-xl border border-failure-bg/30 bg-failure-bg/10 p-6 text-center text-sm text-failure-bg", children: [
|
|
408
|
+
toolsError,
|
|
409
|
+
connector.auth.type === "dcr" && !connector.authenticated && /* @__PURE__ */ jsx2("div", { className: "font-bold mt-1", children: "Click Connect and authenticate successfully to view tools." })
|
|
410
|
+
] }) : tools.length > 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
411
|
+
/* @__PURE__ */ jsxs2("h5", { id: "connector-tools-heading", className: "mb-2 text-[0.8125rem] font-semibold text-text-primary", children: [
|
|
412
|
+
"Tools ",
|
|
413
|
+
/* @__PURE__ */ jsxs2("span", { className: "font-normal text-text-secondary", children: [
|
|
414
|
+
"\xB7 ",
|
|
415
|
+
tools.length
|
|
416
|
+
] })
|
|
417
|
+
] }),
|
|
418
|
+
/* @__PURE__ */ jsx2("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: tools.map((tool) => /* @__PURE__ */ jsx2(
|
|
419
|
+
"article",
|
|
420
|
+
{
|
|
421
|
+
className: "flex min-h-12 items-start gap-3 border-b border-border px-3 py-2 last:border-b-0",
|
|
422
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
|
|
423
|
+
/* @__PURE__ */ jsx2("h6", { className: "text-sm font-medium text-text-primary", children: tool.name }),
|
|
424
|
+
/* @__PURE__ */ jsx2(ExpandableDescription, { text: tool.description })
|
|
425
|
+
] })
|
|
426
|
+
},
|
|
427
|
+
tool.id
|
|
428
|
+
)) })
|
|
429
|
+
] }) : /* @__PURE__ */ jsx2("div", { className: "rounded-xl border border-dashed border-border p-6 text-center text-sm text-text-secondary", children: "No tools reported for this connector." }) })
|
|
430
|
+
] })
|
|
431
|
+
] });
|
|
432
|
+
};
|
|
433
|
+
var ConnectorDetails_default = ConnectorDetails;
|
|
434
|
+
|
|
435
|
+
// src/containers/SettingsBuilder/ConnectorSettings.tsx
|
|
436
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
437
|
+
var ConnectorSettings = () => {
|
|
438
|
+
const { connectorCatalog } = useCatalogServer();
|
|
439
|
+
const toaster = useToasterOptional();
|
|
440
|
+
const [query, setQuery] = useState3("");
|
|
441
|
+
const [connectors, setConnectors] = useState3({
|
|
442
|
+
ordered: [],
|
|
443
|
+
authStatusById: /* @__PURE__ */ new Map()
|
|
444
|
+
});
|
|
445
|
+
const [loading, setLoading] = useState3(true);
|
|
446
|
+
const [error, setError] = useState3(null);
|
|
447
|
+
const [formError, setFormError] = useState3(null);
|
|
448
|
+
const [busy, setBusy] = useState3(false);
|
|
449
|
+
const [catalog, setCatalog] = useState3([]);
|
|
450
|
+
const [addMcpServerFormOpen, setAddMcpServerFormOpen] = useState3(false);
|
|
451
|
+
const [connectorAwaitingKey, setConnectorAwaitingKey] = useState3(null);
|
|
452
|
+
const [selectedConnector, setSelectedConnector] = useState3(null);
|
|
453
|
+
const [apiKey, setApiKey] = useState3("");
|
|
454
|
+
const connectorIconMap = useMemo(() => {
|
|
455
|
+
return (catalog ?? []).reduce(
|
|
456
|
+
(acc, entry) => {
|
|
457
|
+
acc[entry.name] = entry.logo ?? "";
|
|
458
|
+
return acc;
|
|
459
|
+
},
|
|
460
|
+
{}
|
|
461
|
+
);
|
|
462
|
+
}, [catalog]);
|
|
463
|
+
const refresh = useCallback(async () => {
|
|
464
|
+
setLoading(true);
|
|
465
|
+
setError(null);
|
|
466
|
+
try {
|
|
467
|
+
const [listed, available] = await Promise.all([
|
|
468
|
+
connectorCatalog.listConnectors(),
|
|
469
|
+
connectorCatalog.getConnectorCatalog()
|
|
470
|
+
]);
|
|
471
|
+
setCatalog(available);
|
|
472
|
+
const configured = listed ?? [];
|
|
473
|
+
const seenIds = new Set(configured.map((connector) => connector.id));
|
|
474
|
+
const ordered = [
|
|
475
|
+
...configured.map((connector) => ({ connector, isConfigured: true })),
|
|
476
|
+
...available.filter((connector) => !seenIds.has(connector.id)).map((connector) => ({ connector, isConfigured: false }))
|
|
477
|
+
];
|
|
478
|
+
setConnectors({
|
|
479
|
+
ordered,
|
|
480
|
+
authStatusById: new Map(
|
|
481
|
+
ordered.map((item) => [item.connector.id, item.isConfigured ? item.connector.authenticated : false])
|
|
482
|
+
)
|
|
483
|
+
});
|
|
484
|
+
setSelectedConnector((current) => current ? listed.find((item) => item.id === current.id) ?? null : null);
|
|
485
|
+
} catch (err) {
|
|
486
|
+
setError(getErrorMessage(err, "Failed to load connectors"));
|
|
487
|
+
} finally {
|
|
488
|
+
setLoading(false);
|
|
489
|
+
}
|
|
490
|
+
}, [connectorCatalog]);
|
|
491
|
+
useEffect2(() => {
|
|
492
|
+
void refresh();
|
|
493
|
+
}, [refresh]);
|
|
494
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
495
|
+
const matchingConnectors = useMemo(() => {
|
|
496
|
+
if (!normalizedQuery) return connectors.ordered;
|
|
497
|
+
return connectors.ordered.filter(({ connector }) => {
|
|
498
|
+
return connector.name.toLowerCase().includes(normalizedQuery) || (connector.description?.toLowerCase().includes(normalizedQuery) ?? false) || connector.url.toLowerCase().includes(normalizedQuery);
|
|
499
|
+
});
|
|
500
|
+
}, [connectors.ordered, normalizedQuery]);
|
|
501
|
+
const matchingConnected = useMemo(() => {
|
|
502
|
+
const result = [];
|
|
503
|
+
for (const item of matchingConnectors) {
|
|
504
|
+
if (item.isConfigured) {
|
|
505
|
+
const authenticated = connectors.authStatusById.get(item.connector.id) ?? item.connector.authenticated;
|
|
506
|
+
result.push(
|
|
507
|
+
authenticated === item.connector.authenticated ? item.connector : { ...item.connector, authenticated }
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return result;
|
|
512
|
+
}, [connectors.authStatusById, matchingConnectors]);
|
|
513
|
+
const availableConnectors = useMemo(() => {
|
|
514
|
+
const result = [];
|
|
515
|
+
for (const item of matchingConnectors) {
|
|
516
|
+
if (!item.isConfigured) result.push(item.connector);
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
519
|
+
}, [matchingConnectors]);
|
|
520
|
+
const runMutation = async (fn, setMutationError = setError) => {
|
|
521
|
+
setBusy(true);
|
|
522
|
+
setError(null);
|
|
523
|
+
try {
|
|
524
|
+
await fn();
|
|
525
|
+
await refresh();
|
|
526
|
+
} catch (err) {
|
|
527
|
+
setMutationError(getErrorMessage(err, "Request failed"));
|
|
528
|
+
throw err;
|
|
529
|
+
} finally {
|
|
530
|
+
setBusy(false);
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const closeApiKeyModal = () => {
|
|
534
|
+
setConnectorAwaitingKey(null);
|
|
535
|
+
setApiKey("");
|
|
536
|
+
setFormError(null);
|
|
537
|
+
};
|
|
538
|
+
const createFromCatalog = async (entry, authOverride) => {
|
|
539
|
+
const auth = authOverride ?? (entry.auth.type === "header" ? {
|
|
540
|
+
type: "header",
|
|
541
|
+
...entry.auth.headerName ? { headerName: entry.auth.headerName } : {}
|
|
542
|
+
} : entry.auth.type === "dcr" ? { type: "dcr" } : { type: "none" });
|
|
543
|
+
await connectorCatalog.createConnector({
|
|
544
|
+
name: entry.name,
|
|
545
|
+
url: entry.url,
|
|
546
|
+
auth
|
|
547
|
+
});
|
|
548
|
+
};
|
|
549
|
+
const handleConnect = (entry) => {
|
|
550
|
+
if (entry.auth.type === "header") {
|
|
551
|
+
setApiKey("");
|
|
552
|
+
setFormError(null);
|
|
553
|
+
setConnectorAwaitingKey(entry);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
void runMutation(async () => {
|
|
557
|
+
await createFromCatalog(entry);
|
|
558
|
+
}).catch(() => {
|
|
559
|
+
});
|
|
560
|
+
};
|
|
561
|
+
const handleApiKeySubmit = (event) => {
|
|
562
|
+
event.preventDefault();
|
|
563
|
+
if (!connectorAwaitingKey || !apiKey.trim()) return;
|
|
564
|
+
const entry = connectorAwaitingKey;
|
|
565
|
+
setFormError(null);
|
|
566
|
+
void runMutation(async () => {
|
|
567
|
+
const auth = {
|
|
568
|
+
type: "header",
|
|
569
|
+
apiKey: apiKey.trim(),
|
|
570
|
+
...entry.auth.type === "header" && entry.auth.headerName ? { headerName: entry.auth.headerName } : {}
|
|
571
|
+
};
|
|
572
|
+
const existing = connectors.ordered.find(({ connector }) => connector.id === entry.id);
|
|
573
|
+
const existingConnector = existing?.isConfigured ? existing.connector : void 0;
|
|
574
|
+
if (existingConnector) {
|
|
575
|
+
await connectorCatalog.updateConnector({
|
|
576
|
+
id: existingConnector.id,
|
|
577
|
+
name: existingConnector.name,
|
|
578
|
+
url: existingConnector.url,
|
|
579
|
+
auth
|
|
580
|
+
});
|
|
581
|
+
} else {
|
|
582
|
+
await createFromCatalog(entry, auth);
|
|
583
|
+
}
|
|
584
|
+
closeApiKeyModal();
|
|
585
|
+
setTimeout(() => {
|
|
586
|
+
toaster?.showSuccess({ title: `${entry.name} ${existingConnector ? "updated" : "connected"}` });
|
|
587
|
+
}, 100);
|
|
588
|
+
}, setFormError).catch(() => {
|
|
589
|
+
});
|
|
590
|
+
};
|
|
591
|
+
const handleAddMcpServer = async (draft) => {
|
|
592
|
+
setFormError(null);
|
|
593
|
+
await runMutation(async () => {
|
|
594
|
+
await connectorCatalog.createConnector({
|
|
595
|
+
name: draft.name,
|
|
596
|
+
url: draft.url,
|
|
597
|
+
auth: draft.auth
|
|
598
|
+
});
|
|
599
|
+
}, setFormError);
|
|
600
|
+
setTimeout(() => {
|
|
601
|
+
toaster?.showSuccess({ title: `${draft.name} added` });
|
|
602
|
+
}, 0);
|
|
603
|
+
};
|
|
604
|
+
const handleDisconnect = (connector) => {
|
|
605
|
+
void runMutation(async () => {
|
|
606
|
+
await connectorCatalog.disconnectConnector({ id: connector.id });
|
|
607
|
+
setSelectedConnector(null);
|
|
608
|
+
}).catch(() => {
|
|
609
|
+
});
|
|
610
|
+
};
|
|
611
|
+
const handleConnectorRefreshed = (refreshedConnector) => {
|
|
612
|
+
setSelectedConnector((current) => current?.id === refreshedConnector.id ? refreshedConnector : current);
|
|
613
|
+
setConnectors((current) => {
|
|
614
|
+
const authStatusById = new Map(current.authStatusById);
|
|
615
|
+
authStatusById.set(refreshedConnector.id, refreshedConnector.authenticated);
|
|
616
|
+
return {
|
|
617
|
+
ordered: current.ordered.map(
|
|
618
|
+
(item) => item.isConfigured && item.connector.id === refreshedConnector.id ? { connector: refreshedConnector, isConfigured: true } : item
|
|
619
|
+
),
|
|
620
|
+
authStatusById
|
|
621
|
+
};
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
const renderConnector = (connector, isConnected) => {
|
|
625
|
+
const logoSrc = connectorIconMap[connector.name];
|
|
626
|
+
const content = /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
627
|
+
/* @__PURE__ */ jsx3(
|
|
628
|
+
"span",
|
|
629
|
+
{
|
|
630
|
+
className: "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg",
|
|
631
|
+
"aria-hidden": true,
|
|
632
|
+
children: logoSrc ? /* @__PURE__ */ jsx3(CatalogLogo, { src: logoSrc, alt: connector.name, className: "size-4.5" }) : /* @__PURE__ */ jsx3(Icon, { name: "mcp-server", className: "size-4.5 text-text-primary" })
|
|
633
|
+
}
|
|
634
|
+
),
|
|
635
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
636
|
+
/* @__PURE__ */ jsx3("h5", { className: "truncate text-sm font-medium text-text-primary", children: connector.name }),
|
|
637
|
+
/* @__PURE__ */ jsx3("p", { className: "mt-0.5 line-clamp-2 text-sm text-text-secondary sm:truncate", children: connector.description })
|
|
638
|
+
] })
|
|
639
|
+
] });
|
|
640
|
+
const rowClassName = "flex min-h-16 w-full items-center gap-3 border-b border-border p-3 text-left last:border-b-0";
|
|
641
|
+
if (isConnected) {
|
|
642
|
+
return /* @__PURE__ */ jsxs3(
|
|
643
|
+
"article",
|
|
644
|
+
{
|
|
645
|
+
className: `${rowClassName} cursor-pointer transition-colors hover:bg-ghost-button-hover/60`,
|
|
646
|
+
onClick: () => {
|
|
647
|
+
setSelectedConnector(connector);
|
|
648
|
+
},
|
|
649
|
+
children: [
|
|
650
|
+
/* @__PURE__ */ jsx3("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: content }),
|
|
651
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
|
|
652
|
+
/* @__PURE__ */ jsx3("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs3(
|
|
653
|
+
"span",
|
|
654
|
+
{
|
|
655
|
+
className: cn(
|
|
656
|
+
"flex items-center gap-1.5 rounded-full border border-border bg-secondary-bg/40 px-2 py-0.5 text-xs font-medium",
|
|
657
|
+
connector.authenticated ? "text-success-bg" : "text-text-primary"
|
|
658
|
+
),
|
|
659
|
+
children: [
|
|
660
|
+
/* @__PURE__ */ jsx3(
|
|
661
|
+
"span",
|
|
662
|
+
{
|
|
663
|
+
className: cn(
|
|
664
|
+
"h-1.5 w-1.5 rounded-full",
|
|
665
|
+
connector.authenticated ? "bg-success-bg" : "bg-primary-button-bg"
|
|
666
|
+
)
|
|
667
|
+
}
|
|
668
|
+
),
|
|
669
|
+
connector.authenticated ? "Connected" : "Added"
|
|
670
|
+
]
|
|
671
|
+
}
|
|
672
|
+
) }),
|
|
673
|
+
connector.auth.type === "header" ? /* @__PURE__ */ jsxs3(
|
|
674
|
+
Button,
|
|
675
|
+
{
|
|
676
|
+
variant: "secondary",
|
|
677
|
+
size: "sm",
|
|
678
|
+
type: "button",
|
|
679
|
+
disabled: busy,
|
|
680
|
+
onClick: (event) => {
|
|
681
|
+
event.stopPropagation();
|
|
682
|
+
setApiKey("");
|
|
683
|
+
setConnectorAwaitingKey(connector);
|
|
684
|
+
},
|
|
685
|
+
children: [
|
|
686
|
+
/* @__PURE__ */ jsx3(Icon, { name: "wrench", className: "size-3" }),
|
|
687
|
+
"Replace Key"
|
|
688
|
+
]
|
|
689
|
+
}
|
|
690
|
+
) : null,
|
|
691
|
+
/* @__PURE__ */ jsx3(Icon, { name: "chevron-right", className: "size-4" })
|
|
692
|
+
] })
|
|
693
|
+
]
|
|
694
|
+
},
|
|
695
|
+
connector.id
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
return /* @__PURE__ */ jsx3("article", { className: rowClassName, children: content }, connector.id);
|
|
699
|
+
};
|
|
700
|
+
const renderCatalogEntry = (entry) => {
|
|
701
|
+
const logoSrc = connectorIconMap[entry.name];
|
|
702
|
+
return /* @__PURE__ */ jsxs3(
|
|
703
|
+
"article",
|
|
704
|
+
{
|
|
705
|
+
className: "flex min-h-16 w-full items-center gap-3 border-b border-border p-3 text-left last:border-b-0",
|
|
706
|
+
children: [
|
|
707
|
+
/* @__PURE__ */ jsx3(
|
|
708
|
+
"span",
|
|
709
|
+
{
|
|
710
|
+
className: "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-border bg-secondary-bg",
|
|
711
|
+
"aria-hidden": true,
|
|
712
|
+
children: logoSrc ? /* @__PURE__ */ jsx3(CatalogLogo, { src: logoSrc, alt: entry.name, className: "size-4.5" }) : /* @__PURE__ */ jsx3(Icon, { name: "mcp-server", className: "size-4.5 text-text-primary" })
|
|
713
|
+
}
|
|
714
|
+
),
|
|
715
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
716
|
+
/* @__PURE__ */ jsx3("h5", { className: "truncate text-sm font-medium text-text-primary", children: entry.name }),
|
|
717
|
+
/* @__PURE__ */ jsx3("p", { className: "mt-0.5 line-clamp-2 text-sm text-text-secondary sm:truncate", children: entry.description ?? entry.url })
|
|
718
|
+
] }),
|
|
719
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
720
|
+
/* @__PURE__ */ jsx3("span", { className: "hidden text-xs text-text-secondary sm:inline", children: AUTH_TYPE_LABELS[entry.auth.type] ?? AUTH_TYPE_LABELS.none }),
|
|
721
|
+
/* @__PURE__ */ jsx3(
|
|
722
|
+
Button,
|
|
723
|
+
{
|
|
724
|
+
variant: "secondary",
|
|
725
|
+
size: "sm",
|
|
726
|
+
type: "button",
|
|
727
|
+
disabled: busy,
|
|
728
|
+
onClick: () => {
|
|
729
|
+
handleConnect(entry);
|
|
730
|
+
},
|
|
731
|
+
children: entry.auth.type === "dcr" ? "Add" : "Connect"
|
|
732
|
+
}
|
|
733
|
+
)
|
|
734
|
+
] })
|
|
735
|
+
]
|
|
736
|
+
},
|
|
737
|
+
entry.id
|
|
738
|
+
);
|
|
739
|
+
};
|
|
740
|
+
const isReplacingKey = useMemo(() => {
|
|
741
|
+
return connectorAwaitingKey !== null && connectors.ordered.some(
|
|
742
|
+
(item) => item.isConfigured && item.connector.id === connectorAwaitingKey.id
|
|
743
|
+
);
|
|
744
|
+
}, [connectorAwaitingKey, connectors.ordered]);
|
|
745
|
+
if (selectedConnector) {
|
|
746
|
+
return /* @__PURE__ */ jsx3(
|
|
747
|
+
ConnectorDetails_default,
|
|
748
|
+
{
|
|
749
|
+
connector: selectedConnector,
|
|
750
|
+
busy,
|
|
751
|
+
onBack: () => {
|
|
752
|
+
setSelectedConnector(null);
|
|
753
|
+
},
|
|
754
|
+
onConnectorRefreshed: handleConnectorRefreshed,
|
|
755
|
+
onDisconnect: () => {
|
|
756
|
+
handleDisconnect(selectedConnector);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
const hasMatches = matchingConnected.length > 0 || availableConnectors.length > 0;
|
|
762
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
763
|
+
/* @__PURE__ */ jsx3("h3", { className: "text-xl font-semibold tracking-tight text-text-primary", children: "Connectors" }),
|
|
764
|
+
/* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-text-secondary", children: "Connect tools your agents can use." }),
|
|
765
|
+
error ? /* @__PURE__ */ jsx3("p", { className: "mt-3 rounded-md border border-failure-bg/30 bg-failure-bg/10 px-3 py-2 text-sm text-failure-bg", children: error }) : null,
|
|
766
|
+
/* @__PURE__ */ jsx3("div", { className: "mt-4 flex-1 overflow-y-hidden", children: /* @__PURE__ */ jsxs3("div", { className: "flex h-full flex-col gap-3", children: [
|
|
767
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-2", children: [
|
|
768
|
+
/* @__PURE__ */ jsx3("div", { className: "flex-1", children: /* @__PURE__ */ jsx3(SearchInput_default, { query, setQuery, placeholder: "Search connectors" }) }),
|
|
769
|
+
/* @__PURE__ */ jsxs3(
|
|
770
|
+
Button,
|
|
771
|
+
{
|
|
772
|
+
variant: "secondary",
|
|
773
|
+
type: "button",
|
|
774
|
+
onClick: () => {
|
|
775
|
+
setFormError(null);
|
|
776
|
+
setAddMcpServerFormOpen(true);
|
|
777
|
+
},
|
|
778
|
+
children: [
|
|
779
|
+
/* @__PURE__ */ jsx3(Icon, { name: "plus", size: "1rem", className: "mr-1" }),
|
|
780
|
+
"Add MCP Server"
|
|
781
|
+
]
|
|
782
|
+
}
|
|
783
|
+
)
|
|
784
|
+
] }),
|
|
785
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-1 flex-col gap-5 overflow-y-auto pb-1", children: [
|
|
786
|
+
loading ? /* @__PURE__ */ jsx3("p", { className: "py-8 text-center text-sm text-text-secondary", children: "Loading\u2026" }) : null,
|
|
787
|
+
!loading && matchingConnected.length > 0 ? /* @__PURE__ */ jsxs3("section", { "aria-labelledby": "connected-connectors-heading", children: [
|
|
788
|
+
/* @__PURE__ */ jsxs3(
|
|
789
|
+
"h4",
|
|
790
|
+
{
|
|
791
|
+
id: "connected-connectors-heading",
|
|
792
|
+
className: "mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary",
|
|
793
|
+
children: [
|
|
794
|
+
"Configured \xB7 ",
|
|
795
|
+
matchingConnected.length
|
|
796
|
+
]
|
|
797
|
+
}
|
|
798
|
+
),
|
|
799
|
+
/* @__PURE__ */ jsx3("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: matchingConnected.map((connector) => renderConnector(connector, true)) })
|
|
800
|
+
] }) : null,
|
|
801
|
+
!loading && availableConnectors.length > 0 ? /* @__PURE__ */ jsxs3("section", { "aria-labelledby": "available-connectors-heading", children: [
|
|
802
|
+
/* @__PURE__ */ jsxs3(
|
|
803
|
+
"h4",
|
|
804
|
+
{
|
|
805
|
+
id: "available-connectors-heading",
|
|
806
|
+
className: "mb-2 text-[0.8125rem] font-semibold uppercase text-text-secondary",
|
|
807
|
+
children: [
|
|
808
|
+
"Available \xB7 ",
|
|
809
|
+
availableConnectors.length
|
|
810
|
+
]
|
|
811
|
+
}
|
|
812
|
+
),
|
|
813
|
+
/* @__PURE__ */ jsx3("div", { className: "overflow-hidden rounded-xl border border-border bg-card-bg", children: availableConnectors.map((entry) => renderCatalogEntry(entry)) })
|
|
814
|
+
] }) : null,
|
|
815
|
+
!loading && !hasMatches ? /* @__PURE__ */ jsx3("div", { className: "flex flex-1 items-center justify-center rounded-xl border border-dashed border-border p-8 text-center text-sm text-text-secondary", children: query.trim() ? `No connectors match \u201C${query.trim()}\u201D.` : "No connectors yet." }) : null
|
|
816
|
+
] }),
|
|
817
|
+
/* @__PURE__ */ jsx3(
|
|
818
|
+
CenteredModal,
|
|
819
|
+
{
|
|
820
|
+
open: connectorAwaitingKey !== null,
|
|
821
|
+
onOpenChange: (open) => {
|
|
822
|
+
if (!open) closeApiKeyModal();
|
|
823
|
+
},
|
|
824
|
+
title: `${isReplacingKey ? "Replace key for" : "Connect"} ${connectorAwaitingKey?.name ?? "connector"}`,
|
|
825
|
+
description: connectorAwaitingKey?.url,
|
|
826
|
+
contentSized: true,
|
|
827
|
+
className: "md:max-w-xl",
|
|
828
|
+
children: /* @__PURE__ */ jsxs3("form", { onSubmit: handleApiKeySubmit, children: [
|
|
829
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-5 px-5 py-5", children: [
|
|
830
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
|
|
831
|
+
/* @__PURE__ */ jsx3(
|
|
832
|
+
"span",
|
|
833
|
+
{
|
|
834
|
+
className: "flex size-12 shrink-0 items-center justify-center overflow-hidden rounded-xl border border-border bg-secondary-bg",
|
|
835
|
+
"aria-hidden": true,
|
|
836
|
+
children: /* @__PURE__ */ jsx3(Icon, { name: "mcp-server", className: "size-6 text-text-primary" })
|
|
837
|
+
}
|
|
838
|
+
),
|
|
839
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
840
|
+
/* @__PURE__ */ jsx3("p", { className: "font-medium text-text-primary", children: connectorAwaitingKey?.name }),
|
|
841
|
+
/* @__PURE__ */ jsx3("p", { className: "truncate text-sm text-text-secondary", children: connectorAwaitingKey?.description })
|
|
842
|
+
] })
|
|
843
|
+
] }),
|
|
844
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
845
|
+
/* @__PURE__ */ jsx3(
|
|
846
|
+
"label",
|
|
847
|
+
{
|
|
848
|
+
htmlFor: "connector-api-key",
|
|
849
|
+
className: "mb-2 block text-xs font-semibold uppercase tracking-wide text-text-secondary",
|
|
850
|
+
children: "API key / token"
|
|
851
|
+
}
|
|
852
|
+
),
|
|
853
|
+
/* @__PURE__ */ jsx3(
|
|
854
|
+
"input",
|
|
855
|
+
{
|
|
856
|
+
id: "connector-api-key",
|
|
857
|
+
type: "password",
|
|
858
|
+
value: apiKey,
|
|
859
|
+
onChange: (event) => {
|
|
860
|
+
setApiKey(event.target.value);
|
|
861
|
+
},
|
|
862
|
+
placeholder: `Paste the token from ${connectorAwaitingKey?.name ?? "the provider"}`,
|
|
863
|
+
autoFocus: true,
|
|
864
|
+
required: true,
|
|
865
|
+
className: auiInputClass("h-11")
|
|
866
|
+
}
|
|
867
|
+
)
|
|
868
|
+
] }),
|
|
869
|
+
formError ? /* @__PURE__ */ jsx3("p", { className: "text-failure-bg text-sm", children: formError }) : null
|
|
870
|
+
] }),
|
|
871
|
+
/* @__PURE__ */ jsxs3("footer", { className: "flex justify-end gap-2 border-t border-border px-5 py-4", children: [
|
|
872
|
+
/* @__PURE__ */ jsx3(Button, { variant: "ghost", type: "button", onClick: closeApiKeyModal, disabled: busy, children: "Cancel" }),
|
|
873
|
+
/* @__PURE__ */ jsx3(Button, { type: "submit", disabled: !apiKey.trim() || busy, children: isReplacingKey ? "Replace Key" : "Connect" })
|
|
874
|
+
] })
|
|
875
|
+
] })
|
|
876
|
+
}
|
|
877
|
+
),
|
|
878
|
+
/* @__PURE__ */ jsx3(
|
|
879
|
+
AddMcpServerForm_default,
|
|
880
|
+
{
|
|
881
|
+
open: addMcpServerFormOpen,
|
|
882
|
+
onOpenChange: (open) => {
|
|
883
|
+
setAddMcpServerFormOpen(open);
|
|
884
|
+
if (!open) setFormError(null);
|
|
885
|
+
},
|
|
886
|
+
onAdd: handleAddMcpServer,
|
|
887
|
+
busy,
|
|
888
|
+
error: formError
|
|
889
|
+
}
|
|
890
|
+
)
|
|
891
|
+
] }) })
|
|
892
|
+
] });
|
|
893
|
+
};
|
|
894
|
+
var ConnectorSettings_default = ConnectorSettings;
|
|
895
|
+
export {
|
|
896
|
+
ConnectorSettings_default as default
|
|
897
|
+
};
|
|
898
|
+
//# sourceMappingURL=ConnectorSettings-CLBEWGQJ.js.map
|