@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.mjs
CHANGED
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
} from "./chunk-B4JFC2JU.mjs";
|
|
21
21
|
|
|
22
22
|
// index.ts
|
|
23
|
-
import "./shuffle-mcp-
|
|
23
|
+
import "./shuffle-mcp-TWJGPBOQ.css";
|
|
24
24
|
import React5 from "react";
|
|
25
25
|
|
|
26
26
|
// ShuffleMcpThemeProvider.tsx
|
|
27
27
|
import React from "react";
|
|
28
28
|
import { ThemeProvider, createTheme, useTheme as useMuiTheme } from "@mui/material";
|
|
29
|
-
import "./shuffle-mcp-
|
|
29
|
+
import "./shuffle-mcp-TWJGPBOQ.css";
|
|
30
30
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
31
31
|
var readHtmlDarkClass = () => {
|
|
32
32
|
if (typeof document === "undefined") return false;
|
|
@@ -879,6 +879,65 @@ var isIngestionApp = (appName) => {
|
|
|
879
879
|
return isEmailApp(appName) || CASES_PATTERNS.some((p) => name.includes(p)) || EDR_PATTERNS.some((p) => name.includes(p)) || SIEM_PATTERNS.some((p) => name.includes(p));
|
|
880
880
|
};
|
|
881
881
|
var normalizeAppName = (name) => name.toLowerCase().trim().replace(/[\s_\-]+/g, "_");
|
|
882
|
+
var IGNORED_WORKFLOW_APP_NAMES = /* @__PURE__ */ new Set([
|
|
883
|
+
"shuffle_tools",
|
|
884
|
+
"singul",
|
|
885
|
+
"integration",
|
|
886
|
+
"ai_agent",
|
|
887
|
+
"shuffle_agent",
|
|
888
|
+
"shuffle_ai"
|
|
889
|
+
]);
|
|
890
|
+
var isIgnoredWorkflowAppName = (name) => IGNORED_WORKFLOW_APP_NAMES.has(normalizeAppName(name));
|
|
891
|
+
var looksLikeOpaqueId = (raw) => {
|
|
892
|
+
const trimmed = raw.trim();
|
|
893
|
+
if (/^[a-f0-9]{16,}$/i.test(trimmed)) return true;
|
|
894
|
+
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;
|
|
895
|
+
return false;
|
|
896
|
+
};
|
|
897
|
+
var addWorkflowAppName = (names, seen, raw) => {
|
|
898
|
+
if (typeof raw !== "string" || !raw.trim()) return;
|
|
899
|
+
const parts = raw.includes(",") ? raw.split(",") : [raw];
|
|
900
|
+
for (const part of parts) {
|
|
901
|
+
const trimmed = part.trim();
|
|
902
|
+
if (!trimmed) continue;
|
|
903
|
+
const key = normalizeAppName(trimmed);
|
|
904
|
+
if (!key || isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed) || seen.has(key)) continue;
|
|
905
|
+
seen.add(key);
|
|
906
|
+
names.push(trimmed);
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
var collectParameterAppNames = (input, names, seen, depth = 0) => {
|
|
910
|
+
if (!input || depth > 4) return;
|
|
911
|
+
if (Array.isArray(input)) {
|
|
912
|
+
input.forEach((item) => collectParameterAppNames(item, names, seen, depth + 1));
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
if (typeof input !== "object") return;
|
|
916
|
+
const obj = input;
|
|
917
|
+
if (String(obj.name || "").toLowerCase() === "app_name") addWorkflowAppName(names, seen, obj.value);
|
|
918
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
919
|
+
const lower = key.toLowerCase();
|
|
920
|
+
if (lower === "app_name") addWorkflowAppName(names, seen, value);
|
|
921
|
+
else if (lower === "parameters" || lower === "fields" || lower === "value") collectParameterAppNames(value, names, seen, depth + 1);
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
function extractActionAppNames(action) {
|
|
925
|
+
const names = [];
|
|
926
|
+
const seen = /* @__PURE__ */ new Set();
|
|
927
|
+
collectParameterAppNames(action?.parameters, names, seen);
|
|
928
|
+
addWorkflowAppName(names, seen, action?.app_name);
|
|
929
|
+
addWorkflowAppName(names, seen, action?.app_id);
|
|
930
|
+
return names;
|
|
931
|
+
}
|
|
932
|
+
function extractWorkflowActionAppNames(workflow) {
|
|
933
|
+
const names = [];
|
|
934
|
+
const seen = /* @__PURE__ */ new Set();
|
|
935
|
+
if (!workflow?.actions || !Array.isArray(workflow.actions)) return names;
|
|
936
|
+
for (const action of workflow.actions) {
|
|
937
|
+
for (const name of extractActionAppNames(action)) addWorkflowAppName(names, seen, name);
|
|
938
|
+
}
|
|
939
|
+
return names;
|
|
940
|
+
}
|
|
882
941
|
var getIngestionCategory = (appName, appCategories) => {
|
|
883
942
|
const name = appName.toLowerCase();
|
|
884
943
|
const categories = (appCategories || []).map((c) => c.toLowerCase());
|
|
@@ -892,20 +951,14 @@ var INGEST_TICKETS_WORKFLOW_NAME = "Ingest Tickets";
|
|
|
892
951
|
var FORWARD_TICKETS_WORKFLOW_NAME = "Forward Tickets";
|
|
893
952
|
function extractWorkflowAppNames(workflow) {
|
|
894
953
|
const names = /* @__PURE__ */ new Set();
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
if (action.parameters) {
|
|
904
|
-
for (const param of action.parameters) {
|
|
905
|
-
if (param.name === "app_name" && param.value) {
|
|
906
|
-
names.add(normalizeAppName(param.value));
|
|
907
|
-
}
|
|
908
|
-
}
|
|
954
|
+
for (const raw of extractWorkflowActionAppNames(workflow)) {
|
|
955
|
+
const parts = typeof raw === "string" && raw.includes(",") ? raw.split(",") : [raw];
|
|
956
|
+
for (const part of parts) {
|
|
957
|
+
const trimmed = (part || "").trim();
|
|
958
|
+
if (!trimmed) continue;
|
|
959
|
+
if (isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed)) continue;
|
|
960
|
+
const key = normalizeAppName(trimmed);
|
|
961
|
+
if (key) names.add(key);
|
|
909
962
|
}
|
|
910
963
|
}
|
|
911
964
|
return names;
|
|
@@ -1619,6 +1672,7 @@ function AppTitleHeader({
|
|
|
1619
1672
|
isActivated = null,
|
|
1620
1673
|
activateLoading = false,
|
|
1621
1674
|
onActivateToggle,
|
|
1675
|
+
highlightActivate = false,
|
|
1622
1676
|
onAdd
|
|
1623
1677
|
}) {
|
|
1624
1678
|
return /* @__PURE__ */ jsx4(motion.div, { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: /* @__PURE__ */ jsxs3(
|
|
@@ -1722,7 +1776,16 @@ function AppTitleHeader({
|
|
|
1722
1776
|
py: 0.5,
|
|
1723
1777
|
minHeight: 0,
|
|
1724
1778
|
flexShrink: 0,
|
|
1725
|
-
...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)" } }
|
|
1779
|
+
...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)" } },
|
|
1780
|
+
...highlightActivate ? {
|
|
1781
|
+
boxShadow: "0 0 0 0 hsla(var(--primary) / 0.6)",
|
|
1782
|
+
animation: "appTitleActivatePulse 1.1s ease-out infinite",
|
|
1783
|
+
"@keyframes appTitleActivatePulse": {
|
|
1784
|
+
"0%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0.55)" },
|
|
1785
|
+
"70%": { boxShadow: "0 0 0 10px hsla(var(--primary) / 0)" },
|
|
1786
|
+
"100%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0)" }
|
|
1787
|
+
}
|
|
1788
|
+
} : {}
|
|
1726
1789
|
},
|
|
1727
1790
|
children: activateLoading ? "\u2026" : isActivated ? "Deactivate" : "Activate"
|
|
1728
1791
|
}
|
|
@@ -5320,6 +5383,7 @@ function AppDetailDrawer({
|
|
|
5320
5383
|
onAddToCanvas,
|
|
5321
5384
|
isAuthenticated = true,
|
|
5322
5385
|
activeOrgId,
|
|
5386
|
+
autoActivate = false,
|
|
5323
5387
|
globalUrl,
|
|
5324
5388
|
userdata,
|
|
5325
5389
|
isLoaded,
|
|
@@ -5517,8 +5581,9 @@ function AppDetailDrawer({
|
|
|
5517
5581
|
useEffect7(() => {
|
|
5518
5582
|
lastValidAuthRef.current = null;
|
|
5519
5583
|
}, [appName]);
|
|
5520
|
-
const handleActivateToggle = async () => {
|
|
5584
|
+
const handleActivateToggle = async (opts) => {
|
|
5521
5585
|
if (!appName || activateLoading) return;
|
|
5586
|
+
const silent = !!opts?.silent;
|
|
5522
5587
|
const wasActivated = isActivated;
|
|
5523
5588
|
const prevAppId = activatedAppId;
|
|
5524
5589
|
setIsActivated(!wasActivated);
|
|
@@ -5532,7 +5597,7 @@ function AppDetailDrawer({
|
|
|
5532
5597
|
});
|
|
5533
5598
|
if (!res.ok) throw new Error("Deactivate failed");
|
|
5534
5599
|
setActivatedAppId(null);
|
|
5535
|
-
toast.success(`${displayName} deactivated`);
|
|
5600
|
+
if (!silent) toast.success(`${displayName} deactivated`);
|
|
5536
5601
|
} else {
|
|
5537
5602
|
const appId2 = resolvedAlgoliaId;
|
|
5538
5603
|
if (!appId2) throw new Error("App ID not resolved yet");
|
|
@@ -5543,17 +5608,38 @@ function AppDetailDrawer({
|
|
|
5543
5608
|
});
|
|
5544
5609
|
if (!activateRes.ok) throw new Error(`Activate failed (${activateRes.status})`);
|
|
5545
5610
|
setActivatedAppId(appId2);
|
|
5546
|
-
toast.success(`${displayName} activated`);
|
|
5611
|
+
if (!silent) toast.success(`${displayName} activated`);
|
|
5547
5612
|
}
|
|
5548
5613
|
} catch (err) {
|
|
5549
5614
|
console.error("[Activate] Error:", err);
|
|
5550
|
-
toast.error(err?.message || "Activation failed");
|
|
5615
|
+
if (!silent) toast.error(err?.message || "Activation failed");
|
|
5551
5616
|
setIsActivated(wasActivated);
|
|
5552
5617
|
setActivatedAppId(prevAppId);
|
|
5553
5618
|
} finally {
|
|
5554
5619
|
setActivateLoading(false);
|
|
5555
5620
|
}
|
|
5556
5621
|
};
|
|
5622
|
+
const autoActivateFiredRef = useRef5(null);
|
|
5623
|
+
const [autoActivatePulse, setAutoActivatePulse] = useState8(false);
|
|
5624
|
+
useEffect7(() => {
|
|
5625
|
+
if (!open || !autoActivate || !appName) return;
|
|
5626
|
+
const key = `${appName}`;
|
|
5627
|
+
if (autoActivateFiredRef.current === key) return;
|
|
5628
|
+
if (isActivated !== false) return;
|
|
5629
|
+
if (!resolvedAlgoliaId) return;
|
|
5630
|
+
if (activateLoading) return;
|
|
5631
|
+
autoActivateFiredRef.current = key;
|
|
5632
|
+
setAutoActivatePulse(true);
|
|
5633
|
+
handleActivateToggle({ silent: true }).finally(() => {
|
|
5634
|
+
setTimeout(() => setAutoActivatePulse(false), 1200);
|
|
5635
|
+
});
|
|
5636
|
+
}, [open, autoActivate, appName, isActivated, resolvedAlgoliaId, activateLoading]);
|
|
5637
|
+
useEffect7(() => {
|
|
5638
|
+
if (!open) {
|
|
5639
|
+
autoActivateFiredRef.current = null;
|
|
5640
|
+
setAutoActivatePulse(false);
|
|
5641
|
+
}
|
|
5642
|
+
}, [open, appName]);
|
|
5557
5643
|
const isLoadingAll = appLoading || isAuthenticated && appAuthLoading;
|
|
5558
5644
|
return /* @__PURE__ */ jsxs9(
|
|
5559
5645
|
Drawer,
|
|
@@ -5629,7 +5715,8 @@ function AppDetailDrawer({
|
|
|
5629
5715
|
categories: appInfo?.categories,
|
|
5630
5716
|
isActivated: onAddToCanvas ? null : effectiveActivated,
|
|
5631
5717
|
activateLoading,
|
|
5632
|
-
onActivateToggle: handleActivateToggle,
|
|
5718
|
+
onActivateToggle: () => handleActivateToggle(),
|
|
5719
|
+
highlightActivate: autoActivatePulse,
|
|
5633
5720
|
onAdd: onAddToCanvas && appName ? () => {
|
|
5634
5721
|
onAddToCanvas({ name: appName, icon: resolvedImage || "", algoliaId: resolvedAlgoliaId });
|
|
5635
5722
|
onClose();
|
|
@@ -5733,7 +5820,7 @@ function AppDetailDrawer({
|
|
|
5733
5820
|
}
|
|
5734
5821
|
|
|
5735
5822
|
// views/ShuffleMCP.tsx
|
|
5736
|
-
import "./shuffle-mcp-
|
|
5823
|
+
import "./shuffle-mcp-TWJGPBOQ.css";
|
|
5737
5824
|
|
|
5738
5825
|
// components/SegmentedControl.tsx
|
|
5739
5826
|
import * as React2 from "react";
|
|
@@ -5900,7 +5987,7 @@ function SegmentedControl({
|
|
|
5900
5987
|
children: opt.label
|
|
5901
5988
|
}
|
|
5902
5989
|
),
|
|
5903
|
-
!isAction && typeof opt.count === "number" && /* @__PURE__ */ jsx13(
|
|
5990
|
+
!isAction && (typeof opt.count === "number" || typeof opt.count === "string") && /* @__PURE__ */ jsx13(
|
|
5904
5991
|
"span",
|
|
5905
5992
|
{
|
|
5906
5993
|
style: {
|
|
@@ -6399,8 +6486,8 @@ var ShuffleMCP = React3.forwardRef(({
|
|
|
6399
6486
|
value: sourceFilter,
|
|
6400
6487
|
onChange: (v) => setSourceFilter(v),
|
|
6401
6488
|
options: [
|
|
6402
|
-
{ value: "all", label: "All", count: results.length + filteredPrivateApps.length, title: "All available apps \u2014 both the public catalog and your private apps." },
|
|
6403
|
-
{ value: "public", label: "Public", count: results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6489
|
+
{ 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." },
|
|
6490
|
+
{ value: "public", label: "Public", count: results.length >= hitsPerPage ? `${results.length}+` : results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6404
6491
|
{ 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." },
|
|
6405
6492
|
{ 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." }
|
|
6406
6493
|
]
|
|
@@ -6577,9 +6664,11 @@ function AppSearchDrawer({
|
|
|
6577
6664
|
pinnedApps,
|
|
6578
6665
|
highlightAppName,
|
|
6579
6666
|
highlightDelayMs = 5e3,
|
|
6667
|
+
realtimeHighlightAppNames,
|
|
6580
6668
|
multiSelect = false,
|
|
6581
6669
|
selectedApps,
|
|
6582
6670
|
onSelectionChange,
|
|
6671
|
+
autoActivate = false,
|
|
6583
6672
|
globalUrl,
|
|
6584
6673
|
theme,
|
|
6585
6674
|
colorMode
|
|
@@ -6838,6 +6927,41 @@ function AppSearchDrawer({
|
|
|
6838
6927
|
"0%, 100%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 12px 1px hsl(var(--primary) / 0.4)" },
|
|
6839
6928
|
"50%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 24px 4px hsl(var(--primary) / 0.75)" }
|
|
6840
6929
|
}
|
|
6930
|
+
} : {},
|
|
6931
|
+
...realtimeHighlightAppNames && realtimeHighlightAppNames.length > 0 ? {
|
|
6932
|
+
[realtimeHighlightAppNames.map((n) => `& .singul-dropdown-item[data-app-name="${n}"]`).join(", ")]: {
|
|
6933
|
+
position: "relative",
|
|
6934
|
+
zIndex: 2,
|
|
6935
|
+
borderColor: "hsl(var(--primary) / 0.78) !important",
|
|
6936
|
+
backgroundColor: "hsl(var(--primary) / 0.08) !important",
|
|
6937
|
+
outline: "none !important",
|
|
6938
|
+
boxShadow: "none !important",
|
|
6939
|
+
animation: "shuffleHighlightPulseStrong 1.5s ease-in-out infinite",
|
|
6940
|
+
transition: "border-color 120ms ease, background-color 120ms ease",
|
|
6941
|
+
"&::before": {
|
|
6942
|
+
content: '""',
|
|
6943
|
+
position: "absolute",
|
|
6944
|
+
left: "10px",
|
|
6945
|
+
top: "14px",
|
|
6946
|
+
bottom: "14px",
|
|
6947
|
+
width: "3px",
|
|
6948
|
+
borderRadius: "999px",
|
|
6949
|
+
backgroundColor: "hsl(var(--primary))"
|
|
6950
|
+
},
|
|
6951
|
+
"& .singul-app-info": {
|
|
6952
|
+
paddingLeft: "8px"
|
|
6953
|
+
}
|
|
6954
|
+
},
|
|
6955
|
+
"@keyframes shuffleHighlightPulseStrong": {
|
|
6956
|
+
"0%, 100%": {
|
|
6957
|
+
borderColor: "hsl(var(--primary) / 0.62)",
|
|
6958
|
+
backgroundColor: "hsl(var(--primary) / 0.06)"
|
|
6959
|
+
},
|
|
6960
|
+
"50%": {
|
|
6961
|
+
borderColor: "hsl(var(--primary) / 0.92)",
|
|
6962
|
+
backgroundColor: "hsl(var(--primary) / 0.12)"
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6841
6965
|
} : {}
|
|
6842
6966
|
},
|
|
6843
6967
|
children: /* @__PURE__ */ jsx15(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsx15(
|
|
@@ -6860,8 +6984,9 @@ function AppSearchDrawer({
|
|
|
6860
6984
|
layout: "grid",
|
|
6861
6985
|
gridColumns: 2,
|
|
6862
6986
|
inline: true,
|
|
6987
|
+
initialQuery,
|
|
6863
6988
|
initialFilterQuery: initialQuery,
|
|
6864
|
-
hitsPerPage:
|
|
6989
|
+
hitsPerPage: 20,
|
|
6865
6990
|
showDescription: false,
|
|
6866
6991
|
showCategories: true,
|
|
6867
6992
|
showCheckbox: multiSelect,
|
|
@@ -6952,7 +7077,8 @@ function AppSearchDrawer({
|
|
|
6952
7077
|
theme,
|
|
6953
7078
|
colorMode,
|
|
6954
7079
|
onRefresh: onClose,
|
|
6955
|
-
onAddToCanvas
|
|
7080
|
+
onAddToCanvas,
|
|
7081
|
+
autoActivate
|
|
6956
7082
|
}
|
|
6957
7083
|
)
|
|
6958
7084
|
] });
|
|
@@ -7219,7 +7345,7 @@ function ShufflePipelinesBanner() {
|
|
|
7219
7345
|
var ShufflePipelinesBanner_default = ShufflePipelinesBanner;
|
|
7220
7346
|
|
|
7221
7347
|
// components/AgentUI.tsx
|
|
7222
|
-
import { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef8, useState as useState12 } from "react";
|
|
7348
|
+
import React4, { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef8, useState as useState12 } from "react";
|
|
7223
7349
|
import {
|
|
7224
7350
|
Plus as AddIcon3,
|
|
7225
7351
|
Paperclip as AttachFileIcon,
|
|
@@ -7240,7 +7366,8 @@ import {
|
|
|
7240
7366
|
CircleStop as StopCircleIcon,
|
|
7241
7367
|
ThumbsDown as ThumbDownIcon,
|
|
7242
7368
|
ThumbsUp as ThumbUpIcon,
|
|
7243
|
-
AlertTriangle as WarningIcon
|
|
7369
|
+
AlertTriangle as WarningIcon,
|
|
7370
|
+
Search as SearchIcon
|
|
7244
7371
|
} from "lucide-react";
|
|
7245
7372
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
|
7246
7373
|
import {
|
|
@@ -7250,16 +7377,182 @@ import {
|
|
|
7250
7377
|
Button as Button8,
|
|
7251
7378
|
Chip as Chip7,
|
|
7252
7379
|
CircularProgress as CircularProgress4,
|
|
7380
|
+
ClickAwayListener,
|
|
7253
7381
|
IconButton as IconButton8,
|
|
7254
7382
|
InputBase as InputBase2,
|
|
7255
7383
|
MenuItem as MenuItem2,
|
|
7384
|
+
MenuList,
|
|
7385
|
+
Paper,
|
|
7256
7386
|
Popover,
|
|
7387
|
+
Popper,
|
|
7257
7388
|
Select as Select2,
|
|
7258
7389
|
TextField as TextField5,
|
|
7259
7390
|
Tooltip as Tooltip9,
|
|
7260
7391
|
Typography as Typography13
|
|
7261
7392
|
} from "@mui/material";
|
|
7262
7393
|
import Markdown from "react-markdown";
|
|
7394
|
+
|
|
7395
|
+
// components/agentPromptSuggestions.ts
|
|
7396
|
+
var AGENT_PROMPT_SUGGESTIONS = [
|
|
7397
|
+
// — Email & comms ————————————————————————————————————————————————
|
|
7398
|
+
"Take care of my emails by pretending to be me and answering them",
|
|
7399
|
+
"Triage my inbox every hour and draft replies for anything urgent",
|
|
7400
|
+
"Summarise my unread emails from the last 24 hours and rank them by importance",
|
|
7401
|
+
"Forward any phishing-looking emails in my inbox to the security team and quarantine them",
|
|
7402
|
+
"Reply to scheduling requests in my inbox using my working hours and calendar availability",
|
|
7403
|
+
"Every morning, send me a digest of overnight emails grouped by sender and topic",
|
|
7404
|
+
"Auto-unsubscribe from marketing emails I have not opened in 60 days",
|
|
7405
|
+
"Snooze low-priority newsletters until Friday afternoon",
|
|
7406
|
+
"Flag and archive shipping notifications once the package is delivered",
|
|
7407
|
+
"Clean up my inbox by archiving anything older than 30 days that I have already read",
|
|
7408
|
+
// — Calendar & meetings ————————————————————————————————————————————
|
|
7409
|
+
"Block focus time on my calendar every weekday morning between 9 and 11",
|
|
7410
|
+
"Decline meetings that conflict with my focus blocks and propose alternatives",
|
|
7411
|
+
"Send me a daily agenda every weekday at 8am with prep notes per meeting",
|
|
7412
|
+
"Reschedule any meeting without an agenda 24 hours before it starts",
|
|
7413
|
+
"Send meeting notes and action items to all attendees after every call",
|
|
7414
|
+
"Find a 30-minute slot this week that works for me and the people I mention",
|
|
7415
|
+
"Cancel recurring meetings that I have skipped 3 times in a row",
|
|
7416
|
+
"Remind me 15 minutes before any meeting that I have not prepared for",
|
|
7417
|
+
// — Incidents & SOC operations ———————————————————————————————————
|
|
7418
|
+
"Triage new incidents every 15 minutes and assign severity, owner, and next steps",
|
|
7419
|
+
"Watch for new critical incidents and page the on-call engineer immediately",
|
|
7420
|
+
"Close incidents older than 30 days that have had no activity and no observables",
|
|
7421
|
+
"Merge duplicate incidents that share the same observable or hostname",
|
|
7422
|
+
"Enrich every new incident with threat intel and asset context within 2 minutes",
|
|
7423
|
+
"Auto-acknowledge incidents from known maintenance windows and link them to the change ticket",
|
|
7424
|
+
"Summarise yesterday's incidents into a daily standup brief for the SOC team",
|
|
7425
|
+
"Escalate any incident that breaches its SLA to the team lead",
|
|
7426
|
+
"Tag every incident with the MITRE ATT&CK technique that best matches its observables",
|
|
7427
|
+
"Watch the alert queue and group related alerts into a single incident",
|
|
7428
|
+
"Auto-resolve incidents whose root cause matches a previously closed incident",
|
|
7429
|
+
"Reopen any closed incident if the same observable shows up again within 7 days",
|
|
7430
|
+
"Send a weekly incident trend report every Monday morning to the security leadership",
|
|
7431
|
+
// — Threat intel & IOCs —————————————————————————————————————————
|
|
7432
|
+
"Pull new IOCs from my threat feeds every hour and push them to the firewall blocklist",
|
|
7433
|
+
"Check every external IP in today's incidents against VirusTotal and AbuseIPDB",
|
|
7434
|
+
"Sweep the environment for any host that has connected to a known bad domain in the last 7 days",
|
|
7435
|
+
"Subscribe to new CISA advisories and turn them into detection rules where possible",
|
|
7436
|
+
"Cross-reference observed file hashes against MalwareBazaar daily",
|
|
7437
|
+
"Watch for newly registered domains that look like our brand and report them",
|
|
7438
|
+
"Alert me whenever a new CVE with a known exploit affects software in our inventory",
|
|
7439
|
+
"Refresh the IOC datastore every 6 hours and prune entries older than 30 days",
|
|
7440
|
+
// — Detection engineering ———————————————————————————————————————
|
|
7441
|
+
"Review noisy detection rules every week and propose tuning suggestions",
|
|
7442
|
+
"Convert the latest Sigma rules from the public repo into our SIEM's format and stage them for review",
|
|
7443
|
+
"Tell me which detection rules have not fired in the last 90 days so I can retire them",
|
|
7444
|
+
"Audit MITRE ATT&CK coverage every Monday and flag techniques with zero detections",
|
|
7445
|
+
"Backtest new detection rules against the last 30 days of logs before promoting them to production",
|
|
7446
|
+
// — SIEM operations ———————————————————————————————————————————
|
|
7447
|
+
"Triage new Splunk alerts every 10 minutes and assign severity, owner, and next steps",
|
|
7448
|
+
"Watch Microsoft Sentinel for high-severity incidents and page the on-call analyst immediately",
|
|
7449
|
+
"Suppress noisy SIEM alerts that fire more than 50 times per hour and open a tuning ticket",
|
|
7450
|
+
"Correlate failed login spikes in the SIEM with VPN logs and flag possible brute-force attempts",
|
|
7451
|
+
"Hunt the SIEM every morning for sign-ins from countries we do not operate in",
|
|
7452
|
+
"Forward critical SIEM detections straight to Case Management and skip the alert queue",
|
|
7453
|
+
"Run a weekly SIEM data-source health check and alert me on any log source silent for over 1 hour",
|
|
7454
|
+
"Enrich every SIEM alert with asset owner, criticality, and recent vulnerabilities before triage",
|
|
7455
|
+
"Search the SIEM for the latest IOCs from threat intel feeds every 30 minutes",
|
|
7456
|
+
"Summarise top 10 noisiest SIEM rules every Friday and propose tuning candidates",
|
|
7457
|
+
"Detect lateral movement patterns in SIEM auth logs and open an incident with the affected hosts",
|
|
7458
|
+
"Watch the SIEM for any disable or delete of audit logging and treat it as a critical incident",
|
|
7459
|
+
// — EDR operations ————————————————————————————————————————————
|
|
7460
|
+
"Isolate any endpoint that triggers a critical CrowdStrike alert and notify the user's manager",
|
|
7461
|
+
"Kill any process on a flagged host that matches a known malware family in EDR telemetry",
|
|
7462
|
+
"Watch SentinelOne for ransomware behavior detections and auto-contain the host within 60 seconds",
|
|
7463
|
+
"Pull the process tree from EDR for every malware detection and attach it to the incident",
|
|
7464
|
+
"Sweep all endpoints for a given hash or filename when a new IOC arrives and report matches",
|
|
7465
|
+
"Detect newly created local admin accounts on any endpoint and require approval before keeping them",
|
|
7466
|
+
"Alert when an EDR agent goes offline for more than 1 hour and open a ticket against the asset owner",
|
|
7467
|
+
"Quarantine any binary flagged as suspicious by EDR and email the user with next steps",
|
|
7468
|
+
"Hunt EDR telemetry every night for LOLBins executed from user-writable directories",
|
|
7469
|
+
"Correlate EDR alerts with SIEM auth events to detect credential theft followed by execution",
|
|
7470
|
+
"Run a weekly EDR coverage report and list endpoints without an active agent",
|
|
7471
|
+
"Auto-resolve EDR alerts that match a known-good signed binary on our allowlist",
|
|
7472
|
+
// — Vulnerability management ————————————————————————————————————
|
|
7473
|
+
"Scan our asset inventory daily and open tickets for any new critical or high vulnerability",
|
|
7474
|
+
"Remind asset owners every Friday about open vulnerabilities older than 14 days",
|
|
7475
|
+
"Re-scan hosts that recently patched a critical vulnerability and close the ticket if clean",
|
|
7476
|
+
"Send the patch compliance report every Monday morning to IT and security leadership",
|
|
7477
|
+
"Correlate vulnerabilities with active exploits in the wild and re-prioritise the queue",
|
|
7478
|
+
// — Endpoint & host monitoring ———————————————————————————————————
|
|
7479
|
+
"Watch my host monitors and alert me if any agent goes offline for more than 1 hour",
|
|
7480
|
+
"Isolate any endpoint that triggers a critical EDR alert and notify the user's manager",
|
|
7481
|
+
"Kill any process on a flagged host that matches a known malware family",
|
|
7482
|
+
"Run an inventory of installed software on every endpoint every Sunday",
|
|
7483
|
+
"Detect new local admin accounts created on any endpoint and require approval",
|
|
7484
|
+
"Make sure full-disk encryption is on for every laptop and report exceptions weekly",
|
|
7485
|
+
// — Identity & access —————————————————————————————————————————
|
|
7486
|
+
"Review user access every quarter and flag anyone with privileges they have not used in 90 days",
|
|
7487
|
+
"Disable accounts that have not logged in for 60 days and notify their manager",
|
|
7488
|
+
"Watch for impossible travel sign-ins and force a password reset plus MFA re-enrolment",
|
|
7489
|
+
"Alert me whenever someone is added to an admin group and require justification within 24 hours",
|
|
7490
|
+
"Audit MFA enrolment weekly and email any user without a second factor",
|
|
7491
|
+
"Rotate service account credentials every 90 days and update the vault",
|
|
7492
|
+
"Detect dormant API keys older than 180 days and revoke them after notice",
|
|
7493
|
+
"Make sure new joiners get baseline access provisioned within 1 hour of their start date",
|
|
7494
|
+
"Make sure leavers have all access revoked within 15 minutes of their termination event",
|
|
7495
|
+
// — Cloud, infra & posture ————————————————————————————————————
|
|
7496
|
+
"Check our cloud accounts every hour for public S3 buckets and lock them down",
|
|
7497
|
+
"Detect new IAM roles with wildcard permissions and require review before they go live",
|
|
7498
|
+
"Watch for unencrypted databases in production and open a ticket against the owner",
|
|
7499
|
+
"Run a CIS benchmark scan against all production cloud accounts every Sunday",
|
|
7500
|
+
"Alert on any new security group that opens ports to 0.0.0.0/0",
|
|
7501
|
+
"Monitor cloud spend daily and warn me if any service's cost jumps more than 50% week-over-week",
|
|
7502
|
+
"Check certificate expiry across our domains weekly and renew anything within 30 days",
|
|
7503
|
+
"Watch our DNS records for unauthorised changes and revert them",
|
|
7504
|
+
// — Phishing & user reports ———————————————————————————————————
|
|
7505
|
+
"Investigate phishing reports from the abuse mailbox and respond to the reporter within 1 hour",
|
|
7506
|
+
"Detonate suspicious attachments in a sandbox and attach the verdict to the incident",
|
|
7507
|
+
"Pull URLs from reported phishing emails and submit them to URLhaus and PhishTank",
|
|
7508
|
+
"Send a phishing simulation to a sample of users every month and report results",
|
|
7509
|
+
// — Compliance, audit & reporting —————————————————————————————
|
|
7510
|
+
"Generate the SOC2 evidence pack at the start of every month",
|
|
7511
|
+
"Track changes to security policies and alert the GRC team when one is edited",
|
|
7512
|
+
"Send a weekly KPI report covering MTTD, MTTR, and open incident backlog",
|
|
7513
|
+
"Audit log retention every Sunday and confirm we still meet the 1-year requirement",
|
|
7514
|
+
"Generate a monthly executive summary of incidents, vulnerabilities, and detection coverage",
|
|
7515
|
+
// — Backups, DR & uptime ————————————————————————————————————
|
|
7516
|
+
"Verify nightly backups completed successfully and alert me if any failed",
|
|
7517
|
+
"Test restore from backup on a sample workload every month and report results",
|
|
7518
|
+
"Watch our public status page for incidents at our critical vendors and notify the team",
|
|
7519
|
+
"Ping our public endpoints every minute and open an incident if any return non-2xx for 3 minutes",
|
|
7520
|
+
// — Tickets, workflow & docs ——————————————————————————————————
|
|
7521
|
+
"Triage new Jira tickets in the security project every hour and assign by category",
|
|
7522
|
+
"Close tickets that have been waiting on the reporter for more than 14 days",
|
|
7523
|
+
"Summarise this week's closed tickets into release notes every Friday",
|
|
7524
|
+
"Pull action items out of meeting notes I share and create tickets for them",
|
|
7525
|
+
"Keep the on-call runbook in sync with the latest incident postmortems",
|
|
7526
|
+
"Review pull requests in our security repos and leave a summary comment within an hour",
|
|
7527
|
+
// — People, HR & onboarding ————————————————————————————————————
|
|
7528
|
+
"Send a welcome message and security training link to every new joiner on their start date",
|
|
7529
|
+
"Run the offboarding checklist whenever someone is marked as a leaver in HR",
|
|
7530
|
+
"Remind managers to complete quarterly performance reviews 1 week before the deadline",
|
|
7531
|
+
"Send birthday and work anniversary greetings from me on the right day",
|
|
7532
|
+
// — Personal / lightweight ops chores —————————————————————————
|
|
7533
|
+
"Order more office coffee whenever the inventory drops below 2 bags",
|
|
7534
|
+
"File my receipts every Friday and submit the expense report",
|
|
7535
|
+
"Track my open invoices and chase clients whose payment is more than 14 days overdue",
|
|
7536
|
+
"Send a polite follow-up to anyone I have emailed but who has not replied in 5 working days",
|
|
7537
|
+
"Read the security news feeds every morning and summarise the top 5 stories for me"
|
|
7538
|
+
];
|
|
7539
|
+
var matchAgentPromptSuggestions = (input, limit = 8) => {
|
|
7540
|
+
const q = (input || "").trim().toLowerCase();
|
|
7541
|
+
if (!q) return [];
|
|
7542
|
+
const scored = [];
|
|
7543
|
+
for (const text of AGENT_PROMPT_SUGGESTIONS) {
|
|
7544
|
+
const lower = text.toLowerCase();
|
|
7545
|
+
const idx = lower.indexOf(q);
|
|
7546
|
+
if (idx < 0) continue;
|
|
7547
|
+
const score = idx === 0 ? -1e3 + text.length : idx * 10 + text.length;
|
|
7548
|
+
scored.push({ text, score });
|
|
7549
|
+
}
|
|
7550
|
+
scored.sort((a, b) => a.score - b.score);
|
|
7551
|
+
return scored.slice(0, limit).map((s) => s.text);
|
|
7552
|
+
};
|
|
7553
|
+
var DEFAULT_AGENT_PROMPT_PLACEHOLDER = "Take care of my emails by pretending to be me and answering them";
|
|
7554
|
+
|
|
7555
|
+
// components/AgentUI.tsx
|
|
7263
7556
|
import remarkGfm4 from "remark-gfm";
|
|
7264
7557
|
import remarkBreaks from "remark-breaks";
|
|
7265
7558
|
import JsonView2 from "react18-json-view";
|
|
@@ -9193,7 +9486,7 @@ var AgentUI = ({
|
|
|
9193
9486
|
autoLoadApps = true,
|
|
9194
9487
|
title = "What do you want to do?",
|
|
9195
9488
|
subtitle,
|
|
9196
|
-
placeholder =
|
|
9489
|
+
placeholder = DEFAULT_AGENT_PROMPT_PLACEHOLDER,
|
|
9197
9490
|
defaultInput = "",
|
|
9198
9491
|
autoSubmit = false,
|
|
9199
9492
|
hideHeroIcon = false,
|
|
@@ -9245,6 +9538,29 @@ var AgentUI = ({
|
|
|
9245
9538
|
const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
|
|
9246
9539
|
const navigate = useNavigate();
|
|
9247
9540
|
const [actionInput, setActionInput] = useState12(defaultInput);
|
|
9541
|
+
const promptAnchorRef = React4.useRef(null);
|
|
9542
|
+
const [suggestionsDismissed, setSuggestionsDismissed] = useState12(false);
|
|
9543
|
+
const [suggestionIndex, setSuggestionIndex] = useState12(-1);
|
|
9544
|
+
const promptSuggestions = useMemo6(
|
|
9545
|
+
() => matchAgentPromptSuggestions(actionInput, 8),
|
|
9546
|
+
[actionInput]
|
|
9547
|
+
);
|
|
9548
|
+
useEffect11(() => {
|
|
9549
|
+
setSuggestionIndex(-1);
|
|
9550
|
+
setSuggestionsDismissed(false);
|
|
9551
|
+
}, [actionInput]);
|
|
9552
|
+
const suggestionsOpen = promptSuggestions.length > 0 && !suggestionsDismissed;
|
|
9553
|
+
const acceptSuggestion = useCallback8((s) => {
|
|
9554
|
+
setActionInput(s);
|
|
9555
|
+
setSuggestionsDismissed(true);
|
|
9556
|
+
setSuggestionIndex(-1);
|
|
9557
|
+
requestAnimationFrame(() => {
|
|
9558
|
+
try {
|
|
9559
|
+
inputRef.current?.focus();
|
|
9560
|
+
} catch {
|
|
9561
|
+
}
|
|
9562
|
+
});
|
|
9563
|
+
}, []);
|
|
9248
9564
|
const BUILTIN_DEFAULT_APPS = [
|
|
9249
9565
|
{ name: "http" },
|
|
9250
9566
|
{ name: "shuffle_tools" }
|
|
@@ -10238,6 +10554,34 @@ var AgentUI = ({
|
|
|
10238
10554
|
}
|
|
10239
10555
|
}, [submitOverride, actionInput, chosenApps, submitInput]);
|
|
10240
10556
|
const onKeyDown = (e) => {
|
|
10557
|
+
if (suggestionsOpen && promptSuggestions.length > 0) {
|
|
10558
|
+
if (e.key === "ArrowDown") {
|
|
10559
|
+
e.preventDefault();
|
|
10560
|
+
setSuggestionIndex((i) => (i + 1) % promptSuggestions.length);
|
|
10561
|
+
return;
|
|
10562
|
+
}
|
|
10563
|
+
if (e.key === "ArrowUp") {
|
|
10564
|
+
e.preventDefault();
|
|
10565
|
+
setSuggestionIndex((i) => i <= 0 ? promptSuggestions.length - 1 : i - 1);
|
|
10566
|
+
return;
|
|
10567
|
+
}
|
|
10568
|
+
if (e.key === "Escape") {
|
|
10569
|
+
e.preventDefault();
|
|
10570
|
+
setSuggestionsDismissed(true);
|
|
10571
|
+
setSuggestionIndex(-1);
|
|
10572
|
+
return;
|
|
10573
|
+
}
|
|
10574
|
+
if (e.key === "Tab" && suggestionIndex >= 0) {
|
|
10575
|
+
e.preventDefault();
|
|
10576
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10577
|
+
return;
|
|
10578
|
+
}
|
|
10579
|
+
if (e.key === "Enter" && suggestionIndex >= 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
|
10580
|
+
e.preventDefault();
|
|
10581
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10582
|
+
return;
|
|
10583
|
+
}
|
|
10584
|
+
}
|
|
10241
10585
|
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
10242
10586
|
e.preventDefault();
|
|
10243
10587
|
handlePrimarySubmit();
|
|
@@ -10895,7 +11239,7 @@ var AgentUI = ({
|
|
|
10895
11239
|
mt: -1,
|
|
10896
11240
|
maxWidth: 600
|
|
10897
11241
|
}, children: subtitle }),
|
|
10898
|
-
/* @__PURE__ */ jsxs17(Box14, { sx: {
|
|
11242
|
+
/* @__PURE__ */ jsxs17(Box14, { ref: promptAnchorRef, sx: {
|
|
10899
11243
|
width: "100%",
|
|
10900
11244
|
display: "flex",
|
|
10901
11245
|
flexDirection: "column",
|
|
@@ -11103,6 +11447,67 @@ var AgentUI = ({
|
|
|
11103
11447
|
) }) })
|
|
11104
11448
|
] })
|
|
11105
11449
|
] }),
|
|
11450
|
+
/* @__PURE__ */ jsx20(
|
|
11451
|
+
Popper,
|
|
11452
|
+
{
|
|
11453
|
+
open: suggestionsOpen,
|
|
11454
|
+
anchorEl: promptAnchorRef.current,
|
|
11455
|
+
placement: "bottom-start",
|
|
11456
|
+
style: { zIndex: 1300, width: promptAnchorRef.current?.offsetWidth },
|
|
11457
|
+
modifiers: [{ name: "offset", options: { offset: [0, 6] } }],
|
|
11458
|
+
children: /* @__PURE__ */ jsx20(ClickAwayListener, { onClickAway: () => setSuggestionsDismissed(true), children: /* @__PURE__ */ jsx20(
|
|
11459
|
+
Paper,
|
|
11460
|
+
{
|
|
11461
|
+
elevation: 6,
|
|
11462
|
+
sx: {
|
|
11463
|
+
bgcolor: "hsl(var(--card))",
|
|
11464
|
+
border: "1px solid hsl(var(--border))",
|
|
11465
|
+
borderRadius: 2,
|
|
11466
|
+
overflow: "hidden",
|
|
11467
|
+
maxHeight: 320,
|
|
11468
|
+
overflowY: "auto"
|
|
11469
|
+
},
|
|
11470
|
+
children: /* @__PURE__ */ jsx20(MenuList, { dense: true, disablePadding: true, children: promptSuggestions.map((s, i) => {
|
|
11471
|
+
const q = actionInput.trim();
|
|
11472
|
+
const lower = s.toLowerCase();
|
|
11473
|
+
const idx = q ? lower.indexOf(q.toLowerCase()) : -1;
|
|
11474
|
+
const before = idx >= 0 ? s.slice(0, idx) : s;
|
|
11475
|
+
const match = idx >= 0 ? s.slice(idx, idx + q.length) : "";
|
|
11476
|
+
const after = idx >= 0 ? s.slice(idx + q.length) : "";
|
|
11477
|
+
return /* @__PURE__ */ jsxs17(
|
|
11478
|
+
MenuItem2,
|
|
11479
|
+
{
|
|
11480
|
+
selected: i === suggestionIndex,
|
|
11481
|
+
onMouseEnter: () => setSuggestionIndex(i),
|
|
11482
|
+
onMouseDown: (e) => {
|
|
11483
|
+
e.preventDefault();
|
|
11484
|
+
acceptSuggestion(s);
|
|
11485
|
+
},
|
|
11486
|
+
sx: {
|
|
11487
|
+
fontSize: "0.88rem",
|
|
11488
|
+
color: "hsl(var(--foreground))",
|
|
11489
|
+
py: 0.75,
|
|
11490
|
+
px: 2,
|
|
11491
|
+
"&.Mui-selected, &.Mui-selected:hover": {
|
|
11492
|
+
bgcolor: "hsl(var(--muted) / 0.6)"
|
|
11493
|
+
}
|
|
11494
|
+
},
|
|
11495
|
+
children: [
|
|
11496
|
+
/* @__PURE__ */ jsx20(SearchIcon, { size: 14, style: { marginRight: 10, color: "hsl(var(--muted-foreground))", flexShrink: 0 } }),
|
|
11497
|
+
/* @__PURE__ */ jsxs17(Box14, { component: "span", sx: { whiteSpace: "normal", lineHeight: 1.4 }, children: [
|
|
11498
|
+
before,
|
|
11499
|
+
/* @__PURE__ */ jsx20(Box14, { component: "span", sx: { fontWeight: 700, color: "hsl(var(--foreground))" }, children: match }),
|
|
11500
|
+
after
|
|
11501
|
+
] })
|
|
11502
|
+
]
|
|
11503
|
+
},
|
|
11504
|
+
s
|
|
11505
|
+
);
|
|
11506
|
+
}) })
|
|
11507
|
+
}
|
|
11508
|
+
) })
|
|
11509
|
+
}
|
|
11510
|
+
),
|
|
11106
11511
|
!hideAppPicker && /* @__PURE__ */ jsx20(Box14, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs17(Box14, { sx: {
|
|
11107
11512
|
display: "inline-flex",
|
|
11108
11513
|
flexWrap: "wrap",
|
|
@@ -11959,6 +12364,32 @@ var ENDPOINT_PRESETS = [
|
|
|
11959
12364
|
{ 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." },
|
|
11960
12365
|
{ label: CUSTOM_PRESET, url: "" }
|
|
11961
12366
|
];
|
|
12367
|
+
var PROVIDER_DOMAINS = {
|
|
12368
|
+
"Shuffle AI": "shuffler.io",
|
|
12369
|
+
OpenAI: "openai.com",
|
|
12370
|
+
Anthropic: "anthropic.com",
|
|
12371
|
+
"Google Gemini": "gemini.google.com",
|
|
12372
|
+
Mistral: "mistral.ai",
|
|
12373
|
+
Groq: "groq.com",
|
|
12374
|
+
DeepSeek: "deepseek.com",
|
|
12375
|
+
"Together AI": "together.ai",
|
|
12376
|
+
OpenRouter: "openrouter.ai",
|
|
12377
|
+
"Ollama (localhost)": "ollama.com",
|
|
12378
|
+
"LM Studio (localhost)": "lmstudio.ai"
|
|
12379
|
+
};
|
|
12380
|
+
var ProviderLogo = ({ label, url }) => {
|
|
12381
|
+
const [errored, setErrored] = useState13(false);
|
|
12382
|
+
let domain = PROVIDER_DOMAINS[label];
|
|
12383
|
+
if (!domain && url) {
|
|
12384
|
+
try {
|
|
12385
|
+
domain = new URL(url).hostname.replace(/^www\./, "");
|
|
12386
|
+
} catch {
|
|
12387
|
+
}
|
|
12388
|
+
}
|
|
12389
|
+
const src = domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
12390
|
+
const initial = label.trim().charAt(0).toUpperCase() || "?";
|
|
12391
|
+
return /* @__PURE__ */ jsx22(Box16, { 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__ */ jsx22("img", { src, alt: "", width: 18, height: 18, style: { display: "block" }, onError: () => setErrored(true) }) : /* @__PURE__ */ jsx22(Typography15, { sx: { fontSize: "0.65rem", fontWeight: 600, color: "hsl(var(--muted-foreground))", lineHeight: 1 }, children: initial }) });
|
|
12392
|
+
};
|
|
11962
12393
|
var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode }) => {
|
|
11963
12394
|
useSyncHostBaseUrl(globalUrl);
|
|
11964
12395
|
const { authStates, authenticatedApps, handleAuthChange, handleTestConnection, handleSaveAuth, refreshAuth } = useAppAuth();
|
|
@@ -12102,12 +12533,28 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12102
12533
|
isOptionEqualToValue: (opt, val) => opt === val,
|
|
12103
12534
|
renderOption: (props, option) => {
|
|
12104
12535
|
const preset = ENDPOINT_PRESETS.find((p) => p.label === option);
|
|
12105
|
-
return /* @__PURE__ */ createElement2("li", { ...props, key: option }, /* @__PURE__ */ jsxs19(Box16, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%", minWidth: 0 }, children: [
|
|
12536
|
+
return /* @__PURE__ */ createElement2("li", { ...props, key: option }, /* @__PURE__ */ jsxs19(Box16, { sx: { display: "flex", alignItems: "center", gap: 1.25, width: "100%", minWidth: 0 }, children: [
|
|
12537
|
+
/* @__PURE__ */ jsx22(ProviderLogo, { label: option, url: preset?.url }),
|
|
12106
12538
|
/* @__PURE__ */ jsx22(Typography15, { sx: { fontSize: "0.85rem", color: "hsl(var(--popover-foreground))" }, children: option }),
|
|
12107
12539
|
preset?.url && /* @__PURE__ */ jsx22(Typography15, { component: "span", sx: { ml: "auto", color: "hsl(var(--muted-foreground))", fontSize: "0.75rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: preset.url })
|
|
12108
12540
|
] }));
|
|
12109
12541
|
},
|
|
12110
|
-
renderInput: (params) =>
|
|
12542
|
+
renderInput: (params) => {
|
|
12543
|
+
const preset = ENDPOINT_PRESETS.find((p) => p.label === effectivePreset);
|
|
12544
|
+
return /* @__PURE__ */ jsx22(
|
|
12545
|
+
TextField6,
|
|
12546
|
+
{
|
|
12547
|
+
...params,
|
|
12548
|
+
placeholder: "Search a provider\u2026",
|
|
12549
|
+
slotProps: {
|
|
12550
|
+
input: {
|
|
12551
|
+
...params.InputProps,
|
|
12552
|
+
startAdornment: effectivePreset ? /* @__PURE__ */ jsx22(Box16, { sx: { display: "flex", alignItems: "center", pl: 0.5, mr: 0.5 }, children: /* @__PURE__ */ jsx22(ProviderLogo, { label: effectivePreset, url: preset?.url }) }) : void 0
|
|
12553
|
+
}
|
|
12554
|
+
}
|
|
12555
|
+
}
|
|
12556
|
+
);
|
|
12557
|
+
},
|
|
12111
12558
|
slotProps: {
|
|
12112
12559
|
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
12113
12560
|
popper: { sx: { zIndex: 9999 } }
|
|
@@ -12451,7 +12898,7 @@ import {
|
|
|
12451
12898
|
Server as Server2,
|
|
12452
12899
|
XCircle,
|
|
12453
12900
|
Zap,
|
|
12454
|
-
Search as
|
|
12901
|
+
Search as SearchIcon2
|
|
12455
12902
|
} from "lucide-react";
|
|
12456
12903
|
|
|
12457
12904
|
// agentActivity.ts
|
|
@@ -13097,17 +13544,20 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13097
13544
|
] })
|
|
13098
13545
|
] })
|
|
13099
13546
|
] }),
|
|
13100
|
-
|
|
13547
|
+
/* @__PURE__ */ jsx24(
|
|
13101
13548
|
Box18,
|
|
13102
13549
|
{
|
|
13103
13550
|
onClick: (e) => e.stopPropagation(),
|
|
13104
13551
|
sx: {
|
|
13105
13552
|
display: { xs: "none", sm: "flex" },
|
|
13106
13553
|
alignItems: "center",
|
|
13554
|
+
justifyContent: "flex-end",
|
|
13107
13555
|
flexShrink: 0,
|
|
13108
|
-
ml: 1
|
|
13556
|
+
ml: 1,
|
|
13557
|
+
width: 140,
|
|
13558
|
+
minHeight: 28
|
|
13109
13559
|
},
|
|
13110
|
-
children: /* @__PURE__ */ jsx24(
|
|
13560
|
+
children: tools.length > 0 ? /* @__PURE__ */ jsx24(
|
|
13111
13561
|
AvatarGroup2,
|
|
13112
13562
|
{
|
|
13113
13563
|
max: 5,
|
|
@@ -13156,6 +13606,17 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13156
13606
|
) }, t.name);
|
|
13157
13607
|
})
|
|
13158
13608
|
}
|
|
13609
|
+
) : /* @__PURE__ */ jsx24(
|
|
13610
|
+
Typography17,
|
|
13611
|
+
{
|
|
13612
|
+
sx: {
|
|
13613
|
+
fontSize: "0.7rem",
|
|
13614
|
+
color: "hsl(var(--muted-foreground))",
|
|
13615
|
+
opacity: 0.5,
|
|
13616
|
+
fontStyle: "italic"
|
|
13617
|
+
},
|
|
13618
|
+
children: "No apps"
|
|
13619
|
+
}
|
|
13159
13620
|
)
|
|
13160
13621
|
}
|
|
13161
13622
|
)
|
|
@@ -13499,7 +13960,7 @@ var AgentActivityList = ({
|
|
|
13499
13960
|
onChange: (e) => updateSearchQuery(e.target.value),
|
|
13500
13961
|
slotProps: {
|
|
13501
13962
|
input: {
|
|
13502
|
-
startAdornment: /* @__PURE__ */ jsx24(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx24(
|
|
13963
|
+
startAdornment: /* @__PURE__ */ jsx24(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx24(SearchIcon2, { size: 18, color: "hsl(var(--muted-foreground))" }) })
|
|
13503
13964
|
}
|
|
13504
13965
|
},
|
|
13505
13966
|
sx: {
|
|
@@ -14370,7 +14831,9 @@ export {
|
|
|
14370
14831
|
deleteDatastoreItem,
|
|
14371
14832
|
deleteDatastoreItems,
|
|
14372
14833
|
diagnoseOutputWarning,
|
|
14834
|
+
extractActionAppNames,
|
|
14373
14835
|
extractValidatedIngestionApps,
|
|
14836
|
+
extractWorkflowActionAppNames,
|
|
14374
14837
|
extractWorkflowAppNames,
|
|
14375
14838
|
fetchApps,
|
|
14376
14839
|
fetchAppsViaApiConfig,
|