@shuffleio/shuffle-mcps 0.0.31 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +496 -36
- package/dist/index.mjs +502 -39
- package/dist/{shuffle-mcp-ER33P3W2.css → shuffle-mcp-TWJGPBOQ.css} +16 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -422,7 +422,9 @@ __export(index_exports, {
|
|
|
422
422
|
deleteDatastoreItem: () => deleteDatastoreItem,
|
|
423
423
|
deleteDatastoreItems: () => deleteDatastoreItems,
|
|
424
424
|
diagnoseOutputWarning: () => diagnoseOutputWarning,
|
|
425
|
+
extractActionAppNames: () => extractActionAppNames,
|
|
425
426
|
extractValidatedIngestionApps: () => extractValidatedIngestionApps,
|
|
427
|
+
extractWorkflowActionAppNames: () => extractWorkflowActionAppNames,
|
|
426
428
|
extractWorkflowAppNames: () => extractWorkflowAppNames,
|
|
427
429
|
fetchApps: () => fetchApps,
|
|
428
430
|
fetchAppsViaApiConfig: () => fetchAppsViaApiConfig,
|
|
@@ -473,13 +475,13 @@ __export(index_exports, {
|
|
|
473
475
|
useSyncHostBaseUrl: () => useSyncHostBaseUrl
|
|
474
476
|
});
|
|
475
477
|
module.exports = __toCommonJS(index_exports);
|
|
476
|
-
var import_shuffle_mcp3 = require("./shuffle-mcp-
|
|
478
|
+
var import_shuffle_mcp3 = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
477
479
|
var import_react22 = __toESM(require("react"));
|
|
478
480
|
|
|
479
481
|
// ShuffleMcpThemeProvider.tsx
|
|
480
482
|
var import_react = __toESM(require("react"));
|
|
481
483
|
var import_material = require("@mui/material");
|
|
482
|
-
var import_shuffle_mcp = require("./shuffle-mcp-
|
|
484
|
+
var import_shuffle_mcp = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
483
485
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
484
486
|
var readHtmlDarkClass = () => {
|
|
485
487
|
if (typeof document === "undefined") return false;
|
|
@@ -1319,6 +1321,65 @@ var isIngestionApp = (appName) => {
|
|
|
1319
1321
|
return isEmailApp(appName) || CASES_PATTERNS.some((p) => name.includes(p)) || EDR_PATTERNS.some((p) => name.includes(p)) || SIEM_PATTERNS.some((p) => name.includes(p));
|
|
1320
1322
|
};
|
|
1321
1323
|
var normalizeAppName = (name) => name.toLowerCase().trim().replace(/[\s_\-]+/g, "_");
|
|
1324
|
+
var IGNORED_WORKFLOW_APP_NAMES = /* @__PURE__ */ new Set([
|
|
1325
|
+
"shuffle_tools",
|
|
1326
|
+
"singul",
|
|
1327
|
+
"integration",
|
|
1328
|
+
"ai_agent",
|
|
1329
|
+
"shuffle_agent",
|
|
1330
|
+
"shuffle_ai"
|
|
1331
|
+
]);
|
|
1332
|
+
var isIgnoredWorkflowAppName = (name) => IGNORED_WORKFLOW_APP_NAMES.has(normalizeAppName(name));
|
|
1333
|
+
var looksLikeOpaqueId = (raw) => {
|
|
1334
|
+
const trimmed = raw.trim();
|
|
1335
|
+
if (/^[a-f0-9]{16,}$/i.test(trimmed)) return true;
|
|
1336
|
+
if (/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(trimmed)) return true;
|
|
1337
|
+
return false;
|
|
1338
|
+
};
|
|
1339
|
+
var addWorkflowAppName = (names, seen, raw) => {
|
|
1340
|
+
if (typeof raw !== "string" || !raw.trim()) return;
|
|
1341
|
+
const parts = raw.includes(",") ? raw.split(",") : [raw];
|
|
1342
|
+
for (const part of parts) {
|
|
1343
|
+
const trimmed = part.trim();
|
|
1344
|
+
if (!trimmed) continue;
|
|
1345
|
+
const key = normalizeAppName(trimmed);
|
|
1346
|
+
if (!key || isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed) || seen.has(key)) continue;
|
|
1347
|
+
seen.add(key);
|
|
1348
|
+
names.push(trimmed);
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
var collectParameterAppNames = (input, names, seen, depth = 0) => {
|
|
1352
|
+
if (!input || depth > 4) return;
|
|
1353
|
+
if (Array.isArray(input)) {
|
|
1354
|
+
input.forEach((item) => collectParameterAppNames(item, names, seen, depth + 1));
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (typeof input !== "object") return;
|
|
1358
|
+
const obj = input;
|
|
1359
|
+
if (String(obj.name || "").toLowerCase() === "app_name") addWorkflowAppName(names, seen, obj.value);
|
|
1360
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1361
|
+
const lower = key.toLowerCase();
|
|
1362
|
+
if (lower === "app_name") addWorkflowAppName(names, seen, value);
|
|
1363
|
+
else if (lower === "parameters" || lower === "fields" || lower === "value") collectParameterAppNames(value, names, seen, depth + 1);
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
function extractActionAppNames(action) {
|
|
1367
|
+
const names = [];
|
|
1368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1369
|
+
collectParameterAppNames(action?.parameters, names, seen);
|
|
1370
|
+
addWorkflowAppName(names, seen, action?.app_name);
|
|
1371
|
+
addWorkflowAppName(names, seen, action?.app_id);
|
|
1372
|
+
return names;
|
|
1373
|
+
}
|
|
1374
|
+
function extractWorkflowActionAppNames(workflow) {
|
|
1375
|
+
const names = [];
|
|
1376
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1377
|
+
if (!workflow?.actions || !Array.isArray(workflow.actions)) return names;
|
|
1378
|
+
for (const action of workflow.actions) {
|
|
1379
|
+
for (const name of extractActionAppNames(action)) addWorkflowAppName(names, seen, name);
|
|
1380
|
+
}
|
|
1381
|
+
return names;
|
|
1382
|
+
}
|
|
1322
1383
|
var getIngestionCategory = (appName, appCategories) => {
|
|
1323
1384
|
const name = appName.toLowerCase();
|
|
1324
1385
|
const categories = (appCategories || []).map((c) => c.toLowerCase());
|
|
@@ -1332,20 +1393,14 @@ var INGEST_TICKETS_WORKFLOW_NAME = "Ingest Tickets";
|
|
|
1332
1393
|
var FORWARD_TICKETS_WORKFLOW_NAME = "Forward Tickets";
|
|
1333
1394
|
function extractWorkflowAppNames(workflow) {
|
|
1334
1395
|
const names = /* @__PURE__ */ new Set();
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
if (action.parameters) {
|
|
1344
|
-
for (const param of action.parameters) {
|
|
1345
|
-
if (param.name === "app_name" && param.value) {
|
|
1346
|
-
names.add(normalizeAppName(param.value));
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1396
|
+
for (const raw of extractWorkflowActionAppNames(workflow)) {
|
|
1397
|
+
const parts = typeof raw === "string" && raw.includes(",") ? raw.split(",") : [raw];
|
|
1398
|
+
for (const part of parts) {
|
|
1399
|
+
const trimmed = (part || "").trim();
|
|
1400
|
+
if (!trimmed) continue;
|
|
1401
|
+
if (isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed)) continue;
|
|
1402
|
+
const key = normalizeAppName(trimmed);
|
|
1403
|
+
if (key) names.add(key);
|
|
1349
1404
|
}
|
|
1350
1405
|
}
|
|
1351
1406
|
return names;
|
|
@@ -2060,6 +2115,7 @@ function AppTitleHeader({
|
|
|
2060
2115
|
isActivated = null,
|
|
2061
2116
|
activateLoading = false,
|
|
2062
2117
|
onActivateToggle,
|
|
2118
|
+
highlightActivate = false,
|
|
2063
2119
|
onAdd
|
|
2064
2120
|
}) {
|
|
2065
2121
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_framer_motion.motion.div, { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -2163,7 +2219,16 @@ function AppTitleHeader({
|
|
|
2163
2219
|
py: 0.5,
|
|
2164
2220
|
minHeight: 0,
|
|
2165
2221
|
flexShrink: 0,
|
|
2166
|
-
...isActivated ? { color: "hsl(var(--muted-foreground))", borderColor: "hsl(var(--border))", "&:hover": { borderColor: "hsl(var(--destructive))", color: "hsl(var(--destructive))", bgcolor: "hsla(var(--destructive) / 0.08)" } } : { bgcolor: "hsl(var(--primary))", "&:hover": { bgcolor: "hsl(var(--primary) / 0.85)" } }
|
|
2222
|
+
...isActivated ? { color: "hsl(var(--muted-foreground))", borderColor: "hsl(var(--border))", "&:hover": { borderColor: "hsl(var(--destructive))", color: "hsl(var(--destructive))", bgcolor: "hsla(var(--destructive) / 0.08)" } } : { bgcolor: "hsl(var(--primary))", "&:hover": { bgcolor: "hsl(var(--primary) / 0.85)" } },
|
|
2223
|
+
...highlightActivate ? {
|
|
2224
|
+
boxShadow: "0 0 0 0 hsla(var(--primary) / 0.6)",
|
|
2225
|
+
animation: "appTitleActivatePulse 1.1s ease-out infinite",
|
|
2226
|
+
"@keyframes appTitleActivatePulse": {
|
|
2227
|
+
"0%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0.55)" },
|
|
2228
|
+
"70%": { boxShadow: "0 0 0 10px hsla(var(--primary) / 0)" },
|
|
2229
|
+
"100%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0)" }
|
|
2230
|
+
}
|
|
2231
|
+
} : {}
|
|
2167
2232
|
},
|
|
2168
2233
|
children: activateLoading ? "\u2026" : isActivated ? "Deactivate" : "Activate"
|
|
2169
2234
|
}
|
|
@@ -5706,6 +5771,7 @@ function AppDetailDrawer({
|
|
|
5706
5771
|
onAddToCanvas,
|
|
5707
5772
|
isAuthenticated = true,
|
|
5708
5773
|
activeOrgId,
|
|
5774
|
+
autoActivate = false,
|
|
5709
5775
|
globalUrl,
|
|
5710
5776
|
userdata,
|
|
5711
5777
|
isLoaded,
|
|
@@ -5903,8 +5969,9 @@ function AppDetailDrawer({
|
|
|
5903
5969
|
(0, import_react11.useEffect)(() => {
|
|
5904
5970
|
lastValidAuthRef.current = null;
|
|
5905
5971
|
}, [appName]);
|
|
5906
|
-
const handleActivateToggle = async () => {
|
|
5972
|
+
const handleActivateToggle = async (opts) => {
|
|
5907
5973
|
if (!appName || activateLoading) return;
|
|
5974
|
+
const silent = !!opts?.silent;
|
|
5908
5975
|
const wasActivated = isActivated;
|
|
5909
5976
|
const prevAppId = activatedAppId;
|
|
5910
5977
|
setIsActivated(!wasActivated);
|
|
@@ -5918,7 +5985,7 @@ function AppDetailDrawer({
|
|
|
5918
5985
|
});
|
|
5919
5986
|
if (!res.ok) throw new Error("Deactivate failed");
|
|
5920
5987
|
setActivatedAppId(null);
|
|
5921
|
-
toast.success(`${displayName} deactivated`);
|
|
5988
|
+
if (!silent) toast.success(`${displayName} deactivated`);
|
|
5922
5989
|
} else {
|
|
5923
5990
|
const appId2 = resolvedAlgoliaId;
|
|
5924
5991
|
if (!appId2) throw new Error("App ID not resolved yet");
|
|
@@ -5929,17 +5996,38 @@ function AppDetailDrawer({
|
|
|
5929
5996
|
});
|
|
5930
5997
|
if (!activateRes.ok) throw new Error(`Activate failed (${activateRes.status})`);
|
|
5931
5998
|
setActivatedAppId(appId2);
|
|
5932
|
-
toast.success(`${displayName} activated`);
|
|
5999
|
+
if (!silent) toast.success(`${displayName} activated`);
|
|
5933
6000
|
}
|
|
5934
6001
|
} catch (err) {
|
|
5935
6002
|
console.error("[Activate] Error:", err);
|
|
5936
|
-
toast.error(err?.message || "Activation failed");
|
|
6003
|
+
if (!silent) toast.error(err?.message || "Activation failed");
|
|
5937
6004
|
setIsActivated(wasActivated);
|
|
5938
6005
|
setActivatedAppId(prevAppId);
|
|
5939
6006
|
} finally {
|
|
5940
6007
|
setActivateLoading(false);
|
|
5941
6008
|
}
|
|
5942
6009
|
};
|
|
6010
|
+
const autoActivateFiredRef = (0, import_react11.useRef)(null);
|
|
6011
|
+
const [autoActivatePulse, setAutoActivatePulse] = (0, import_react11.useState)(false);
|
|
6012
|
+
(0, import_react11.useEffect)(() => {
|
|
6013
|
+
if (!open || !autoActivate || !appName) return;
|
|
6014
|
+
const key = `${appName}`;
|
|
6015
|
+
if (autoActivateFiredRef.current === key) return;
|
|
6016
|
+
if (isActivated !== false) return;
|
|
6017
|
+
if (!resolvedAlgoliaId) return;
|
|
6018
|
+
if (activateLoading) return;
|
|
6019
|
+
autoActivateFiredRef.current = key;
|
|
6020
|
+
setAutoActivatePulse(true);
|
|
6021
|
+
handleActivateToggle({ silent: true }).finally(() => {
|
|
6022
|
+
setTimeout(() => setAutoActivatePulse(false), 1200);
|
|
6023
|
+
});
|
|
6024
|
+
}, [open, autoActivate, appName, isActivated, resolvedAlgoliaId, activateLoading]);
|
|
6025
|
+
(0, import_react11.useEffect)(() => {
|
|
6026
|
+
if (!open) {
|
|
6027
|
+
autoActivateFiredRef.current = null;
|
|
6028
|
+
setAutoActivatePulse(false);
|
|
6029
|
+
}
|
|
6030
|
+
}, [open, appName]);
|
|
5943
6031
|
const isLoadingAll = appLoading || isAuthenticated && appAuthLoading;
|
|
5944
6032
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
5945
6033
|
import_material9.Drawer,
|
|
@@ -6015,7 +6103,8 @@ function AppDetailDrawer({
|
|
|
6015
6103
|
categories: appInfo?.categories,
|
|
6016
6104
|
isActivated: onAddToCanvas ? null : effectiveActivated,
|
|
6017
6105
|
activateLoading,
|
|
6018
|
-
onActivateToggle: handleActivateToggle,
|
|
6106
|
+
onActivateToggle: () => handleActivateToggle(),
|
|
6107
|
+
highlightActivate: autoActivatePulse,
|
|
6019
6108
|
onAdd: onAddToCanvas && appName ? () => {
|
|
6020
6109
|
onAddToCanvas({ name: appName, icon: resolvedImage || "", algoliaId: resolvedAlgoliaId });
|
|
6021
6110
|
onClose();
|
|
@@ -6119,7 +6208,7 @@ function AppDetailDrawer({
|
|
|
6119
6208
|
}
|
|
6120
6209
|
|
|
6121
6210
|
// views/ShuffleMCP.tsx
|
|
6122
|
-
var import_shuffle_mcp2 = require("./shuffle-mcp-
|
|
6211
|
+
var import_shuffle_mcp2 = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
6123
6212
|
init_appsCache();
|
|
6124
6213
|
|
|
6125
6214
|
// components/SegmentedControl.tsx
|
|
@@ -6287,7 +6376,7 @@ function SegmentedControl({
|
|
|
6287
6376
|
children: opt.label
|
|
6288
6377
|
}
|
|
6289
6378
|
),
|
|
6290
|
-
!isAction && typeof opt.count === "number" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6379
|
+
!isAction && (typeof opt.count === "number" || typeof opt.count === "string") && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6291
6380
|
"span",
|
|
6292
6381
|
{
|
|
6293
6382
|
style: {
|
|
@@ -6786,8 +6875,8 @@ var ShuffleMCP = import_react12.default.forwardRef(({
|
|
|
6786
6875
|
value: sourceFilter,
|
|
6787
6876
|
onChange: (v) => setSourceFilter(v),
|
|
6788
6877
|
options: [
|
|
6789
|
-
{ value: "all", label: "All", count: results.length + filteredPrivateApps.length, title: "All available apps \u2014 both the public catalog and your private apps." },
|
|
6790
|
-
{ value: "public", label: "Public", count: results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6878
|
+
{ value: "all", label: "All", count: results.length >= hitsPerPage ? `${results.length + filteredPrivateApps.length}+` : results.length + filteredPrivateApps.length, title: "All available apps \u2014 both the public catalog and your private apps." },
|
|
6879
|
+
{ value: "public", label: "Public", count: results.length >= hitsPerPage ? `${results.length}+` : results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6791
6880
|
{ value: "private", label: "Private", count: filteredPrivateApps.length, title: "Private apps are apps you have activated in your organization, or your own custom apps \u2014 not just from the public Algolia catalog." },
|
|
6792
6881
|
{ value: "authenticated", label: "Authenticated", count: [...filteredPrivateApps, ...results].filter((a, i, arr) => arr.findIndex((x) => x.name?.toLowerCase() === a.name?.toLowerCase()) === i).filter(isAppConfigured).length, title: "Apps you have authenticated and that are ready to use." }
|
|
6793
6882
|
]
|
|
@@ -6963,9 +7052,11 @@ function AppSearchDrawer({
|
|
|
6963
7052
|
pinnedApps,
|
|
6964
7053
|
highlightAppName,
|
|
6965
7054
|
highlightDelayMs = 5e3,
|
|
7055
|
+
realtimeHighlightAppNames,
|
|
6966
7056
|
multiSelect = false,
|
|
6967
7057
|
selectedApps,
|
|
6968
7058
|
onSelectionChange,
|
|
7059
|
+
autoActivate = false,
|
|
6969
7060
|
globalUrl,
|
|
6970
7061
|
theme,
|
|
6971
7062
|
colorMode
|
|
@@ -7224,6 +7315,41 @@ function AppSearchDrawer({
|
|
|
7224
7315
|
"0%, 100%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 12px 1px hsl(var(--primary) / 0.4)" },
|
|
7225
7316
|
"50%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 24px 4px hsl(var(--primary) / 0.75)" }
|
|
7226
7317
|
}
|
|
7318
|
+
} : {},
|
|
7319
|
+
...realtimeHighlightAppNames && realtimeHighlightAppNames.length > 0 ? {
|
|
7320
|
+
[realtimeHighlightAppNames.map((n) => `& .singul-dropdown-item[data-app-name="${n}"]`).join(", ")]: {
|
|
7321
|
+
position: "relative",
|
|
7322
|
+
zIndex: 2,
|
|
7323
|
+
borderColor: "hsl(var(--primary) / 0.78) !important",
|
|
7324
|
+
backgroundColor: "hsl(var(--primary) / 0.08) !important",
|
|
7325
|
+
outline: "none !important",
|
|
7326
|
+
boxShadow: "none !important",
|
|
7327
|
+
animation: "shuffleHighlightPulseStrong 1.5s ease-in-out infinite",
|
|
7328
|
+
transition: "border-color 120ms ease, background-color 120ms ease",
|
|
7329
|
+
"&::before": {
|
|
7330
|
+
content: '""',
|
|
7331
|
+
position: "absolute",
|
|
7332
|
+
left: "10px",
|
|
7333
|
+
top: "14px",
|
|
7334
|
+
bottom: "14px",
|
|
7335
|
+
width: "3px",
|
|
7336
|
+
borderRadius: "999px",
|
|
7337
|
+
backgroundColor: "hsl(var(--primary))"
|
|
7338
|
+
},
|
|
7339
|
+
"& .singul-app-info": {
|
|
7340
|
+
paddingLeft: "8px"
|
|
7341
|
+
}
|
|
7342
|
+
},
|
|
7343
|
+
"@keyframes shuffleHighlightPulseStrong": {
|
|
7344
|
+
"0%, 100%": {
|
|
7345
|
+
borderColor: "hsl(var(--primary) / 0.62)",
|
|
7346
|
+
backgroundColor: "hsl(var(--primary) / 0.06)"
|
|
7347
|
+
},
|
|
7348
|
+
"50%": {
|
|
7349
|
+
borderColor: "hsl(var(--primary) / 0.92)",
|
|
7350
|
+
backgroundColor: "hsl(var(--primary) / 0.12)"
|
|
7351
|
+
}
|
|
7352
|
+
}
|
|
7227
7353
|
} : {}
|
|
7228
7354
|
},
|
|
7229
7355
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_framer_motion8.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -7246,8 +7372,9 @@ function AppSearchDrawer({
|
|
|
7246
7372
|
layout: "grid",
|
|
7247
7373
|
gridColumns: 2,
|
|
7248
7374
|
inline: true,
|
|
7375
|
+
initialQuery,
|
|
7249
7376
|
initialFilterQuery: initialQuery,
|
|
7250
|
-
hitsPerPage:
|
|
7377
|
+
hitsPerPage: 20,
|
|
7251
7378
|
showDescription: false,
|
|
7252
7379
|
showCategories: true,
|
|
7253
7380
|
showCheckbox: multiSelect,
|
|
@@ -7338,7 +7465,8 @@ function AppSearchDrawer({
|
|
|
7338
7465
|
theme,
|
|
7339
7466
|
colorMode,
|
|
7340
7467
|
onRefresh: onClose,
|
|
7341
|
-
onAddToCanvas
|
|
7468
|
+
onAddToCanvas,
|
|
7469
|
+
autoActivate
|
|
7342
7470
|
}
|
|
7343
7471
|
)
|
|
7344
7472
|
] });
|
|
@@ -7605,11 +7733,173 @@ function ShufflePipelinesBanner() {
|
|
|
7605
7733
|
var ShufflePipelinesBanner_default = ShufflePipelinesBanner;
|
|
7606
7734
|
|
|
7607
7735
|
// components/AgentUI.tsx
|
|
7608
|
-
var import_react15 = require("react");
|
|
7736
|
+
var import_react15 = __toESM(require("react"));
|
|
7609
7737
|
var import_lucide_react11 = require("lucide-react");
|
|
7610
7738
|
var import_react_router_dom2 = require("react-router-dom");
|
|
7611
7739
|
var import_material16 = require("@mui/material");
|
|
7612
7740
|
var import_react_markdown4 = __toESM(require("react-markdown"));
|
|
7741
|
+
|
|
7742
|
+
// components/agentPromptSuggestions.ts
|
|
7743
|
+
var AGENT_PROMPT_SUGGESTIONS = [
|
|
7744
|
+
// — Email & comms ————————————————————————————————————————————————
|
|
7745
|
+
"Take care of my emails by pretending to be me and answering them",
|
|
7746
|
+
"Triage my inbox every hour and draft replies for anything urgent",
|
|
7747
|
+
"Summarise my unread emails from the last 24 hours and rank them by importance",
|
|
7748
|
+
"Forward any phishing-looking emails in my inbox to the security team and quarantine them",
|
|
7749
|
+
"Reply to scheduling requests in my inbox using my working hours and calendar availability",
|
|
7750
|
+
"Every morning, send me a digest of overnight emails grouped by sender and topic",
|
|
7751
|
+
"Auto-unsubscribe from marketing emails I have not opened in 60 days",
|
|
7752
|
+
"Snooze low-priority newsletters until Friday afternoon",
|
|
7753
|
+
"Flag and archive shipping notifications once the package is delivered",
|
|
7754
|
+
"Clean up my inbox by archiving anything older than 30 days that I have already read",
|
|
7755
|
+
// — Calendar & meetings ————————————————————————————————————————————
|
|
7756
|
+
"Block focus time on my calendar every weekday morning between 9 and 11",
|
|
7757
|
+
"Decline meetings that conflict with my focus blocks and propose alternatives",
|
|
7758
|
+
"Send me a daily agenda every weekday at 8am with prep notes per meeting",
|
|
7759
|
+
"Reschedule any meeting without an agenda 24 hours before it starts",
|
|
7760
|
+
"Send meeting notes and action items to all attendees after every call",
|
|
7761
|
+
"Find a 30-minute slot this week that works for me and the people I mention",
|
|
7762
|
+
"Cancel recurring meetings that I have skipped 3 times in a row",
|
|
7763
|
+
"Remind me 15 minutes before any meeting that I have not prepared for",
|
|
7764
|
+
// — Incidents & SOC operations ———————————————————————————————————
|
|
7765
|
+
"Triage new incidents every 15 minutes and assign severity, owner, and next steps",
|
|
7766
|
+
"Watch for new critical incidents and page the on-call engineer immediately",
|
|
7767
|
+
"Close incidents older than 30 days that have had no activity and no observables",
|
|
7768
|
+
"Merge duplicate incidents that share the same observable or hostname",
|
|
7769
|
+
"Enrich every new incident with threat intel and asset context within 2 minutes",
|
|
7770
|
+
"Auto-acknowledge incidents from known maintenance windows and link them to the change ticket",
|
|
7771
|
+
"Summarise yesterday's incidents into a daily standup brief for the SOC team",
|
|
7772
|
+
"Escalate any incident that breaches its SLA to the team lead",
|
|
7773
|
+
"Tag every incident with the MITRE ATT&CK technique that best matches its observables",
|
|
7774
|
+
"Watch the alert queue and group related alerts into a single incident",
|
|
7775
|
+
"Auto-resolve incidents whose root cause matches a previously closed incident",
|
|
7776
|
+
"Reopen any closed incident if the same observable shows up again within 7 days",
|
|
7777
|
+
"Send a weekly incident trend report every Monday morning to the security leadership",
|
|
7778
|
+
// — Threat intel & IOCs —————————————————————————————————————————
|
|
7779
|
+
"Pull new IOCs from my threat feeds every hour and push them to the firewall blocklist",
|
|
7780
|
+
"Check every external IP in today's incidents against VirusTotal and AbuseIPDB",
|
|
7781
|
+
"Sweep the environment for any host that has connected to a known bad domain in the last 7 days",
|
|
7782
|
+
"Subscribe to new CISA advisories and turn them into detection rules where possible",
|
|
7783
|
+
"Cross-reference observed file hashes against MalwareBazaar daily",
|
|
7784
|
+
"Watch for newly registered domains that look like our brand and report them",
|
|
7785
|
+
"Alert me whenever a new CVE with a known exploit affects software in our inventory",
|
|
7786
|
+
"Refresh the IOC datastore every 6 hours and prune entries older than 30 days",
|
|
7787
|
+
// — Detection engineering ———————————————————————————————————————
|
|
7788
|
+
"Review noisy detection rules every week and propose tuning suggestions",
|
|
7789
|
+
"Convert the latest Sigma rules from the public repo into our SIEM's format and stage them for review",
|
|
7790
|
+
"Tell me which detection rules have not fired in the last 90 days so I can retire them",
|
|
7791
|
+
"Audit MITRE ATT&CK coverage every Monday and flag techniques with zero detections",
|
|
7792
|
+
"Backtest new detection rules against the last 30 days of logs before promoting them to production",
|
|
7793
|
+
// — SIEM operations ———————————————————————————————————————————
|
|
7794
|
+
"Triage new Splunk alerts every 10 minutes and assign severity, owner, and next steps",
|
|
7795
|
+
"Watch Microsoft Sentinel for high-severity incidents and page the on-call analyst immediately",
|
|
7796
|
+
"Suppress noisy SIEM alerts that fire more than 50 times per hour and open a tuning ticket",
|
|
7797
|
+
"Correlate failed login spikes in the SIEM with VPN logs and flag possible brute-force attempts",
|
|
7798
|
+
"Hunt the SIEM every morning for sign-ins from countries we do not operate in",
|
|
7799
|
+
"Forward critical SIEM detections straight to Case Management and skip the alert queue",
|
|
7800
|
+
"Run a weekly SIEM data-source health check and alert me on any log source silent for over 1 hour",
|
|
7801
|
+
"Enrich every SIEM alert with asset owner, criticality, and recent vulnerabilities before triage",
|
|
7802
|
+
"Search the SIEM for the latest IOCs from threat intel feeds every 30 minutes",
|
|
7803
|
+
"Summarise top 10 noisiest SIEM rules every Friday and propose tuning candidates",
|
|
7804
|
+
"Detect lateral movement patterns in SIEM auth logs and open an incident with the affected hosts",
|
|
7805
|
+
"Watch the SIEM for any disable or delete of audit logging and treat it as a critical incident",
|
|
7806
|
+
// — EDR operations ————————————————————————————————————————————
|
|
7807
|
+
"Isolate any endpoint that triggers a critical CrowdStrike alert and notify the user's manager",
|
|
7808
|
+
"Kill any process on a flagged host that matches a known malware family in EDR telemetry",
|
|
7809
|
+
"Watch SentinelOne for ransomware behavior detections and auto-contain the host within 60 seconds",
|
|
7810
|
+
"Pull the process tree from EDR for every malware detection and attach it to the incident",
|
|
7811
|
+
"Sweep all endpoints for a given hash or filename when a new IOC arrives and report matches",
|
|
7812
|
+
"Detect newly created local admin accounts on any endpoint and require approval before keeping them",
|
|
7813
|
+
"Alert when an EDR agent goes offline for more than 1 hour and open a ticket against the asset owner",
|
|
7814
|
+
"Quarantine any binary flagged as suspicious by EDR and email the user with next steps",
|
|
7815
|
+
"Hunt EDR telemetry every night for LOLBins executed from user-writable directories",
|
|
7816
|
+
"Correlate EDR alerts with SIEM auth events to detect credential theft followed by execution",
|
|
7817
|
+
"Run a weekly EDR coverage report and list endpoints without an active agent",
|
|
7818
|
+
"Auto-resolve EDR alerts that match a known-good signed binary on our allowlist",
|
|
7819
|
+
// — Vulnerability management ————————————————————————————————————
|
|
7820
|
+
"Scan our asset inventory daily and open tickets for any new critical or high vulnerability",
|
|
7821
|
+
"Remind asset owners every Friday about open vulnerabilities older than 14 days",
|
|
7822
|
+
"Re-scan hosts that recently patched a critical vulnerability and close the ticket if clean",
|
|
7823
|
+
"Send the patch compliance report every Monday morning to IT and security leadership",
|
|
7824
|
+
"Correlate vulnerabilities with active exploits in the wild and re-prioritise the queue",
|
|
7825
|
+
// — Endpoint & host monitoring ———————————————————————————————————
|
|
7826
|
+
"Watch my host monitors and alert me if any agent goes offline for more than 1 hour",
|
|
7827
|
+
"Isolate any endpoint that triggers a critical EDR alert and notify the user's manager",
|
|
7828
|
+
"Kill any process on a flagged host that matches a known malware family",
|
|
7829
|
+
"Run an inventory of installed software on every endpoint every Sunday",
|
|
7830
|
+
"Detect new local admin accounts created on any endpoint and require approval",
|
|
7831
|
+
"Make sure full-disk encryption is on for every laptop and report exceptions weekly",
|
|
7832
|
+
// — Identity & access —————————————————————————————————————————
|
|
7833
|
+
"Review user access every quarter and flag anyone with privileges they have not used in 90 days",
|
|
7834
|
+
"Disable accounts that have not logged in for 60 days and notify their manager",
|
|
7835
|
+
"Watch for impossible travel sign-ins and force a password reset plus MFA re-enrolment",
|
|
7836
|
+
"Alert me whenever someone is added to an admin group and require justification within 24 hours",
|
|
7837
|
+
"Audit MFA enrolment weekly and email any user without a second factor",
|
|
7838
|
+
"Rotate service account credentials every 90 days and update the vault",
|
|
7839
|
+
"Detect dormant API keys older than 180 days and revoke them after notice",
|
|
7840
|
+
"Make sure new joiners get baseline access provisioned within 1 hour of their start date",
|
|
7841
|
+
"Make sure leavers have all access revoked within 15 minutes of their termination event",
|
|
7842
|
+
// — Cloud, infra & posture ————————————————————————————————————
|
|
7843
|
+
"Check our cloud accounts every hour for public S3 buckets and lock them down",
|
|
7844
|
+
"Detect new IAM roles with wildcard permissions and require review before they go live",
|
|
7845
|
+
"Watch for unencrypted databases in production and open a ticket against the owner",
|
|
7846
|
+
"Run a CIS benchmark scan against all production cloud accounts every Sunday",
|
|
7847
|
+
"Alert on any new security group that opens ports to 0.0.0.0/0",
|
|
7848
|
+
"Monitor cloud spend daily and warn me if any service's cost jumps more than 50% week-over-week",
|
|
7849
|
+
"Check certificate expiry across our domains weekly and renew anything within 30 days",
|
|
7850
|
+
"Watch our DNS records for unauthorised changes and revert them",
|
|
7851
|
+
// — Phishing & user reports ———————————————————————————————————
|
|
7852
|
+
"Investigate phishing reports from the abuse mailbox and respond to the reporter within 1 hour",
|
|
7853
|
+
"Detonate suspicious attachments in a sandbox and attach the verdict to the incident",
|
|
7854
|
+
"Pull URLs from reported phishing emails and submit them to URLhaus and PhishTank",
|
|
7855
|
+
"Send a phishing simulation to a sample of users every month and report results",
|
|
7856
|
+
// — Compliance, audit & reporting —————————————————————————————
|
|
7857
|
+
"Generate the SOC2 evidence pack at the start of every month",
|
|
7858
|
+
"Track changes to security policies and alert the GRC team when one is edited",
|
|
7859
|
+
"Send a weekly KPI report covering MTTD, MTTR, and open incident backlog",
|
|
7860
|
+
"Audit log retention every Sunday and confirm we still meet the 1-year requirement",
|
|
7861
|
+
"Generate a monthly executive summary of incidents, vulnerabilities, and detection coverage",
|
|
7862
|
+
// — Backups, DR & uptime ————————————————————————————————————
|
|
7863
|
+
"Verify nightly backups completed successfully and alert me if any failed",
|
|
7864
|
+
"Test restore from backup on a sample workload every month and report results",
|
|
7865
|
+
"Watch our public status page for incidents at our critical vendors and notify the team",
|
|
7866
|
+
"Ping our public endpoints every minute and open an incident if any return non-2xx for 3 minutes",
|
|
7867
|
+
// — Tickets, workflow & docs ——————————————————————————————————
|
|
7868
|
+
"Triage new Jira tickets in the security project every hour and assign by category",
|
|
7869
|
+
"Close tickets that have been waiting on the reporter for more than 14 days",
|
|
7870
|
+
"Summarise this week's closed tickets into release notes every Friday",
|
|
7871
|
+
"Pull action items out of meeting notes I share and create tickets for them",
|
|
7872
|
+
"Keep the on-call runbook in sync with the latest incident postmortems",
|
|
7873
|
+
"Review pull requests in our security repos and leave a summary comment within an hour",
|
|
7874
|
+
// — People, HR & onboarding ————————————————————————————————————
|
|
7875
|
+
"Send a welcome message and security training link to every new joiner on their start date",
|
|
7876
|
+
"Run the offboarding checklist whenever someone is marked as a leaver in HR",
|
|
7877
|
+
"Remind managers to complete quarterly performance reviews 1 week before the deadline",
|
|
7878
|
+
"Send birthday and work anniversary greetings from me on the right day",
|
|
7879
|
+
// — Personal / lightweight ops chores —————————————————————————
|
|
7880
|
+
"Order more office coffee whenever the inventory drops below 2 bags",
|
|
7881
|
+
"File my receipts every Friday and submit the expense report",
|
|
7882
|
+
"Track my open invoices and chase clients whose payment is more than 14 days overdue",
|
|
7883
|
+
"Send a polite follow-up to anyone I have emailed but who has not replied in 5 working days",
|
|
7884
|
+
"Read the security news feeds every morning and summarise the top 5 stories for me"
|
|
7885
|
+
];
|
|
7886
|
+
var matchAgentPromptSuggestions = (input, limit = 8) => {
|
|
7887
|
+
const q = (input || "").trim().toLowerCase();
|
|
7888
|
+
if (!q) return [];
|
|
7889
|
+
const scored = [];
|
|
7890
|
+
for (const text of AGENT_PROMPT_SUGGESTIONS) {
|
|
7891
|
+
const lower = text.toLowerCase();
|
|
7892
|
+
const idx = lower.indexOf(q);
|
|
7893
|
+
if (idx < 0) continue;
|
|
7894
|
+
const score = idx === 0 ? -1e3 + text.length : idx * 10 + text.length;
|
|
7895
|
+
scored.push({ text, score });
|
|
7896
|
+
}
|
|
7897
|
+
scored.sort((a, b) => a.score - b.score);
|
|
7898
|
+
return scored.slice(0, limit).map((s) => s.text);
|
|
7899
|
+
};
|
|
7900
|
+
var DEFAULT_AGENT_PROMPT_PLACEHOLDER = "Take care of my emails by pretending to be me and answering them";
|
|
7901
|
+
|
|
7902
|
+
// components/AgentUI.tsx
|
|
7613
7903
|
var import_remark_gfm4 = __toESM(require("remark-gfm"));
|
|
7614
7904
|
var import_remark_breaks = __toESM(require("remark-breaks"));
|
|
7615
7905
|
var import_react18_json_view2 = __toESM(require("react18-json-view"));
|
|
@@ -9547,7 +9837,7 @@ var AgentUI = ({
|
|
|
9547
9837
|
autoLoadApps = true,
|
|
9548
9838
|
title = "What do you want to do?",
|
|
9549
9839
|
subtitle,
|
|
9550
|
-
placeholder =
|
|
9840
|
+
placeholder = DEFAULT_AGENT_PROMPT_PLACEHOLDER,
|
|
9551
9841
|
defaultInput = "",
|
|
9552
9842
|
autoSubmit = false,
|
|
9553
9843
|
hideHeroIcon = false,
|
|
@@ -9599,6 +9889,29 @@ var AgentUI = ({
|
|
|
9599
9889
|
const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
|
|
9600
9890
|
const navigate = (0, import_react_router_dom2.useNavigate)();
|
|
9601
9891
|
const [actionInput, setActionInput] = (0, import_react15.useState)(defaultInput);
|
|
9892
|
+
const promptAnchorRef = import_react15.default.useRef(null);
|
|
9893
|
+
const [suggestionsDismissed, setSuggestionsDismissed] = (0, import_react15.useState)(false);
|
|
9894
|
+
const [suggestionIndex, setSuggestionIndex] = (0, import_react15.useState)(-1);
|
|
9895
|
+
const promptSuggestions = (0, import_react15.useMemo)(
|
|
9896
|
+
() => matchAgentPromptSuggestions(actionInput, 8),
|
|
9897
|
+
[actionInput]
|
|
9898
|
+
);
|
|
9899
|
+
(0, import_react15.useEffect)(() => {
|
|
9900
|
+
setSuggestionIndex(-1);
|
|
9901
|
+
setSuggestionsDismissed(false);
|
|
9902
|
+
}, [actionInput]);
|
|
9903
|
+
const suggestionsOpen = promptSuggestions.length > 0 && !suggestionsDismissed;
|
|
9904
|
+
const acceptSuggestion = (0, import_react15.useCallback)((s) => {
|
|
9905
|
+
setActionInput(s);
|
|
9906
|
+
setSuggestionsDismissed(true);
|
|
9907
|
+
setSuggestionIndex(-1);
|
|
9908
|
+
requestAnimationFrame(() => {
|
|
9909
|
+
try {
|
|
9910
|
+
inputRef.current?.focus();
|
|
9911
|
+
} catch {
|
|
9912
|
+
}
|
|
9913
|
+
});
|
|
9914
|
+
}, []);
|
|
9602
9915
|
const BUILTIN_DEFAULT_APPS = [
|
|
9603
9916
|
{ name: "http" },
|
|
9604
9917
|
{ name: "shuffle_tools" }
|
|
@@ -10592,6 +10905,34 @@ var AgentUI = ({
|
|
|
10592
10905
|
}
|
|
10593
10906
|
}, [submitOverride, actionInput, chosenApps, submitInput]);
|
|
10594
10907
|
const onKeyDown = (e) => {
|
|
10908
|
+
if (suggestionsOpen && promptSuggestions.length > 0) {
|
|
10909
|
+
if (e.key === "ArrowDown") {
|
|
10910
|
+
e.preventDefault();
|
|
10911
|
+
setSuggestionIndex((i) => (i + 1) % promptSuggestions.length);
|
|
10912
|
+
return;
|
|
10913
|
+
}
|
|
10914
|
+
if (e.key === "ArrowUp") {
|
|
10915
|
+
e.preventDefault();
|
|
10916
|
+
setSuggestionIndex((i) => i <= 0 ? promptSuggestions.length - 1 : i - 1);
|
|
10917
|
+
return;
|
|
10918
|
+
}
|
|
10919
|
+
if (e.key === "Escape") {
|
|
10920
|
+
e.preventDefault();
|
|
10921
|
+
setSuggestionsDismissed(true);
|
|
10922
|
+
setSuggestionIndex(-1);
|
|
10923
|
+
return;
|
|
10924
|
+
}
|
|
10925
|
+
if (e.key === "Tab" && suggestionIndex >= 0) {
|
|
10926
|
+
e.preventDefault();
|
|
10927
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10928
|
+
return;
|
|
10929
|
+
}
|
|
10930
|
+
if (e.key === "Enter" && suggestionIndex >= 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
|
10931
|
+
e.preventDefault();
|
|
10932
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10933
|
+
return;
|
|
10934
|
+
}
|
|
10935
|
+
}
|
|
10595
10936
|
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
10596
10937
|
e.preventDefault();
|
|
10597
10938
|
handlePrimarySubmit();
|
|
@@ -11249,7 +11590,7 @@ var AgentUI = ({
|
|
|
11249
11590
|
mt: -1,
|
|
11250
11591
|
maxWidth: 600
|
|
11251
11592
|
}, children: subtitle }),
|
|
11252
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { sx: {
|
|
11593
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { ref: promptAnchorRef, sx: {
|
|
11253
11594
|
width: "100%",
|
|
11254
11595
|
display: "flex",
|
|
11255
11596
|
flexDirection: "column",
|
|
@@ -11457,6 +11798,67 @@ var AgentUI = ({
|
|
|
11457
11798
|
) }) })
|
|
11458
11799
|
] })
|
|
11459
11800
|
] }),
|
|
11801
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
11802
|
+
import_material16.Popper,
|
|
11803
|
+
{
|
|
11804
|
+
open: suggestionsOpen,
|
|
11805
|
+
anchorEl: promptAnchorRef.current,
|
|
11806
|
+
placement: "bottom-start",
|
|
11807
|
+
style: { zIndex: 1300, width: promptAnchorRef.current?.offsetWidth },
|
|
11808
|
+
modifiers: [{ name: "offset", options: { offset: [0, 6] } }],
|
|
11809
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.ClickAwayListener, { onClickAway: () => setSuggestionsDismissed(true), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
11810
|
+
import_material16.Paper,
|
|
11811
|
+
{
|
|
11812
|
+
elevation: 6,
|
|
11813
|
+
sx: {
|
|
11814
|
+
bgcolor: "hsl(var(--card))",
|
|
11815
|
+
border: "1px solid hsl(var(--border))",
|
|
11816
|
+
borderRadius: 2,
|
|
11817
|
+
overflow: "hidden",
|
|
11818
|
+
maxHeight: 320,
|
|
11819
|
+
overflowY: "auto"
|
|
11820
|
+
},
|
|
11821
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.MenuList, { dense: true, disablePadding: true, children: promptSuggestions.map((s, i) => {
|
|
11822
|
+
const q = actionInput.trim();
|
|
11823
|
+
const lower = s.toLowerCase();
|
|
11824
|
+
const idx = q ? lower.indexOf(q.toLowerCase()) : -1;
|
|
11825
|
+
const before = idx >= 0 ? s.slice(0, idx) : s;
|
|
11826
|
+
const match = idx >= 0 ? s.slice(idx, idx + q.length) : "";
|
|
11827
|
+
const after = idx >= 0 ? s.slice(idx + q.length) : "";
|
|
11828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
11829
|
+
import_material16.MenuItem,
|
|
11830
|
+
{
|
|
11831
|
+
selected: i === suggestionIndex,
|
|
11832
|
+
onMouseEnter: () => setSuggestionIndex(i),
|
|
11833
|
+
onMouseDown: (e) => {
|
|
11834
|
+
e.preventDefault();
|
|
11835
|
+
acceptSuggestion(s);
|
|
11836
|
+
},
|
|
11837
|
+
sx: {
|
|
11838
|
+
fontSize: "0.88rem",
|
|
11839
|
+
color: "hsl(var(--foreground))",
|
|
11840
|
+
py: 0.75,
|
|
11841
|
+
px: 2,
|
|
11842
|
+
"&.Mui-selected, &.Mui-selected:hover": {
|
|
11843
|
+
bgcolor: "hsl(var(--muted) / 0.6)"
|
|
11844
|
+
}
|
|
11845
|
+
},
|
|
11846
|
+
children: [
|
|
11847
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.Search, { size: 14, style: { marginRight: 10, color: "hsl(var(--muted-foreground))", flexShrink: 0 } }),
|
|
11848
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { component: "span", sx: { whiteSpace: "normal", lineHeight: 1.4 }, children: [
|
|
11849
|
+
before,
|
|
11850
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { component: "span", sx: { fontWeight: 700, color: "hsl(var(--foreground))" }, children: match }),
|
|
11851
|
+
after
|
|
11852
|
+
] })
|
|
11853
|
+
]
|
|
11854
|
+
},
|
|
11855
|
+
s
|
|
11856
|
+
);
|
|
11857
|
+
}) })
|
|
11858
|
+
}
|
|
11859
|
+
) })
|
|
11860
|
+
}
|
|
11861
|
+
),
|
|
11460
11862
|
!hideAppPicker && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { sx: {
|
|
11461
11863
|
display: "inline-flex",
|
|
11462
11864
|
flexWrap: "wrap",
|
|
@@ -12290,6 +12692,32 @@ var ENDPOINT_PRESETS = [
|
|
|
12290
12692
|
{ label: "LM Studio (localhost)", url: "http://localhost:1234/v1", apiKeyHint: "Local LM Studio does not require an API key \u2014 any non-empty value works." },
|
|
12291
12693
|
{ label: CUSTOM_PRESET, url: "" }
|
|
12292
12694
|
];
|
|
12695
|
+
var PROVIDER_DOMAINS = {
|
|
12696
|
+
"Shuffle AI": "shuffler.io",
|
|
12697
|
+
OpenAI: "openai.com",
|
|
12698
|
+
Anthropic: "anthropic.com",
|
|
12699
|
+
"Google Gemini": "gemini.google.com",
|
|
12700
|
+
Mistral: "mistral.ai",
|
|
12701
|
+
Groq: "groq.com",
|
|
12702
|
+
DeepSeek: "deepseek.com",
|
|
12703
|
+
"Together AI": "together.ai",
|
|
12704
|
+
OpenRouter: "openrouter.ai",
|
|
12705
|
+
"Ollama (localhost)": "ollama.com",
|
|
12706
|
+
"LM Studio (localhost)": "lmstudio.ai"
|
|
12707
|
+
};
|
|
12708
|
+
var ProviderLogo = ({ label, url }) => {
|
|
12709
|
+
const [errored, setErrored] = (0, import_react16.useState)(false);
|
|
12710
|
+
let domain = PROVIDER_DOMAINS[label];
|
|
12711
|
+
if (!domain && url) {
|
|
12712
|
+
try {
|
|
12713
|
+
domain = new URL(url).hostname.replace(/^www\./, "");
|
|
12714
|
+
} catch {
|
|
12715
|
+
}
|
|
12716
|
+
}
|
|
12717
|
+
const src = domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
12718
|
+
const initial = label.trim().charAt(0).toUpperCase() || "?";
|
|
12719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Box, { sx: { width: 18, height: 18, borderRadius: "4px", display: "flex", alignItems: "center", justifyContent: "center", bgcolor: "hsl(var(--muted))", overflow: "hidden", flexShrink: 0 }, children: src && !errored ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src, alt: "", width: 18, height: 18, style: { display: "block" }, onError: () => setErrored(true) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { sx: { fontSize: "0.65rem", fontWeight: 600, color: "hsl(var(--muted-foreground))", lineHeight: 1 }, children: initial }) });
|
|
12720
|
+
};
|
|
12293
12721
|
var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode }) => {
|
|
12294
12722
|
useSyncHostBaseUrl(globalUrl);
|
|
12295
12723
|
const { authStates, authenticatedApps, handleAuthChange, handleTestConnection, handleSaveAuth, refreshAuth } = useAppAuth();
|
|
@@ -12433,12 +12861,28 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12433
12861
|
isOptionEqualToValue: (opt, val) => opt === val,
|
|
12434
12862
|
renderOption: (props, option) => {
|
|
12435
12863
|
const preset = ENDPOINT_PRESETS.find((p) => p.label === option);
|
|
12436
|
-
return /* @__PURE__ */ (0, import_react17.createElement)("li", { ...props, key: option }, /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%", minWidth: 0 }, children: [
|
|
12864
|
+
return /* @__PURE__ */ (0, import_react17.createElement)("li", { ...props, key: option }, /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 1.25, width: "100%", minWidth: 0 }, children: [
|
|
12865
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ProviderLogo, { label: option, url: preset?.url }),
|
|
12437
12866
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { sx: { fontSize: "0.85rem", color: "hsl(var(--popover-foreground))" }, children: option }),
|
|
12438
12867
|
preset?.url && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { component: "span", sx: { ml: "auto", color: "hsl(var(--muted-foreground))", fontSize: "0.75rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: preset.url })
|
|
12439
12868
|
] }));
|
|
12440
12869
|
},
|
|
12441
|
-
renderInput: (params) =>
|
|
12870
|
+
renderInput: (params) => {
|
|
12871
|
+
const preset = ENDPOINT_PRESETS.find((p) => p.label === effectivePreset);
|
|
12872
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
12873
|
+
import_material18.TextField,
|
|
12874
|
+
{
|
|
12875
|
+
...params,
|
|
12876
|
+
placeholder: "Search a provider\u2026",
|
|
12877
|
+
slotProps: {
|
|
12878
|
+
input: {
|
|
12879
|
+
...params.InputProps,
|
|
12880
|
+
startAdornment: effectivePreset ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Box, { sx: { display: "flex", alignItems: "center", pl: 0.5, mr: 0.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ProviderLogo, { label: effectivePreset, url: preset?.url }) }) : void 0
|
|
12881
|
+
}
|
|
12882
|
+
}
|
|
12883
|
+
}
|
|
12884
|
+
);
|
|
12885
|
+
},
|
|
12442
12886
|
slotProps: {
|
|
12443
12887
|
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
12444
12888
|
popper: { sx: { zIndex: 9999 } }
|
|
@@ -13401,17 +13845,20 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13401
13845
|
] })
|
|
13402
13846
|
] })
|
|
13403
13847
|
] }),
|
|
13404
|
-
|
|
13848
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13405
13849
|
import_material20.Box,
|
|
13406
13850
|
{
|
|
13407
13851
|
onClick: (e) => e.stopPropagation(),
|
|
13408
13852
|
sx: {
|
|
13409
13853
|
display: { xs: "none", sm: "flex" },
|
|
13410
13854
|
alignItems: "center",
|
|
13855
|
+
justifyContent: "flex-end",
|
|
13411
13856
|
flexShrink: 0,
|
|
13412
|
-
ml: 1
|
|
13857
|
+
ml: 1,
|
|
13858
|
+
width: 140,
|
|
13859
|
+
minHeight: 28
|
|
13413
13860
|
},
|
|
13414
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13861
|
+
children: tools.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13415
13862
|
import_material20.AvatarGroup,
|
|
13416
13863
|
{
|
|
13417
13864
|
max: 5,
|
|
@@ -13460,6 +13907,17 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13460
13907
|
) }, t.name);
|
|
13461
13908
|
})
|
|
13462
13909
|
}
|
|
13910
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13911
|
+
import_material20.Typography,
|
|
13912
|
+
{
|
|
13913
|
+
sx: {
|
|
13914
|
+
fontSize: "0.7rem",
|
|
13915
|
+
color: "hsl(var(--muted-foreground))",
|
|
13916
|
+
opacity: 0.5,
|
|
13917
|
+
fontStyle: "italic"
|
|
13918
|
+
},
|
|
13919
|
+
children: "No apps"
|
|
13920
|
+
}
|
|
13463
13921
|
)
|
|
13464
13922
|
}
|
|
13465
13923
|
)
|
|
@@ -14677,7 +15135,9 @@ var LocalLLMConfig2 = withMcpTheme(LocalLLMConfig_default, "LocalLLMConfig");
|
|
|
14677
15135
|
deleteDatastoreItem,
|
|
14678
15136
|
deleteDatastoreItems,
|
|
14679
15137
|
diagnoseOutputWarning,
|
|
15138
|
+
extractActionAppNames,
|
|
14680
15139
|
extractValidatedIngestionApps,
|
|
15140
|
+
extractWorkflowActionAppNames,
|
|
14681
15141
|
extractWorkflowAppNames,
|
|
14682
15142
|
fetchApps,
|
|
14683
15143
|
fetchAppsViaApiConfig,
|