@shuffleio/shuffle-mcps 0.0.31 → 0.0.33
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 +49 -31
- package/dist/index.d.ts +49 -31
- package/dist/index.js +1067 -232
- package/dist/index.mjs +1080 -238
- 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
|
}
|
|
@@ -1745,7 +1808,9 @@ import {
|
|
|
1745
1808
|
Pencil as EditIcon,
|
|
1746
1809
|
ChevronDown as ExpandMoreIcon,
|
|
1747
1810
|
Lock as LockIcon,
|
|
1748
|
-
BookOpen as MenuBookIcon
|
|
1811
|
+
BookOpen as MenuBookIcon,
|
|
1812
|
+
Eye as EyeIcon,
|
|
1813
|
+
EyeOff as EyeOffIcon
|
|
1749
1814
|
} from "lucide-react";
|
|
1750
1815
|
import {
|
|
1751
1816
|
Box as Box3,
|
|
@@ -1986,6 +2051,8 @@ var AppAuthCard = ({
|
|
|
1986
2051
|
hideDocsLink,
|
|
1987
2052
|
hideUrlFields,
|
|
1988
2053
|
borderless,
|
|
2054
|
+
compactAuthForm,
|
|
2055
|
+
extraFieldsSlot,
|
|
1989
2056
|
globalUrl,
|
|
1990
2057
|
userdata,
|
|
1991
2058
|
isLoaded,
|
|
@@ -2052,10 +2119,6 @@ var AppAuthCard = ({
|
|
|
2052
2119
|
if (!alreadyValid && newestId !== autoTestFiredRef.current) {
|
|
2053
2120
|
autoTestFiredRef.current = newestId;
|
|
2054
2121
|
setTimeout(() => {
|
|
2055
|
-
toast({
|
|
2056
|
-
title: "Auto-testing new authentication",
|
|
2057
|
-
description: `Verifying connection for ${app.name.replace(/_/g, " ")}...`
|
|
2058
|
-
});
|
|
2059
2122
|
setTestingAuthId(newestId);
|
|
2060
2123
|
onTestConnection(app.objectID, newestId);
|
|
2061
2124
|
}, 500);
|
|
@@ -2117,11 +2180,17 @@ var AppAuthCard = ({
|
|
|
2117
2180
|
executionId: authState.executionId,
|
|
2118
2181
|
errorCode: authState.errorCode
|
|
2119
2182
|
});
|
|
2183
|
+
if (autoTestFiredRef.current === testingAuthId) {
|
|
2184
|
+
setSelectedAuthId(ADD_NEW_AUTH);
|
|
2185
|
+
setUserHasSelected(true);
|
|
2186
|
+
setPendingFailedAuthId(testingAuthId);
|
|
2187
|
+
autoTestFiredRef.current = null;
|
|
2188
|
+
}
|
|
2120
2189
|
setTestingAuthId(null);
|
|
2121
2190
|
}
|
|
2122
2191
|
}, [authState.status, authState.errorMessage, authState.successMessage, authState.warningMessage, testingAuthId, apiAuthEntries, wasPreValidatedPerAuth]);
|
|
2123
2192
|
const isCredentialError = localTestMessages.errorCode === 401 || localTestMessages.errorCode === 403;
|
|
2124
|
-
const showAddNewForm = selectedAuthId === ADD_NEW_AUTH;
|
|
2193
|
+
const showAddNewForm = compactAuthForm ? true : selectedAuthId === ADD_NEW_AUTH;
|
|
2125
2194
|
const isConfigured = selectedAuth?.active === true;
|
|
2126
2195
|
const isTested = selectedAuth?.validation?.valid === true;
|
|
2127
2196
|
const getLastValidTimestamp = () => {
|
|
@@ -2143,6 +2212,8 @@ var AppAuthCard = ({
|
|
|
2143
2212
|
});
|
|
2144
2213
|
};
|
|
2145
2214
|
const [localCredentials, setLocalCredentials] = useState5(authState.credentials || {});
|
|
2215
|
+
const [revealedFields, setRevealedFields] = useState5({});
|
|
2216
|
+
const [pendingFailedAuthId, setPendingFailedAuthId] = useState5(null);
|
|
2146
2217
|
const [fieldErrors, setFieldErrors] = useState5({});
|
|
2147
2218
|
const [loading, setLoading] = useState5(false);
|
|
2148
2219
|
const [saving, setSaving] = useState5(false);
|
|
@@ -2218,7 +2289,8 @@ var AppAuthCard = ({
|
|
|
2218
2289
|
for (const [k, v] of Object.entries(incoming)) {
|
|
2219
2290
|
const lk = k.toLowerCase();
|
|
2220
2291
|
const isUrlish = lk.includes("url") || lk.includes("endpoint") || lk.includes("host");
|
|
2221
|
-
|
|
2292
|
+
const isModel = lk === "model";
|
|
2293
|
+
if ((isUrlish || isModel) && typeof v === "string" && v !== prev[k]) {
|
|
2222
2294
|
next[k] = v;
|
|
2223
2295
|
changed = true;
|
|
2224
2296
|
}
|
|
@@ -2414,7 +2486,7 @@ var AppAuthCard = ({
|
|
|
2414
2486
|
sx: {
|
|
2415
2487
|
"& .MuiOutlinedInput-root": {
|
|
2416
2488
|
backgroundColor: "hsl(var(--background))",
|
|
2417
|
-
borderRadius:
|
|
2489
|
+
borderRadius: 1,
|
|
2418
2490
|
"& fieldset": { borderColor: "hsl(var(--border))" },
|
|
2419
2491
|
"&:hover fieldset": { borderColor: "hsl(var(--border) / 0.8)" },
|
|
2420
2492
|
"&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
|
|
@@ -2437,7 +2509,7 @@ var AppAuthCard = ({
|
|
|
2437
2509
|
sx: {
|
|
2438
2510
|
"& .MuiOutlinedInput-root": {
|
|
2439
2511
|
backgroundColor: "hsl(var(--background))",
|
|
2440
|
-
borderRadius:
|
|
2512
|
+
borderRadius: 1,
|
|
2441
2513
|
"& fieldset": { borderColor: "hsl(var(--border))" },
|
|
2442
2514
|
"&:hover fieldset": { borderColor: "hsl(var(--border) / 0.8)" },
|
|
2443
2515
|
"&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
|
|
@@ -2462,7 +2534,7 @@ var AppAuthCard = ({
|
|
|
2462
2534
|
displayEmpty: true,
|
|
2463
2535
|
sx: {
|
|
2464
2536
|
backgroundColor: "action.hover",
|
|
2465
|
-
borderRadius:
|
|
2537
|
+
borderRadius: 1,
|
|
2466
2538
|
color: "text.primary",
|
|
2467
2539
|
"& .MuiOutlinedInput-notchedOutline": { borderColor: "divider" },
|
|
2468
2540
|
"&:hover .MuiOutlinedInput-notchedOutline": { borderColor: "text.disabled" },
|
|
@@ -2507,6 +2579,7 @@ var AppAuthCard = ({
|
|
|
2507
2579
|
const fieldKey = param.id || param.name || `param_${index}`;
|
|
2508
2580
|
const lowerName = (param.name || "").toLowerCase();
|
|
2509
2581
|
const isSecretField = lowerName.includes("password") || lowerName.includes("secret") || lowerName.includes("key") || lowerName.includes("token");
|
|
2582
|
+
const isRevealed = !!revealedFields[fieldKey];
|
|
2510
2583
|
return /* @__PURE__ */ jsx6(
|
|
2511
2584
|
TextField,
|
|
2512
2585
|
{
|
|
@@ -2537,13 +2610,25 @@ var AppAuthCard = ({
|
|
|
2537
2610
|
onFocus: (e) => {
|
|
2538
2611
|
e.target.removeAttribute("readonly");
|
|
2539
2612
|
}
|
|
2540
|
-
}
|
|
2613
|
+
},
|
|
2614
|
+
input: isSecretField ? {
|
|
2615
|
+
endAdornment: /* @__PURE__ */ jsx6(
|
|
2616
|
+
IconButton2,
|
|
2617
|
+
{
|
|
2618
|
+
size: "small",
|
|
2619
|
+
onClick: () => setRevealedFields((prev) => ({ ...prev, [fieldKey]: !prev[fieldKey] })),
|
|
2620
|
+
"aria-label": isRevealed ? `Hide ${param.name}` : `Show ${param.name}`,
|
|
2621
|
+
sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--foreground))" } },
|
|
2622
|
+
children: isRevealed ? /* @__PURE__ */ jsx6(EyeOffIcon, { size: 16 }) : /* @__PURE__ */ jsx6(EyeIcon, { size: 16 })
|
|
2623
|
+
}
|
|
2624
|
+
)
|
|
2625
|
+
} : void 0
|
|
2541
2626
|
},
|
|
2542
2627
|
name: `auth-${fieldKey}-${app.objectID}-${Math.random().toString(36).slice(2, 8)}`,
|
|
2543
2628
|
sx: {
|
|
2544
2629
|
"& .MuiOutlinedInput-root": {
|
|
2545
2630
|
backgroundColor: isSecretField ? "hsl(var(--primary) / 0.06)" : "hsl(var(--muted))",
|
|
2546
|
-
borderRadius:
|
|
2631
|
+
borderRadius: 1,
|
|
2547
2632
|
"& fieldset": {
|
|
2548
2633
|
borderColor: fieldErrors[fieldKey] ? "hsl(var(--destructive))" : isSecretField ? "hsl(var(--primary) / 0.5)" : "hsl(var(--border))",
|
|
2549
2634
|
borderWidth: isSecretField ? 2 : 1
|
|
@@ -2555,7 +2640,7 @@ var AppAuthCard = ({
|
|
|
2555
2640
|
},
|
|
2556
2641
|
"& .MuiInputBase-input": {
|
|
2557
2642
|
color: "hsl(var(--foreground))",
|
|
2558
|
-
...isSecretField && {
|
|
2643
|
+
...isSecretField && !isRevealed && {
|
|
2559
2644
|
WebkitTextSecurity: "disc",
|
|
2560
2645
|
textSecurity: "disc",
|
|
2561
2646
|
fontFamily: "text-security-disc, monospace"
|
|
@@ -2606,7 +2691,6 @@ var AppAuthCard = ({
|
|
|
2606
2691
|
setSaveSuccess(success);
|
|
2607
2692
|
if (success) {
|
|
2608
2693
|
setUserHasSelected(false);
|
|
2609
|
-
setLocalCredentials({});
|
|
2610
2694
|
setFieldErrors({});
|
|
2611
2695
|
}
|
|
2612
2696
|
};
|
|
@@ -2814,7 +2898,7 @@ var AppAuthCard = ({
|
|
|
2814
2898
|
borderTop: borderless ? "none" : "1px solid hsl(var(--border))"
|
|
2815
2899
|
},
|
|
2816
2900
|
children: [
|
|
2817
|
-
apiAuthEntries.length > 0 && /* @__PURE__ */ jsxs4(Box3, { sx: { mb: 3 }, children: [
|
|
2901
|
+
!compactAuthForm && apiAuthEntries.length > 0 && /* @__PURE__ */ jsxs4(Box3, { sx: { mb: 3 }, children: [
|
|
2818
2902
|
/* @__PURE__ */ jsx6(Typography3, { variant: "body2", sx: { color: "hsl(var(--muted-foreground))", mb: 1 }, children: "Select authentication" }),
|
|
2819
2903
|
/* @__PURE__ */ jsx6(FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ jsxs4(
|
|
2820
2904
|
Select,
|
|
@@ -3353,7 +3437,7 @@ var AppAuthCard = ({
|
|
|
3353
3437
|
children: /* @__PURE__ */ jsx6(Typography3, { sx: { fontSize: "0.875rem" }, children: localTestMessages.errorCode === 401 ? "Previous credentials were invalid or expired. Please enter new credentials." : "Access was denied with the previous credentials. Please re-authenticate with valid permissions." })
|
|
3354
3438
|
}
|
|
3355
3439
|
),
|
|
3356
|
-
/* @__PURE__ */ jsx6(Typography3, { variant: "subtitle2", sx: { color: "hsl(var(--foreground))", fontWeight: 600, mb: 2 }, children: apiAuthEntries.length === 0 ?
|
|
3440
|
+
/* @__PURE__ */ jsx6(Typography3, { variant: "subtitle2", sx: { color: "hsl(var(--foreground))", fontWeight: 600, mb: 2 }, children: apiAuthEntries.length === 0 ? `Configure ${app.name.replace(/_/g, " ")}` : "Add New Authentication" }),
|
|
3357
3441
|
loading ? /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", alignItems: "center", justifyContent: "center", py: 4 }, children: [
|
|
3358
3442
|
/* @__PURE__ */ jsx6(CircularProgress2, { size: 32, sx: { color: "hsl(var(--primary))" } }),
|
|
3359
3443
|
/* @__PURE__ */ jsx6(Typography3, { sx: { ml: 2, color: "hsl(var(--muted-foreground))" }, children: "Loading configuration..." })
|
|
@@ -3389,6 +3473,7 @@ var AppAuthCard = ({
|
|
|
3389
3473
|
] })
|
|
3390
3474
|
}
|
|
3391
3475
|
) : /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", flexDirection: "column", gap: 3 }, children: [
|
|
3476
|
+
extraFieldsSlot?.({ credentials: localCredentials, setField: handleCredentialChange }),
|
|
3392
3477
|
renderOAuth2Fields(),
|
|
3393
3478
|
renderParameterFields(),
|
|
3394
3479
|
authState.status === "error" && authState.errorMessage && /* @__PURE__ */ jsx6(
|
|
@@ -3443,38 +3528,97 @@ var AppAuthCard = ({
|
|
|
3443
3528
|
children: "Failed to save authentication. Please try again."
|
|
3444
3529
|
}
|
|
3445
3530
|
),
|
|
3446
|
-
!isOAuth2 && /* @__PURE__ */
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
e
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3531
|
+
!isOAuth2 && /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", justifyContent: "flex-end", pt: 1.5, gap: 1, flexWrap: "wrap" }, children: [
|
|
3532
|
+
pendingFailedAuthId && /* @__PURE__ */ jsx6(
|
|
3533
|
+
Button2,
|
|
3534
|
+
{
|
|
3535
|
+
variant: "text",
|
|
3536
|
+
size: "medium",
|
|
3537
|
+
onClick: async (e) => {
|
|
3538
|
+
e.stopPropagation();
|
|
3539
|
+
const previousFailedId = pendingFailedAuthId;
|
|
3540
|
+
setPendingFailedAuthId(null);
|
|
3541
|
+
setUserHasSelected(true);
|
|
3542
|
+
setFieldErrors({});
|
|
3543
|
+
await onSaveAuth(app.objectID, localCredentials);
|
|
3544
|
+
let entries = apiAuthEntries;
|
|
3545
|
+
if (onRefreshAuth) {
|
|
3546
|
+
await onRefreshAuth();
|
|
3547
|
+
}
|
|
3548
|
+
entries = apiAuthEntries || [];
|
|
3549
|
+
const sorted = [...entries].sort((a, b) => (b.created || 0) - (a.created || 0));
|
|
3550
|
+
const acceptId = sorted[0]?.id || previousFailedId;
|
|
3551
|
+
setSelectedAuthId(acceptId);
|
|
3552
|
+
const stale = entries.filter((e2) => e2.id && e2.id !== acceptId);
|
|
3553
|
+
await Promise.all(stale.map(async (entry) => {
|
|
3554
|
+
try {
|
|
3555
|
+
await fetch(getApiUrl(`/api/v1/apps/authentication/${entry.id}`), {
|
|
3556
|
+
method: "DELETE",
|
|
3557
|
+
credentials: "include",
|
|
3558
|
+
headers: { ...getAuthHeader() }
|
|
3559
|
+
});
|
|
3560
|
+
} catch (err) {
|
|
3561
|
+
console.error("[AppAuthCard] Failed to delete stale auth on Save anyway:", err);
|
|
3562
|
+
}
|
|
3563
|
+
}));
|
|
3564
|
+
if (onRefreshAuth) await onRefreshAuth();
|
|
3565
|
+
if (onSelectAuth) onSelectAuth(app.objectID, acceptId);
|
|
3566
|
+
if (typeof window !== "undefined") {
|
|
3567
|
+
window.dispatchEvent(new CustomEvent("integrations-changed"));
|
|
3568
|
+
window.dispatchEvent(new CustomEvent("agent-drawer-close"));
|
|
3569
|
+
}
|
|
3469
3570
|
},
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3571
|
+
sx: {
|
|
3572
|
+
color: "hsl(var(--muted-foreground))",
|
|
3573
|
+
fontWeight: 600,
|
|
3574
|
+
textTransform: "none",
|
|
3575
|
+
fontSize: "0.85rem",
|
|
3576
|
+
px: 2,
|
|
3577
|
+
py: 1,
|
|
3578
|
+
borderRadius: 2,
|
|
3579
|
+
"&:hover": {
|
|
3580
|
+
color: "hsl(var(--foreground))",
|
|
3581
|
+
backgroundColor: "hsl(var(--muted) / 0.5)"
|
|
3582
|
+
}
|
|
3583
|
+
},
|
|
3584
|
+
title: "Our test isn't always authoritative \u2014 keep the credentials you saved and dismiss the failure.",
|
|
3585
|
+
children: "Save anyway"
|
|
3586
|
+
}
|
|
3587
|
+
),
|
|
3588
|
+
/* @__PURE__ */ jsx6(
|
|
3589
|
+
Button2,
|
|
3590
|
+
{
|
|
3591
|
+
variant: "outlined",
|
|
3592
|
+
size: "medium",
|
|
3593
|
+
onClick: (e) => {
|
|
3594
|
+
e.stopPropagation();
|
|
3595
|
+
setPendingFailedAuthId(null);
|
|
3596
|
+
handleSave();
|
|
3597
|
+
},
|
|
3598
|
+
disabled: saving || !isFormValid(),
|
|
3599
|
+
sx: {
|
|
3600
|
+
borderColor: isFormValid() ? "hsl(var(--primary) / 0.5)" : "hsl(var(--border))",
|
|
3601
|
+
color: isFormValid() ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))",
|
|
3602
|
+
fontWeight: 600,
|
|
3603
|
+
textTransform: "none",
|
|
3604
|
+
fontSize: "0.9rem",
|
|
3605
|
+
px: 3,
|
|
3606
|
+
py: 1,
|
|
3607
|
+
borderRadius: 2,
|
|
3608
|
+
transition: "all 0.2s ease",
|
|
3609
|
+
"&:hover": {
|
|
3610
|
+
borderColor: "hsl(var(--primary))",
|
|
3611
|
+
backgroundColor: "hsl(var(--primary) / 0.08)"
|
|
3612
|
+
},
|
|
3613
|
+
"&.Mui-disabled": {
|
|
3614
|
+
borderColor: "hsl(var(--border))",
|
|
3615
|
+
color: "hsl(var(--muted-foreground))"
|
|
3616
|
+
}
|
|
3617
|
+
},
|
|
3618
|
+
children: saving ? "Testing..." : pendingFailedAuthId ? "Retry Test" : "Test Authentication"
|
|
3619
|
+
}
|
|
3620
|
+
)
|
|
3621
|
+
] }),
|
|
3478
3622
|
isOAuth2 && (() => {
|
|
3479
3623
|
const hasClientId = !!localCredentials["client_id"]?.trim();
|
|
3480
3624
|
const hasClientSecret = !!localCredentials["client_secret"]?.trim();
|
|
@@ -5320,6 +5464,7 @@ function AppDetailDrawer({
|
|
|
5320
5464
|
onAddToCanvas,
|
|
5321
5465
|
isAuthenticated = true,
|
|
5322
5466
|
activeOrgId,
|
|
5467
|
+
autoActivate = false,
|
|
5323
5468
|
globalUrl,
|
|
5324
5469
|
userdata,
|
|
5325
5470
|
isLoaded,
|
|
@@ -5517,8 +5662,9 @@ function AppDetailDrawer({
|
|
|
5517
5662
|
useEffect7(() => {
|
|
5518
5663
|
lastValidAuthRef.current = null;
|
|
5519
5664
|
}, [appName]);
|
|
5520
|
-
const handleActivateToggle = async () => {
|
|
5665
|
+
const handleActivateToggle = async (opts) => {
|
|
5521
5666
|
if (!appName || activateLoading) return;
|
|
5667
|
+
const silent = !!opts?.silent;
|
|
5522
5668
|
const wasActivated = isActivated;
|
|
5523
5669
|
const prevAppId = activatedAppId;
|
|
5524
5670
|
setIsActivated(!wasActivated);
|
|
@@ -5532,7 +5678,7 @@ function AppDetailDrawer({
|
|
|
5532
5678
|
});
|
|
5533
5679
|
if (!res.ok) throw new Error("Deactivate failed");
|
|
5534
5680
|
setActivatedAppId(null);
|
|
5535
|
-
toast.success(`${displayName} deactivated`);
|
|
5681
|
+
if (!silent) toast.success(`${displayName} deactivated`);
|
|
5536
5682
|
} else {
|
|
5537
5683
|
const appId2 = resolvedAlgoliaId;
|
|
5538
5684
|
if (!appId2) throw new Error("App ID not resolved yet");
|
|
@@ -5543,40 +5689,71 @@ function AppDetailDrawer({
|
|
|
5543
5689
|
});
|
|
5544
5690
|
if (!activateRes.ok) throw new Error(`Activate failed (${activateRes.status})`);
|
|
5545
5691
|
setActivatedAppId(appId2);
|
|
5546
|
-
toast.success(`${displayName} activated`);
|
|
5692
|
+
if (!silent) toast.success(`${displayName} activated`);
|
|
5547
5693
|
}
|
|
5548
5694
|
} catch (err) {
|
|
5549
5695
|
console.error("[Activate] Error:", err);
|
|
5550
|
-
toast.error(err?.message || "Activation failed");
|
|
5696
|
+
if (!silent) toast.error(err?.message || "Activation failed");
|
|
5551
5697
|
setIsActivated(wasActivated);
|
|
5552
5698
|
setActivatedAppId(prevAppId);
|
|
5553
5699
|
} finally {
|
|
5554
5700
|
setActivateLoading(false);
|
|
5555
5701
|
}
|
|
5556
5702
|
};
|
|
5703
|
+
const autoActivateFiredRef = useRef5(null);
|
|
5704
|
+
const [autoActivatePulse, setAutoActivatePulse] = useState8(false);
|
|
5705
|
+
useEffect7(() => {
|
|
5706
|
+
if (!open || !autoActivate || !appName) return;
|
|
5707
|
+
const key = `${appName}`;
|
|
5708
|
+
if (autoActivateFiredRef.current === key) return;
|
|
5709
|
+
if (isActivated !== false) return;
|
|
5710
|
+
if (!resolvedAlgoliaId) return;
|
|
5711
|
+
if (activateLoading) return;
|
|
5712
|
+
autoActivateFiredRef.current = key;
|
|
5713
|
+
setAutoActivatePulse(true);
|
|
5714
|
+
handleActivateToggle({ silent: true }).finally(() => {
|
|
5715
|
+
setTimeout(() => setAutoActivatePulse(false), 1200);
|
|
5716
|
+
});
|
|
5717
|
+
}, [open, autoActivate, appName, isActivated, resolvedAlgoliaId, activateLoading]);
|
|
5718
|
+
useEffect7(() => {
|
|
5719
|
+
if (!open) {
|
|
5720
|
+
autoActivateFiredRef.current = null;
|
|
5721
|
+
setAutoActivatePulse(false);
|
|
5722
|
+
}
|
|
5723
|
+
}, [open, appName]);
|
|
5557
5724
|
const isLoadingAll = appLoading || isAuthenticated && appAuthLoading;
|
|
5725
|
+
const drawerWidth = `min(${width}px, 100vw)`;
|
|
5558
5726
|
return /* @__PURE__ */ jsxs9(
|
|
5559
5727
|
Drawer,
|
|
5560
5728
|
{
|
|
5561
5729
|
anchor,
|
|
5562
5730
|
open,
|
|
5563
5731
|
onClose: handleClose,
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5732
|
+
PaperProps: {
|
|
5733
|
+
className: scopeClassName,
|
|
5734
|
+
sx: {
|
|
5735
|
+
width: drawerWidth,
|
|
5736
|
+
minWidth: drawerWidth,
|
|
5737
|
+
maxWidth: drawerWidth,
|
|
5738
|
+
flex: `0 0 ${drawerWidth}`,
|
|
5739
|
+
height: "100vh",
|
|
5740
|
+
display: "flex",
|
|
5741
|
+
flexDirection: "column",
|
|
5742
|
+
overflow: "hidden",
|
|
5743
|
+
background: "linear-gradient(180deg, hsl(var(--card)) 0%, hsl(var(--background)) 100%)",
|
|
5744
|
+
borderLeft: anchor === "right" ? "1px solid hsl(var(--border))" : "none",
|
|
5745
|
+
borderRight: anchor === "left" ? "1px solid hsl(var(--border))" : "none"
|
|
5576
5746
|
}
|
|
5577
5747
|
},
|
|
5578
5748
|
sx: {
|
|
5579
|
-
|
|
5749
|
+
zIndex: 9999,
|
|
5750
|
+
"& .MuiDrawer-paper": {
|
|
5751
|
+
boxSizing: "border-box",
|
|
5752
|
+
width: `${drawerWidth} !important`,
|
|
5753
|
+
minWidth: `${drawerWidth} !important`,
|
|
5754
|
+
maxWidth: `${drawerWidth} !important`,
|
|
5755
|
+
flex: `0 0 ${drawerWidth} !important`
|
|
5756
|
+
}
|
|
5580
5757
|
},
|
|
5581
5758
|
children: [
|
|
5582
5759
|
/* @__PURE__ */ jsxs9(
|
|
@@ -5629,7 +5806,8 @@ function AppDetailDrawer({
|
|
|
5629
5806
|
categories: appInfo?.categories,
|
|
5630
5807
|
isActivated: onAddToCanvas ? null : effectiveActivated,
|
|
5631
5808
|
activateLoading,
|
|
5632
|
-
onActivateToggle: handleActivateToggle,
|
|
5809
|
+
onActivateToggle: () => handleActivateToggle(),
|
|
5810
|
+
highlightActivate: autoActivatePulse,
|
|
5633
5811
|
onAdd: onAddToCanvas && appName ? () => {
|
|
5634
5812
|
onAddToCanvas({ name: appName, icon: resolvedImage || "", algoliaId: resolvedAlgoliaId });
|
|
5635
5813
|
onClose();
|
|
@@ -5733,7 +5911,7 @@ function AppDetailDrawer({
|
|
|
5733
5911
|
}
|
|
5734
5912
|
|
|
5735
5913
|
// views/ShuffleMCP.tsx
|
|
5736
|
-
import "./shuffle-mcp-
|
|
5914
|
+
import "./shuffle-mcp-TWJGPBOQ.css";
|
|
5737
5915
|
|
|
5738
5916
|
// components/SegmentedControl.tsx
|
|
5739
5917
|
import * as React2 from "react";
|
|
@@ -5900,7 +6078,7 @@ function SegmentedControl({
|
|
|
5900
6078
|
children: opt.label
|
|
5901
6079
|
}
|
|
5902
6080
|
),
|
|
5903
|
-
!isAction && typeof opt.count === "number" && /* @__PURE__ */ jsx13(
|
|
6081
|
+
!isAction && (typeof opt.count === "number" || typeof opt.count === "string") && /* @__PURE__ */ jsx13(
|
|
5904
6082
|
"span",
|
|
5905
6083
|
{
|
|
5906
6084
|
style: {
|
|
@@ -6399,8 +6577,8 @@ var ShuffleMCP = React3.forwardRef(({
|
|
|
6399
6577
|
value: sourceFilter,
|
|
6400
6578
|
onChange: (v) => setSourceFilter(v),
|
|
6401
6579
|
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)." },
|
|
6580
|
+
{ 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." },
|
|
6581
|
+
{ value: "public", label: "Public", count: results.length >= hitsPerPage ? `${results.length}+` : results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6404
6582
|
{ 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
6583
|
{ 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
6584
|
]
|
|
@@ -6577,9 +6755,11 @@ function AppSearchDrawer({
|
|
|
6577
6755
|
pinnedApps,
|
|
6578
6756
|
highlightAppName,
|
|
6579
6757
|
highlightDelayMs = 5e3,
|
|
6758
|
+
realtimeHighlightAppNames,
|
|
6580
6759
|
multiSelect = false,
|
|
6581
6760
|
selectedApps,
|
|
6582
6761
|
onSelectionChange,
|
|
6762
|
+
autoActivate = false,
|
|
6583
6763
|
globalUrl,
|
|
6584
6764
|
theme,
|
|
6585
6765
|
colorMode
|
|
@@ -6606,6 +6786,7 @@ function AppSearchDrawer({
|
|
|
6606
6786
|
const t = setTimeout(() => setHighlightActive(true), highlightDelayMs);
|
|
6607
6787
|
return () => clearTimeout(t);
|
|
6608
6788
|
}, [open, highlightAppName, highlightDelayMs]);
|
|
6789
|
+
const drawerWidth = `min(${width}px, 100vw)`;
|
|
6609
6790
|
const handleClose = () => {
|
|
6610
6791
|
setDetailAppName(null);
|
|
6611
6792
|
setDetailAppId(null);
|
|
@@ -6682,29 +6863,38 @@ function AppSearchDrawer({
|
|
|
6682
6863
|
anchor,
|
|
6683
6864
|
open: open && detailAppName === null,
|
|
6684
6865
|
onClose: handleClose,
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6866
|
+
PaperProps: {
|
|
6867
|
+
className: scopeClassName,
|
|
6868
|
+
sx: {
|
|
6869
|
+
// Strict, environment-independent sizing so the drawer
|
|
6870
|
+
// looks identical on every host (Shuffle Security, /agents,
|
|
6871
|
+
// test page, embedded library, etc.). No breakpoint variance.
|
|
6872
|
+
// NOTE: use PaperProps (not slotProps.paper) — slotProps.paper
|
|
6873
|
+
// was added in MUI v6 and is silently ignored on MUI v5 hosts,
|
|
6874
|
+
// which made the drawer collapse to content width when
|
|
6875
|
+
// consumed from the published library.
|
|
6876
|
+
width: drawerWidth,
|
|
6877
|
+
minWidth: drawerWidth,
|
|
6878
|
+
maxWidth: drawerWidth,
|
|
6879
|
+
flex: `0 0 ${drawerWidth}`,
|
|
6880
|
+
height: "100vh",
|
|
6881
|
+
display: "flex",
|
|
6882
|
+
flexDirection: "column",
|
|
6883
|
+
overflow: "hidden",
|
|
6884
|
+
background: "linear-gradient(180deg, hsl(var(--card)) 0%, hsl(var(--background)) 100%)",
|
|
6885
|
+
borderLeft: anchor === "right" ? "1px solid hsl(var(--border))" : "none",
|
|
6886
|
+
borderRight: anchor === "left" ? "1px solid hsl(var(--border))" : "none"
|
|
6703
6887
|
}
|
|
6704
6888
|
},
|
|
6705
6889
|
sx: {
|
|
6706
6890
|
zIndex: 9999,
|
|
6707
|
-
"& .MuiDrawer-paper": {
|
|
6891
|
+
"& .MuiDrawer-paper": {
|
|
6892
|
+
boxSizing: "border-box",
|
|
6893
|
+
width: `${drawerWidth} !important`,
|
|
6894
|
+
minWidth: `${drawerWidth} !important`,
|
|
6895
|
+
maxWidth: `${drawerWidth} !important`,
|
|
6896
|
+
flex: `0 0 ${drawerWidth} !important`
|
|
6897
|
+
}
|
|
6708
6898
|
},
|
|
6709
6899
|
children: [
|
|
6710
6900
|
/* @__PURE__ */ jsxs12(
|
|
@@ -6736,7 +6926,7 @@ function AppSearchDrawer({
|
|
|
6736
6926
|
]
|
|
6737
6927
|
}
|
|
6738
6928
|
),
|
|
6739
|
-
/* @__PURE__ */ jsxs12(Box9, { sx: { flex: 1, boxSizing: "border-box", overflow: "hidden", p: 3, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
6929
|
+
/* @__PURE__ */ jsxs12(Box9, { sx: { flex: 1, width: "100%", minWidth: 0, boxSizing: "border-box", overflow: "hidden", p: 3, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
6740
6930
|
connectionPathApps && connectionPathApps.length > 0 && /* @__PURE__ */ jsxs12(Box9, { sx: { mb: 2.5 }, children: [
|
|
6741
6931
|
/* @__PURE__ */ jsx15(Typography9, { sx: { color: "hsl(var(--muted-foreground))", fontSize: "0.7rem", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.05em", mb: 1 }, children: "In this usecase" }),
|
|
6742
6932
|
/* @__PURE__ */ jsx15(Box9, { sx: { display: "flex", gap: 1.5, flexWrap: "wrap" }, children: connectionPathApps.map((app) => /* @__PURE__ */ jsx15(Tooltip5, { title: app.name.replace(/_/g, " "), arrow: true, placement: "bottom", children: /* @__PURE__ */ jsxs12(
|
|
@@ -6783,6 +6973,8 @@ function AppSearchDrawer({
|
|
|
6783
6973
|
{
|
|
6784
6974
|
sx: {
|
|
6785
6975
|
flex: 1,
|
|
6976
|
+
width: "100%",
|
|
6977
|
+
minWidth: 0,
|
|
6786
6978
|
minHeight: 0,
|
|
6787
6979
|
overflow: "hidden",
|
|
6788
6980
|
"& .singul-container, & .singul-search-bar-container": {
|
|
@@ -6795,16 +6987,22 @@ function AppSearchDrawer({
|
|
|
6795
6987
|
},
|
|
6796
6988
|
"& .singul-results-container": {
|
|
6797
6989
|
flex: 1,
|
|
6990
|
+
width: "100%",
|
|
6991
|
+
minWidth: 0,
|
|
6798
6992
|
minHeight: 0,
|
|
6799
6993
|
maxHeight: "none",
|
|
6800
6994
|
overflowY: "auto"
|
|
6801
6995
|
},
|
|
6802
6996
|
"& .singul-results-grid": {
|
|
6997
|
+
width: "100% !important",
|
|
6998
|
+
minWidth: "0 !important",
|
|
6803
6999
|
gridTemplateColumns: "repeat(2, minmax(0, 1fr)) !important",
|
|
6804
7000
|
gridAutoRows: "78px !important",
|
|
6805
7001
|
gap: "12px !important"
|
|
6806
7002
|
},
|
|
6807
7003
|
"& .singul-results-grid .singul-dropdown-item": {
|
|
7004
|
+
width: "100%",
|
|
7005
|
+
maxWidth: "100%",
|
|
6808
7006
|
minWidth: 0,
|
|
6809
7007
|
minHeight: "78px !important",
|
|
6810
7008
|
maxHeight: "78px !important",
|
|
@@ -6838,6 +7036,41 @@ function AppSearchDrawer({
|
|
|
6838
7036
|
"0%, 100%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 12px 1px hsl(var(--primary) / 0.4)" },
|
|
6839
7037
|
"50%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 24px 4px hsl(var(--primary) / 0.75)" }
|
|
6840
7038
|
}
|
|
7039
|
+
} : {},
|
|
7040
|
+
...realtimeHighlightAppNames && realtimeHighlightAppNames.length > 0 ? {
|
|
7041
|
+
[realtimeHighlightAppNames.map((n) => `& .singul-dropdown-item[data-app-name="${n}"]`).join(", ")]: {
|
|
7042
|
+
position: "relative",
|
|
7043
|
+
zIndex: 2,
|
|
7044
|
+
borderColor: "hsl(var(--primary) / 0.78) !important",
|
|
7045
|
+
backgroundColor: "hsl(var(--primary) / 0.08) !important",
|
|
7046
|
+
outline: "none !important",
|
|
7047
|
+
boxShadow: "none !important",
|
|
7048
|
+
animation: "shuffleHighlightPulseStrong 1.5s ease-in-out infinite",
|
|
7049
|
+
transition: "border-color 120ms ease, background-color 120ms ease",
|
|
7050
|
+
"&::before": {
|
|
7051
|
+
content: '""',
|
|
7052
|
+
position: "absolute",
|
|
7053
|
+
left: "10px",
|
|
7054
|
+
top: "14px",
|
|
7055
|
+
bottom: "14px",
|
|
7056
|
+
width: "3px",
|
|
7057
|
+
borderRadius: "999px",
|
|
7058
|
+
backgroundColor: "hsl(var(--primary))"
|
|
7059
|
+
},
|
|
7060
|
+
"& .singul-app-info": {
|
|
7061
|
+
paddingLeft: "8px"
|
|
7062
|
+
}
|
|
7063
|
+
},
|
|
7064
|
+
"@keyframes shuffleHighlightPulseStrong": {
|
|
7065
|
+
"0%, 100%": {
|
|
7066
|
+
borderColor: "hsl(var(--primary) / 0.62)",
|
|
7067
|
+
backgroundColor: "hsl(var(--primary) / 0.06)"
|
|
7068
|
+
},
|
|
7069
|
+
"50%": {
|
|
7070
|
+
borderColor: "hsl(var(--primary) / 0.92)",
|
|
7071
|
+
backgroundColor: "hsl(var(--primary) / 0.12)"
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
6841
7074
|
} : {}
|
|
6842
7075
|
},
|
|
6843
7076
|
children: /* @__PURE__ */ jsx15(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsx15(
|
|
@@ -6860,8 +7093,9 @@ function AppSearchDrawer({
|
|
|
6860
7093
|
layout: "grid",
|
|
6861
7094
|
gridColumns: 2,
|
|
6862
7095
|
inline: true,
|
|
7096
|
+
initialQuery,
|
|
6863
7097
|
initialFilterQuery: initialQuery,
|
|
6864
|
-
hitsPerPage:
|
|
7098
|
+
hitsPerPage: 20,
|
|
6865
7099
|
showDescription: false,
|
|
6866
7100
|
showCategories: true,
|
|
6867
7101
|
showCheckbox: multiSelect,
|
|
@@ -6952,7 +7186,8 @@ function AppSearchDrawer({
|
|
|
6952
7186
|
theme,
|
|
6953
7187
|
colorMode,
|
|
6954
7188
|
onRefresh: onClose,
|
|
6955
|
-
onAddToCanvas
|
|
7189
|
+
onAddToCanvas,
|
|
7190
|
+
autoActivate
|
|
6956
7191
|
}
|
|
6957
7192
|
)
|
|
6958
7193
|
] });
|
|
@@ -7219,7 +7454,7 @@ function ShufflePipelinesBanner() {
|
|
|
7219
7454
|
var ShufflePipelinesBanner_default = ShufflePipelinesBanner;
|
|
7220
7455
|
|
|
7221
7456
|
// components/AgentUI.tsx
|
|
7222
|
-
import { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef8, useState as useState12 } from "react";
|
|
7457
|
+
import React4, { useCallback as useCallback8, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef8, useState as useState12 } from "react";
|
|
7223
7458
|
import {
|
|
7224
7459
|
Plus as AddIcon3,
|
|
7225
7460
|
Paperclip as AttachFileIcon,
|
|
@@ -7240,7 +7475,8 @@ import {
|
|
|
7240
7475
|
CircleStop as StopCircleIcon,
|
|
7241
7476
|
ThumbsDown as ThumbDownIcon,
|
|
7242
7477
|
ThumbsUp as ThumbUpIcon,
|
|
7243
|
-
AlertTriangle as WarningIcon
|
|
7478
|
+
AlertTriangle as WarningIcon,
|
|
7479
|
+
Search as SearchIcon
|
|
7244
7480
|
} from "lucide-react";
|
|
7245
7481
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
|
7246
7482
|
import {
|
|
@@ -7250,16 +7486,182 @@ import {
|
|
|
7250
7486
|
Button as Button8,
|
|
7251
7487
|
Chip as Chip7,
|
|
7252
7488
|
CircularProgress as CircularProgress4,
|
|
7489
|
+
ClickAwayListener,
|
|
7253
7490
|
IconButton as IconButton8,
|
|
7254
7491
|
InputBase as InputBase2,
|
|
7255
7492
|
MenuItem as MenuItem2,
|
|
7493
|
+
MenuList,
|
|
7494
|
+
Paper,
|
|
7256
7495
|
Popover,
|
|
7496
|
+
Popper,
|
|
7257
7497
|
Select as Select2,
|
|
7258
7498
|
TextField as TextField5,
|
|
7259
7499
|
Tooltip as Tooltip9,
|
|
7260
7500
|
Typography as Typography13
|
|
7261
7501
|
} from "@mui/material";
|
|
7262
7502
|
import Markdown from "react-markdown";
|
|
7503
|
+
|
|
7504
|
+
// components/agentPromptSuggestions.ts
|
|
7505
|
+
var AGENT_PROMPT_SUGGESTIONS = [
|
|
7506
|
+
// — Email & comms ————————————————————————————————————————————————
|
|
7507
|
+
"Take care of my emails by pretending to be me and answering them",
|
|
7508
|
+
"Triage my inbox every hour and draft replies for anything urgent",
|
|
7509
|
+
"Summarise my unread emails from the last 24 hours and rank them by importance",
|
|
7510
|
+
"Forward any phishing-looking emails in my inbox to the security team and quarantine them",
|
|
7511
|
+
"Reply to scheduling requests in my inbox using my working hours and calendar availability",
|
|
7512
|
+
"Every morning, send me a digest of overnight emails grouped by sender and topic",
|
|
7513
|
+
"Auto-unsubscribe from marketing emails I have not opened in 60 days",
|
|
7514
|
+
"Snooze low-priority newsletters until Friday afternoon",
|
|
7515
|
+
"Flag and archive shipping notifications once the package is delivered",
|
|
7516
|
+
"Clean up my inbox by archiving anything older than 30 days that I have already read",
|
|
7517
|
+
// — Calendar & meetings ————————————————————————————————————————————
|
|
7518
|
+
"Block focus time on my calendar every weekday morning between 9 and 11",
|
|
7519
|
+
"Decline meetings that conflict with my focus blocks and propose alternatives",
|
|
7520
|
+
"Send me a daily agenda every weekday at 8am with prep notes per meeting",
|
|
7521
|
+
"Reschedule any meeting without an agenda 24 hours before it starts",
|
|
7522
|
+
"Send meeting notes and action items to all attendees after every call",
|
|
7523
|
+
"Find a 30-minute slot this week that works for me and the people I mention",
|
|
7524
|
+
"Cancel recurring meetings that I have skipped 3 times in a row",
|
|
7525
|
+
"Remind me 15 minutes before any meeting that I have not prepared for",
|
|
7526
|
+
// — Incidents & SOC operations ———————————————————————————————————
|
|
7527
|
+
"Triage new incidents every 15 minutes and assign severity, owner, and next steps",
|
|
7528
|
+
"Watch for new critical incidents and page the on-call engineer immediately",
|
|
7529
|
+
"Close incidents older than 30 days that have had no activity and no observables",
|
|
7530
|
+
"Merge duplicate incidents that share the same observable or hostname",
|
|
7531
|
+
"Enrich every new incident with threat intel and asset context within 2 minutes",
|
|
7532
|
+
"Auto-acknowledge incidents from known maintenance windows and link them to the change ticket",
|
|
7533
|
+
"Summarise yesterday's incidents into a daily standup brief for the SOC team",
|
|
7534
|
+
"Escalate any incident that breaches its SLA to the team lead",
|
|
7535
|
+
"Tag every incident with the MITRE ATT&CK technique that best matches its observables",
|
|
7536
|
+
"Watch the alert queue and group related alerts into a single incident",
|
|
7537
|
+
"Auto-resolve incidents whose root cause matches a previously closed incident",
|
|
7538
|
+
"Reopen any closed incident if the same observable shows up again within 7 days",
|
|
7539
|
+
"Send a weekly incident trend report every Monday morning to the security leadership",
|
|
7540
|
+
// — Threat intel & IOCs —————————————————————————————————————————
|
|
7541
|
+
"Pull new IOCs from my threat feeds every hour and push them to the firewall blocklist",
|
|
7542
|
+
"Check every external IP in today's incidents against VirusTotal and AbuseIPDB",
|
|
7543
|
+
"Sweep the environment for any host that has connected to a known bad domain in the last 7 days",
|
|
7544
|
+
"Subscribe to new CISA advisories and turn them into detection rules where possible",
|
|
7545
|
+
"Cross-reference observed file hashes against MalwareBazaar daily",
|
|
7546
|
+
"Watch for newly registered domains that look like our brand and report them",
|
|
7547
|
+
"Alert me whenever a new CVE with a known exploit affects software in our inventory",
|
|
7548
|
+
"Refresh the IOC datastore every 6 hours and prune entries older than 30 days",
|
|
7549
|
+
// — Detection engineering ———————————————————————————————————————
|
|
7550
|
+
"Review noisy detection rules every week and propose tuning suggestions",
|
|
7551
|
+
"Convert the latest Sigma rules from the public repo into our SIEM's format and stage them for review",
|
|
7552
|
+
"Tell me which detection rules have not fired in the last 90 days so I can retire them",
|
|
7553
|
+
"Audit MITRE ATT&CK coverage every Monday and flag techniques with zero detections",
|
|
7554
|
+
"Backtest new detection rules against the last 30 days of logs before promoting them to production",
|
|
7555
|
+
// — SIEM operations ———————————————————————————————————————————
|
|
7556
|
+
"Triage new Splunk alerts every 10 minutes and assign severity, owner, and next steps",
|
|
7557
|
+
"Watch Microsoft Sentinel for high-severity incidents and page the on-call analyst immediately",
|
|
7558
|
+
"Suppress noisy SIEM alerts that fire more than 50 times per hour and open a tuning ticket",
|
|
7559
|
+
"Correlate failed login spikes in the SIEM with VPN logs and flag possible brute-force attempts",
|
|
7560
|
+
"Hunt the SIEM every morning for sign-ins from countries we do not operate in",
|
|
7561
|
+
"Forward critical SIEM detections straight to Case Management and skip the alert queue",
|
|
7562
|
+
"Run a weekly SIEM data-source health check and alert me on any log source silent for over 1 hour",
|
|
7563
|
+
"Enrich every SIEM alert with asset owner, criticality, and recent vulnerabilities before triage",
|
|
7564
|
+
"Search the SIEM for the latest IOCs from threat intel feeds every 30 minutes",
|
|
7565
|
+
"Summarise top 10 noisiest SIEM rules every Friday and propose tuning candidates",
|
|
7566
|
+
"Detect lateral movement patterns in SIEM auth logs and open an incident with the affected hosts",
|
|
7567
|
+
"Watch the SIEM for any disable or delete of audit logging and treat it as a critical incident",
|
|
7568
|
+
// — EDR operations ————————————————————————————————————————————
|
|
7569
|
+
"Isolate any endpoint that triggers a critical CrowdStrike alert and notify the user's manager",
|
|
7570
|
+
"Kill any process on a flagged host that matches a known malware family in EDR telemetry",
|
|
7571
|
+
"Watch SentinelOne for ransomware behavior detections and auto-contain the host within 60 seconds",
|
|
7572
|
+
"Pull the process tree from EDR for every malware detection and attach it to the incident",
|
|
7573
|
+
"Sweep all endpoints for a given hash or filename when a new IOC arrives and report matches",
|
|
7574
|
+
"Detect newly created local admin accounts on any endpoint and require approval before keeping them",
|
|
7575
|
+
"Alert when an EDR agent goes offline for more than 1 hour and open a ticket against the asset owner",
|
|
7576
|
+
"Quarantine any binary flagged as suspicious by EDR and email the user with next steps",
|
|
7577
|
+
"Hunt EDR telemetry every night for LOLBins executed from user-writable directories",
|
|
7578
|
+
"Correlate EDR alerts with SIEM auth events to detect credential theft followed by execution",
|
|
7579
|
+
"Run a weekly EDR coverage report and list endpoints without an active agent",
|
|
7580
|
+
"Auto-resolve EDR alerts that match a known-good signed binary on our allowlist",
|
|
7581
|
+
// — Vulnerability management ————————————————————————————————————
|
|
7582
|
+
"Scan our asset inventory daily and open tickets for any new critical or high vulnerability",
|
|
7583
|
+
"Remind asset owners every Friday about open vulnerabilities older than 14 days",
|
|
7584
|
+
"Re-scan hosts that recently patched a critical vulnerability and close the ticket if clean",
|
|
7585
|
+
"Send the patch compliance report every Monday morning to IT and security leadership",
|
|
7586
|
+
"Correlate vulnerabilities with active exploits in the wild and re-prioritise the queue",
|
|
7587
|
+
// — Endpoint & host monitoring ———————————————————————————————————
|
|
7588
|
+
"Watch my host monitors and alert me if any agent goes offline for more than 1 hour",
|
|
7589
|
+
"Isolate any endpoint that triggers a critical EDR alert and notify the user's manager",
|
|
7590
|
+
"Kill any process on a flagged host that matches a known malware family",
|
|
7591
|
+
"Run an inventory of installed software on every endpoint every Sunday",
|
|
7592
|
+
"Detect new local admin accounts created on any endpoint and require approval",
|
|
7593
|
+
"Make sure full-disk encryption is on for every laptop and report exceptions weekly",
|
|
7594
|
+
// — Identity & access —————————————————————————————————————————
|
|
7595
|
+
"Review user access every quarter and flag anyone with privileges they have not used in 90 days",
|
|
7596
|
+
"Disable accounts that have not logged in for 60 days and notify their manager",
|
|
7597
|
+
"Watch for impossible travel sign-ins and force a password reset plus MFA re-enrolment",
|
|
7598
|
+
"Alert me whenever someone is added to an admin group and require justification within 24 hours",
|
|
7599
|
+
"Audit MFA enrolment weekly and email any user without a second factor",
|
|
7600
|
+
"Rotate service account credentials every 90 days and update the vault",
|
|
7601
|
+
"Detect dormant API keys older than 180 days and revoke them after notice",
|
|
7602
|
+
"Make sure new joiners get baseline access provisioned within 1 hour of their start date",
|
|
7603
|
+
"Make sure leavers have all access revoked within 15 minutes of their termination event",
|
|
7604
|
+
// — Cloud, infra & posture ————————————————————————————————————
|
|
7605
|
+
"Check our cloud accounts every hour for public S3 buckets and lock them down",
|
|
7606
|
+
"Detect new IAM roles with wildcard permissions and require review before they go live",
|
|
7607
|
+
"Watch for unencrypted databases in production and open a ticket against the owner",
|
|
7608
|
+
"Run a CIS benchmark scan against all production cloud accounts every Sunday",
|
|
7609
|
+
"Alert on any new security group that opens ports to 0.0.0.0/0",
|
|
7610
|
+
"Monitor cloud spend daily and warn me if any service's cost jumps more than 50% week-over-week",
|
|
7611
|
+
"Check certificate expiry across our domains weekly and renew anything within 30 days",
|
|
7612
|
+
"Watch our DNS records for unauthorised changes and revert them",
|
|
7613
|
+
// — Phishing & user reports ———————————————————————————————————
|
|
7614
|
+
"Investigate phishing reports from the abuse mailbox and respond to the reporter within 1 hour",
|
|
7615
|
+
"Detonate suspicious attachments in a sandbox and attach the verdict to the incident",
|
|
7616
|
+
"Pull URLs from reported phishing emails and submit them to URLhaus and PhishTank",
|
|
7617
|
+
"Send a phishing simulation to a sample of users every month and report results",
|
|
7618
|
+
// — Compliance, audit & reporting —————————————————————————————
|
|
7619
|
+
"Generate the SOC2 evidence pack at the start of every month",
|
|
7620
|
+
"Track changes to security policies and alert the GRC team when one is edited",
|
|
7621
|
+
"Send a weekly KPI report covering MTTD, MTTR, and open incident backlog",
|
|
7622
|
+
"Audit log retention every Sunday and confirm we still meet the 1-year requirement",
|
|
7623
|
+
"Generate a monthly executive summary of incidents, vulnerabilities, and detection coverage",
|
|
7624
|
+
// — Backups, DR & uptime ————————————————————————————————————
|
|
7625
|
+
"Verify nightly backups completed successfully and alert me if any failed",
|
|
7626
|
+
"Test restore from backup on a sample workload every month and report results",
|
|
7627
|
+
"Watch our public status page for incidents at our critical vendors and notify the team",
|
|
7628
|
+
"Ping our public endpoints every minute and open an incident if any return non-2xx for 3 minutes",
|
|
7629
|
+
// — Tickets, workflow & docs ——————————————————————————————————
|
|
7630
|
+
"Triage new Jira tickets in the security project every hour and assign by category",
|
|
7631
|
+
"Close tickets that have been waiting on the reporter for more than 14 days",
|
|
7632
|
+
"Summarise this week's closed tickets into release notes every Friday",
|
|
7633
|
+
"Pull action items out of meeting notes I share and create tickets for them",
|
|
7634
|
+
"Keep the on-call runbook in sync with the latest incident postmortems",
|
|
7635
|
+
"Review pull requests in our security repos and leave a summary comment within an hour",
|
|
7636
|
+
// — People, HR & onboarding ————————————————————————————————————
|
|
7637
|
+
"Send a welcome message and security training link to every new joiner on their start date",
|
|
7638
|
+
"Run the offboarding checklist whenever someone is marked as a leaver in HR",
|
|
7639
|
+
"Remind managers to complete quarterly performance reviews 1 week before the deadline",
|
|
7640
|
+
"Send birthday and work anniversary greetings from me on the right day",
|
|
7641
|
+
// — Personal / lightweight ops chores —————————————————————————
|
|
7642
|
+
"Order more office coffee whenever the inventory drops below 2 bags",
|
|
7643
|
+
"File my receipts every Friday and submit the expense report",
|
|
7644
|
+
"Track my open invoices and chase clients whose payment is more than 14 days overdue",
|
|
7645
|
+
"Send a polite follow-up to anyone I have emailed but who has not replied in 5 working days",
|
|
7646
|
+
"Read the security news feeds every morning and summarise the top 5 stories for me"
|
|
7647
|
+
];
|
|
7648
|
+
var matchAgentPromptSuggestions = (input, limit = 8) => {
|
|
7649
|
+
const q = (input || "").trim().toLowerCase();
|
|
7650
|
+
if (!q) return [];
|
|
7651
|
+
const scored = [];
|
|
7652
|
+
for (const text of AGENT_PROMPT_SUGGESTIONS) {
|
|
7653
|
+
const lower = text.toLowerCase();
|
|
7654
|
+
const idx = lower.indexOf(q);
|
|
7655
|
+
if (idx < 0) continue;
|
|
7656
|
+
const score = idx === 0 ? -1e3 + text.length : idx * 10 + text.length;
|
|
7657
|
+
scored.push({ text, score });
|
|
7658
|
+
}
|
|
7659
|
+
scored.sort((a, b) => a.score - b.score);
|
|
7660
|
+
return scored.slice(0, limit).map((s) => s.text);
|
|
7661
|
+
};
|
|
7662
|
+
var DEFAULT_AGENT_PROMPT_PLACEHOLDER = "Take care of my emails by pretending to be me and answering them";
|
|
7663
|
+
|
|
7664
|
+
// components/AgentUI.tsx
|
|
7263
7665
|
import remarkGfm4 from "remark-gfm";
|
|
7264
7666
|
import remarkBreaks from "remark-breaks";
|
|
7265
7667
|
import JsonView2 from "react18-json-view";
|
|
@@ -7402,6 +7804,73 @@ function invalidateResolvedApps() {
|
|
|
7402
7804
|
_cache.clear();
|
|
7403
7805
|
}
|
|
7404
7806
|
|
|
7807
|
+
// llmProviderDetect.ts
|
|
7808
|
+
var SHUFFLE_AI_PRESET = "Shuffle AI";
|
|
7809
|
+
var CUSTOM_PRESET = "Custom / self-hosted";
|
|
7810
|
+
var ENDPOINT_PRESETS = [
|
|
7811
|
+
{ label: SHUFFLE_AI_PRESET, url: "" },
|
|
7812
|
+
{ label: "OpenAI", url: "https://api.openai.com/v1", apiKeyUrl: "https://platform.openai.com/api-keys", apiKeyHint: "Create a key under API keys in the OpenAI platform dashboard." },
|
|
7813
|
+
{ label: "Anthropic", url: "https://api.anthropic.com/v1/", apiKeyUrl: "https://console.anthropic.com/settings/keys", apiKeyHint: "Generate a key under Settings \u2192 API Keys in the Anthropic Console." },
|
|
7814
|
+
{ label: "Google Gemini", url: "https://generativelanguage.googleapis.com/v1beta/openai/", apiKeyUrl: "https://aistudio.google.com/app/apikey", apiKeyHint: "Create a key in Google AI Studio under Get API key." },
|
|
7815
|
+
{ label: "Mistral", url: "https://api.mistral.ai/v1", apiKeyUrl: "https://console.mistral.ai/api-keys/", apiKeyHint: "Create a key under API Keys in the Mistral Console." },
|
|
7816
|
+
{ label: "Groq", url: "https://api.groq.com/openai/v1", apiKeyUrl: "https://console.groq.com/keys", apiKeyHint: "Create a key under API Keys in the Groq Console." },
|
|
7817
|
+
{ label: "DeepSeek", url: "https://api.deepseek.com/v1", apiKeyUrl: "https://platform.deepseek.com/api_keys", apiKeyHint: "Create a key under API Keys in the DeepSeek platform." },
|
|
7818
|
+
{ label: "Together AI", url: "https://api.together.xyz/v1", apiKeyUrl: "https://api.together.ai/settings/api-keys", apiKeyHint: "Create a key under Settings \u2192 API Keys in Together AI." },
|
|
7819
|
+
{ label: "OpenRouter", url: "https://openrouter.ai/api/v1", apiKeyUrl: "https://openrouter.ai/keys", apiKeyHint: "Create a key under Keys in your OpenRouter dashboard." },
|
|
7820
|
+
{ label: "Ollama (localhost)", url: "http://localhost:11434/v1", apiKeyHint: "Local Ollama does not require an API key \u2014 any non-empty value works." },
|
|
7821
|
+
{ 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." },
|
|
7822
|
+
{ label: CUSTOM_PRESET, url: "" }
|
|
7823
|
+
];
|
|
7824
|
+
var PROVIDER_DOMAINS = {
|
|
7825
|
+
"Shuffle AI": "shuffler.io",
|
|
7826
|
+
OpenAI: "openai.com",
|
|
7827
|
+
Anthropic: "anthropic.com",
|
|
7828
|
+
"Google Gemini": "gemini.google.com",
|
|
7829
|
+
Mistral: "mistral.ai",
|
|
7830
|
+
Groq: "groq.com",
|
|
7831
|
+
DeepSeek: "deepseek.com",
|
|
7832
|
+
"Together AI": "together.ai",
|
|
7833
|
+
OpenRouter: "openrouter.ai",
|
|
7834
|
+
"Ollama (localhost)": "ollama.com",
|
|
7835
|
+
"LM Studio (localhost)": "lmstudio.ai"
|
|
7836
|
+
};
|
|
7837
|
+
var hostnameOf = (url) => {
|
|
7838
|
+
try {
|
|
7839
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
7840
|
+
} catch {
|
|
7841
|
+
return null;
|
|
7842
|
+
}
|
|
7843
|
+
};
|
|
7844
|
+
var detectLLMProvider = (url) => {
|
|
7845
|
+
if (!url) return null;
|
|
7846
|
+
const trimmed = url.trim();
|
|
7847
|
+
if (!trimmed) return null;
|
|
7848
|
+
const exact = ENDPOINT_PRESETS.find((p) => p.url && p.url === trimmed);
|
|
7849
|
+
if (exact) return exact;
|
|
7850
|
+
const host = hostnameOf(trimmed);
|
|
7851
|
+
if (host) {
|
|
7852
|
+
const byHost = ENDPOINT_PRESETS.find((p) => {
|
|
7853
|
+
const presetHost = hostnameOf(p.url);
|
|
7854
|
+
return presetHost && presetHost === host;
|
|
7855
|
+
});
|
|
7856
|
+
if (byHost) return byHost;
|
|
7857
|
+
if (host === "localhost" || host === "127.0.0.1") {
|
|
7858
|
+
if (trimmed.includes(":11434")) return ENDPOINT_PRESETS.find((p) => p.label === "Ollama (localhost)") || null;
|
|
7859
|
+
if (trimmed.includes(":1234")) return ENDPOINT_PRESETS.find((p) => p.label === "LM Studio (localhost)") || null;
|
|
7860
|
+
}
|
|
7861
|
+
}
|
|
7862
|
+
return ENDPOINT_PRESETS.find((p) => p.label === CUSTOM_PRESET) || null;
|
|
7863
|
+
};
|
|
7864
|
+
var getProviderLogoUrl = (label, url) => {
|
|
7865
|
+
if (!label && !url) return "";
|
|
7866
|
+
let domain = label ? PROVIDER_DOMAINS[label] : void 0;
|
|
7867
|
+
if (!domain && url) {
|
|
7868
|
+
const host = hostnameOf(url);
|
|
7869
|
+
if (host) domain = host;
|
|
7870
|
+
}
|
|
7871
|
+
return domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
7872
|
+
};
|
|
7873
|
+
|
|
7405
7874
|
// agentRun.ts
|
|
7406
7875
|
var resolveTarget = (path, opts = {}) => {
|
|
7407
7876
|
const url = opts.apiBaseUrl ? `${opts.apiBaseUrl.replace(/\/+$/, "")}${path}` : getApiUrl(path);
|
|
@@ -8315,10 +8784,10 @@ var AgentRunDiagnosisBanner = ({ run, sx, onJumpToEvidence, executionId }) => {
|
|
|
8315
8784
|
const outputWarning = !isFailed && hasOutputWarning(run);
|
|
8316
8785
|
const diagnosis = outputWarning ? diagnoseOutputWarning(run) : null;
|
|
8317
8786
|
if (!failureInfo && !diagnosis) return null;
|
|
8318
|
-
const isCritical = !!failureInfo;
|
|
8787
|
+
const isCritical = !!failureInfo || diagnosis?.kind === "token_limit";
|
|
8319
8788
|
const tone = isCritical ? "critical" : "medium";
|
|
8320
8789
|
const Icon = isCritical ? AlertTriangle : HelpCircle;
|
|
8321
|
-
const message =
|
|
8790
|
+
const message = failureInfo ? failureInfo.reason : `${diagnosis.title} \u2014 ${diagnosis.remediation}`;
|
|
8322
8791
|
const firstEvidence = diagnosis?.evidence?.[0] || null;
|
|
8323
8792
|
const jumpDecisionIndex = firstEvidence ? extractDecisionIndex(firstEvidence.path) : null;
|
|
8324
8793
|
const canJump = !!(onJumpToEvidence && jumpDecisionIndex !== null);
|
|
@@ -8857,7 +9326,7 @@ var TimelineRow = ({
|
|
|
8857
9326
|
),
|
|
8858
9327
|
/* @__PURE__ */ jsx20(Box14, { sx: {
|
|
8859
9328
|
flex: 1,
|
|
8860
|
-
minWidth:
|
|
9329
|
+
minWidth: 180,
|
|
8861
9330
|
fontSize: "0.85rem",
|
|
8862
9331
|
color: "hsl(var(--foreground))",
|
|
8863
9332
|
maxHeight: 60,
|
|
@@ -8867,7 +9336,7 @@ var TimelineRow = ({
|
|
|
8867
9336
|
"& a": { color: "hsl(var(--primary))", textDecoration: "underline", textUnderlineOffset: "2px" },
|
|
8868
9337
|
"& a:hover": { opacity: 0.85 }
|
|
8869
9338
|
}, children: /* @__PURE__ */ jsx20(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(displayLabel) }) }),
|
|
8870
|
-
/* @__PURE__ */ jsx20(Tooltip9, { title: hasTiming ? `Duration: ${dur.toFixed(2)}s \xB7 ${new Date(itemStart * 1e3).toLocaleString()}` : "No timing data", children: /* @__PURE__ */ jsx20(Box14, { sx: { width: maxWidth, position: "relative", height: 10, flexShrink:
|
|
9339
|
+
/* @__PURE__ */ jsx20(Tooltip9, { title: hasTiming ? `Duration: ${dur.toFixed(2)}s \xB7 ${new Date(itemStart * 1e3).toLocaleString()}` : "No timing data", children: /* @__PURE__ */ jsx20(Box14, { sx: { width: maxWidth, maxWidth, minWidth: 40, position: "relative", height: 10, flexShrink: 1, flexBasis: maxWidth }, children: dur > 0 && /* @__PURE__ */ jsx20(Box14, { sx: {
|
|
8871
9340
|
position: "absolute",
|
|
8872
9341
|
left: Math.max(0, offset),
|
|
8873
9342
|
width,
|
|
@@ -9193,7 +9662,7 @@ var AgentUI = ({
|
|
|
9193
9662
|
autoLoadApps = true,
|
|
9194
9663
|
title = "What do you want to do?",
|
|
9195
9664
|
subtitle,
|
|
9196
|
-
placeholder =
|
|
9665
|
+
placeholder = DEFAULT_AGENT_PROMPT_PLACEHOLDER,
|
|
9197
9666
|
defaultInput = "",
|
|
9198
9667
|
autoSubmit = false,
|
|
9199
9668
|
hideHeroIcon = false,
|
|
@@ -9245,6 +9714,29 @@ var AgentUI = ({
|
|
|
9245
9714
|
const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
|
|
9246
9715
|
const navigate = useNavigate();
|
|
9247
9716
|
const [actionInput, setActionInput] = useState12(defaultInput);
|
|
9717
|
+
const promptAnchorRef = React4.useRef(null);
|
|
9718
|
+
const [suggestionsDismissed, setSuggestionsDismissed] = useState12(false);
|
|
9719
|
+
const [suggestionIndex, setSuggestionIndex] = useState12(-1);
|
|
9720
|
+
const promptSuggestions = useMemo6(
|
|
9721
|
+
() => matchAgentPromptSuggestions(actionInput, 8),
|
|
9722
|
+
[actionInput]
|
|
9723
|
+
);
|
|
9724
|
+
useEffect11(() => {
|
|
9725
|
+
setSuggestionIndex(-1);
|
|
9726
|
+
setSuggestionsDismissed(false);
|
|
9727
|
+
}, [actionInput]);
|
|
9728
|
+
const suggestionsOpen = promptSuggestions.length > 0 && !suggestionsDismissed;
|
|
9729
|
+
const acceptSuggestion = useCallback8((s) => {
|
|
9730
|
+
setActionInput(s);
|
|
9731
|
+
setSuggestionsDismissed(true);
|
|
9732
|
+
setSuggestionIndex(-1);
|
|
9733
|
+
requestAnimationFrame(() => {
|
|
9734
|
+
try {
|
|
9735
|
+
inputRef.current?.focus();
|
|
9736
|
+
} catch {
|
|
9737
|
+
}
|
|
9738
|
+
});
|
|
9739
|
+
}, []);
|
|
9248
9740
|
const BUILTIN_DEFAULT_APPS = [
|
|
9249
9741
|
{ name: "http" },
|
|
9250
9742
|
{ name: "shuffle_tools" }
|
|
@@ -9252,6 +9744,7 @@ var AgentUI = ({
|
|
|
9252
9744
|
const [chosenApps, setChosenApps] = useState12(apps ?? defaultApps ?? BUILTIN_DEFAULT_APPS);
|
|
9253
9745
|
const [availableApps, setAvailableApps] = useState12([]);
|
|
9254
9746
|
const [authAppsLoading, setAuthAppsLoading] = useState12(autoLoadApps && hasApiKey);
|
|
9747
|
+
const [detectedLLM, setDetectedLLM] = useState12(null);
|
|
9255
9748
|
const [executionApps, setExecutionApps] = useState12([]);
|
|
9256
9749
|
const [resolvedToolApps, setResolvedToolApps] = useState12({});
|
|
9257
9750
|
const [appSearchOpen, setAppSearchOpen] = useState12(false);
|
|
@@ -9286,9 +9779,25 @@ var AgentUI = ({
|
|
|
9286
9779
|
const [error, setError] = useState12(null);
|
|
9287
9780
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
9288
9781
|
const initialViewParam = searchParams.get("agentView");
|
|
9289
|
-
const
|
|
9290
|
-
initialViewParam === "detailed"
|
|
9291
|
-
|
|
9782
|
+
const readStoredViewMode = () => {
|
|
9783
|
+
if (initialViewParam === "detailed") return "detailed";
|
|
9784
|
+
if (typeof window === "undefined") return "simple";
|
|
9785
|
+
try {
|
|
9786
|
+
const stored = window.localStorage.getItem("shuffle-agents-view-mode");
|
|
9787
|
+
if (stored === "detailed" || stored === "simple") return stored;
|
|
9788
|
+
} catch {
|
|
9789
|
+
}
|
|
9790
|
+
return "simple";
|
|
9791
|
+
};
|
|
9792
|
+
const [viewMode, setViewMode] = useState12(readStoredViewMode);
|
|
9793
|
+
useEffect11(() => {
|
|
9794
|
+
try {
|
|
9795
|
+
if (typeof window !== "undefined") {
|
|
9796
|
+
window.localStorage.setItem("shuffle-agents-view-mode", viewMode);
|
|
9797
|
+
}
|
|
9798
|
+
} catch {
|
|
9799
|
+
}
|
|
9800
|
+
}, [viewMode]);
|
|
9292
9801
|
const [attachedImages, setAttachedImages] = useState12([]);
|
|
9293
9802
|
const [nowTick, setNowTick] = useState12(() => Math.floor(Date.now() / 1e3));
|
|
9294
9803
|
const [localRunStart, setLocalRunStart] = useState12(null);
|
|
@@ -9524,12 +10033,23 @@ var AgentUI = ({
|
|
|
9524
10033
|
const list = Array.isArray(result) ? result : result?.data || [];
|
|
9525
10034
|
const seen = /* @__PURE__ */ new Set();
|
|
9526
10035
|
const loaded = [];
|
|
10036
|
+
let detectedFromEntries = null;
|
|
9527
10037
|
for (const entry of list) {
|
|
9528
10038
|
const app = entry?.app || entry;
|
|
9529
10039
|
const name = app?.name;
|
|
9530
10040
|
if (!name) continue;
|
|
9531
10041
|
const valid = entry?.active || entry?.validation?.valid || entry?.hasValidAuth || app?.is_valid || app?.tested;
|
|
9532
10042
|
if (valid === false) continue;
|
|
10043
|
+
if (!detectedFromEntries && (name.toLowerCase() === "openai" || app?.id === "5d19dd82517870c68d40cacad9b5ca91")) {
|
|
10044
|
+
const urlField = (entry?.fields || []).find((f) => (f?.key || "").toLowerCase() === "url");
|
|
10045
|
+
const urlVal = (urlField?.value || "").trim();
|
|
10046
|
+
if (urlVal) {
|
|
10047
|
+
const preset = detectLLMProvider(urlVal);
|
|
10048
|
+
if (preset) {
|
|
10049
|
+
detectedFromEntries = { label: preset.label, url: urlVal, logo: getProviderLogoUrl(preset.label, urlVal) };
|
|
10050
|
+
}
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
9533
10053
|
const key = normalizeAgentAppName(name);
|
|
9534
10054
|
if (seen.has(key)) continue;
|
|
9535
10055
|
seen.add(key);
|
|
@@ -9541,6 +10061,7 @@ var AgentUI = ({
|
|
|
9541
10061
|
}
|
|
9542
10062
|
if (signal?.cancelled) return;
|
|
9543
10063
|
setAvailableApps(loaded);
|
|
10064
|
+
setDetectedLLM(detectedFromEntries);
|
|
9544
10065
|
} catch {
|
|
9545
10066
|
} finally {
|
|
9546
10067
|
if (!signal?.cancelled) setAuthAppsLoading(false);
|
|
@@ -9802,7 +10323,12 @@ var AgentUI = ({
|
|
|
9802
10323
|
setSimpleSubmitAttempted(false);
|
|
9803
10324
|
setError(null);
|
|
9804
10325
|
setLocalRunStart(null);
|
|
9805
|
-
|
|
10326
|
+
try {
|
|
10327
|
+
const stored = typeof window !== "undefined" ? window.localStorage.getItem("shuffle-agents-view-mode") : null;
|
|
10328
|
+
setViewMode(stored === "detailed" ? "detailed" : "simple");
|
|
10329
|
+
} catch {
|
|
10330
|
+
setViewMode("simple");
|
|
10331
|
+
}
|
|
9806
10332
|
setShowStarter(false);
|
|
9807
10333
|
userPickedStartRef.current = false;
|
|
9808
10334
|
if (readUrlParams && typeof window !== "undefined") {
|
|
@@ -10238,6 +10764,34 @@ var AgentUI = ({
|
|
|
10238
10764
|
}
|
|
10239
10765
|
}, [submitOverride, actionInput, chosenApps, submitInput]);
|
|
10240
10766
|
const onKeyDown = (e) => {
|
|
10767
|
+
if (suggestionsOpen && promptSuggestions.length > 0) {
|
|
10768
|
+
if (e.key === "ArrowDown") {
|
|
10769
|
+
e.preventDefault();
|
|
10770
|
+
setSuggestionIndex((i) => (i + 1) % promptSuggestions.length);
|
|
10771
|
+
return;
|
|
10772
|
+
}
|
|
10773
|
+
if (e.key === "ArrowUp") {
|
|
10774
|
+
e.preventDefault();
|
|
10775
|
+
setSuggestionIndex((i) => i <= 0 ? promptSuggestions.length - 1 : i - 1);
|
|
10776
|
+
return;
|
|
10777
|
+
}
|
|
10778
|
+
if (e.key === "Escape") {
|
|
10779
|
+
e.preventDefault();
|
|
10780
|
+
setSuggestionsDismissed(true);
|
|
10781
|
+
setSuggestionIndex(-1);
|
|
10782
|
+
return;
|
|
10783
|
+
}
|
|
10784
|
+
if (e.key === "Tab" && suggestionIndex >= 0) {
|
|
10785
|
+
e.preventDefault();
|
|
10786
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10787
|
+
return;
|
|
10788
|
+
}
|
|
10789
|
+
if (e.key === "Enter" && suggestionIndex >= 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
|
10790
|
+
e.preventDefault();
|
|
10791
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
10792
|
+
return;
|
|
10793
|
+
}
|
|
10794
|
+
}
|
|
10241
10795
|
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
10242
10796
|
e.preventDefault();
|
|
10243
10797
|
handlePrimarySubmit();
|
|
@@ -10895,7 +11449,7 @@ var AgentUI = ({
|
|
|
10895
11449
|
mt: -1,
|
|
10896
11450
|
maxWidth: 600
|
|
10897
11451
|
}, children: subtitle }),
|
|
10898
|
-
/* @__PURE__ */ jsxs17(Box14, { sx: {
|
|
11452
|
+
/* @__PURE__ */ jsxs17(Box14, { ref: promptAnchorRef, sx: {
|
|
10899
11453
|
width: "100%",
|
|
10900
11454
|
display: "flex",
|
|
10901
11455
|
flexDirection: "column",
|
|
@@ -11103,6 +11657,67 @@ var AgentUI = ({
|
|
|
11103
11657
|
) }) })
|
|
11104
11658
|
] })
|
|
11105
11659
|
] }),
|
|
11660
|
+
/* @__PURE__ */ jsx20(
|
|
11661
|
+
Popper,
|
|
11662
|
+
{
|
|
11663
|
+
open: suggestionsOpen,
|
|
11664
|
+
anchorEl: promptAnchorRef.current,
|
|
11665
|
+
placement: "bottom-start",
|
|
11666
|
+
style: { zIndex: 1300, width: promptAnchorRef.current?.offsetWidth },
|
|
11667
|
+
modifiers: [{ name: "offset", options: { offset: [0, 6] } }],
|
|
11668
|
+
children: /* @__PURE__ */ jsx20(ClickAwayListener, { onClickAway: () => setSuggestionsDismissed(true), children: /* @__PURE__ */ jsx20(
|
|
11669
|
+
Paper,
|
|
11670
|
+
{
|
|
11671
|
+
elevation: 6,
|
|
11672
|
+
sx: {
|
|
11673
|
+
bgcolor: "hsl(var(--card))",
|
|
11674
|
+
border: "1px solid hsl(var(--border))",
|
|
11675
|
+
borderRadius: 2,
|
|
11676
|
+
overflow: "hidden",
|
|
11677
|
+
maxHeight: 320,
|
|
11678
|
+
overflowY: "auto"
|
|
11679
|
+
},
|
|
11680
|
+
children: /* @__PURE__ */ jsx20(MenuList, { dense: true, disablePadding: true, children: promptSuggestions.map((s, i) => {
|
|
11681
|
+
const q = actionInput.trim();
|
|
11682
|
+
const lower = s.toLowerCase();
|
|
11683
|
+
const idx = q ? lower.indexOf(q.toLowerCase()) : -1;
|
|
11684
|
+
const before = idx >= 0 ? s.slice(0, idx) : s;
|
|
11685
|
+
const match = idx >= 0 ? s.slice(idx, idx + q.length) : "";
|
|
11686
|
+
const after = idx >= 0 ? s.slice(idx + q.length) : "";
|
|
11687
|
+
return /* @__PURE__ */ jsxs17(
|
|
11688
|
+
MenuItem2,
|
|
11689
|
+
{
|
|
11690
|
+
selected: i === suggestionIndex,
|
|
11691
|
+
onMouseEnter: () => setSuggestionIndex(i),
|
|
11692
|
+
onMouseDown: (e) => {
|
|
11693
|
+
e.preventDefault();
|
|
11694
|
+
acceptSuggestion(s);
|
|
11695
|
+
},
|
|
11696
|
+
sx: {
|
|
11697
|
+
fontSize: "0.88rem",
|
|
11698
|
+
color: "hsl(var(--foreground))",
|
|
11699
|
+
py: 0.75,
|
|
11700
|
+
px: 2,
|
|
11701
|
+
"&.Mui-selected, &.Mui-selected:hover": {
|
|
11702
|
+
bgcolor: "hsl(var(--muted) / 0.6)"
|
|
11703
|
+
}
|
|
11704
|
+
},
|
|
11705
|
+
children: [
|
|
11706
|
+
/* @__PURE__ */ jsx20(SearchIcon, { size: 14, style: { marginRight: 10, color: "hsl(var(--muted-foreground))", flexShrink: 0 } }),
|
|
11707
|
+
/* @__PURE__ */ jsxs17(Box14, { component: "span", sx: { whiteSpace: "normal", lineHeight: 1.4 }, children: [
|
|
11708
|
+
before,
|
|
11709
|
+
/* @__PURE__ */ jsx20(Box14, { component: "span", sx: { fontWeight: 700, color: "hsl(var(--foreground))" }, children: match }),
|
|
11710
|
+
after
|
|
11711
|
+
] })
|
|
11712
|
+
]
|
|
11713
|
+
},
|
|
11714
|
+
s
|
|
11715
|
+
);
|
|
11716
|
+
}) })
|
|
11717
|
+
}
|
|
11718
|
+
) })
|
|
11719
|
+
}
|
|
11720
|
+
),
|
|
11106
11721
|
!hideAppPicker && /* @__PURE__ */ jsx20(Box14, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs17(Box14, { sx: {
|
|
11107
11722
|
display: "inline-flex",
|
|
11108
11723
|
flexWrap: "wrap",
|
|
@@ -11153,8 +11768,19 @@ var AgentUI = ({
|
|
|
11153
11768
|
"&:hover": { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted) / 0.5)" }
|
|
11154
11769
|
},
|
|
11155
11770
|
children: [
|
|
11156
|
-
/* @__PURE__ */ jsx20(
|
|
11157
|
-
|
|
11771
|
+
detectedLLM?.logo ? /* @__PURE__ */ jsx20(
|
|
11772
|
+
Box14,
|
|
11773
|
+
{
|
|
11774
|
+
component: "img",
|
|
11775
|
+
src: detectedLLM.logo,
|
|
11776
|
+
alt: "",
|
|
11777
|
+
sx: { width: 14, height: 14, borderRadius: "3px", objectFit: "contain", display: "block" },
|
|
11778
|
+
onError: (e) => {
|
|
11779
|
+
e.currentTarget.style.display = "none";
|
|
11780
|
+
}
|
|
11781
|
+
}
|
|
11782
|
+
) : /* @__PURE__ */ jsx20(SettingsIcon, { size: 14 }),
|
|
11783
|
+
detectedLLM?.label || "Choose LLM"
|
|
11158
11784
|
]
|
|
11159
11785
|
}
|
|
11160
11786
|
) }),
|
|
@@ -11388,7 +12014,7 @@ var AgentUI = ({
|
|
|
11388
12014
|
AgentRunDiagnosisBanner_default,
|
|
11389
12015
|
{
|
|
11390
12016
|
run: execution?.results?.length ? execution : agentData,
|
|
11391
|
-
sx: { px:
|
|
12017
|
+
sx: { px: 1.5, pb: 0, mb: 2 },
|
|
11392
12018
|
executionId: execution?.execution_id,
|
|
11393
12019
|
onJumpToEvidence: (decisionIndex) => {
|
|
11394
12020
|
const dec = (agentData?.decisions || [])[decisionIndex];
|
|
@@ -11613,14 +12239,14 @@ var AgentUI = ({
|
|
|
11613
12239
|
] })
|
|
11614
12240
|
] });
|
|
11615
12241
|
})() : !finishAnswer && isRunning ? /* @__PURE__ */ jsx20(Typography13, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "Waiting for the agent to produce the first step." }) : !finishAnswer ? /* @__PURE__ */ jsx20(Typography13, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "No final answer was returned. Open Detailed to inspect each step." }) : null,
|
|
11616
|
-
|
|
12242
|
+
/* @__PURE__ */ jsx20(Box14, { children: /* @__PURE__ */ jsx20(
|
|
11617
12243
|
Button8,
|
|
11618
12244
|
{
|
|
11619
12245
|
size: "small",
|
|
11620
12246
|
variant: "text",
|
|
11621
12247
|
onClick: () => setViewMode("detailed"),
|
|
11622
12248
|
sx: { color: "hsl(var(--primary))", textTransform: "none", px: 0 },
|
|
11623
|
-
children: "View detailed timeline \u2192"
|
|
12249
|
+
children: isRunning ? "View live detailed timeline \u2192" : "View detailed timeline \u2192"
|
|
11624
12250
|
}
|
|
11625
12251
|
) })
|
|
11626
12252
|
] });
|
|
@@ -11825,7 +12451,7 @@ import {
|
|
|
11825
12451
|
} from "lucide-react";
|
|
11826
12452
|
|
|
11827
12453
|
// components/LocalLLMConfig.tsx
|
|
11828
|
-
import { useEffect as useEffect12, useMemo as useMemo7,
|
|
12454
|
+
import { useEffect as useEffect12, useMemo as useMemo7, useState as useState13 } from "react";
|
|
11829
12455
|
import {
|
|
11830
12456
|
Autocomplete as Autocomplete3,
|
|
11831
12457
|
Box as Box16,
|
|
@@ -11924,8 +12550,6 @@ import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs19 } from "react/jsx-r
|
|
|
11924
12550
|
import { createElement as createElement2 } from "react";
|
|
11925
12551
|
var OPENAI_APP_NAME = "OpenAI";
|
|
11926
12552
|
var OPENAI_APP_ID = "5d19dd82517870c68d40cacad9b5ca91";
|
|
11927
|
-
var SHUFFLE_AI_PRESET = "Shuffle AI";
|
|
11928
|
-
var CUSTOM_PRESET = "Custom / self-hosted";
|
|
11929
12553
|
var OPENAI_ALGOLIA_APP = {
|
|
11930
12554
|
name: OPENAI_APP_NAME,
|
|
11931
12555
|
description: "OpenAI-compatible LLM endpoint for agent operations",
|
|
@@ -11945,20 +12569,32 @@ var OPENAI_ALGOLIA_APP = {
|
|
|
11945
12569
|
triggers: [],
|
|
11946
12570
|
verified: true
|
|
11947
12571
|
};
|
|
11948
|
-
var
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
11952
|
-
|
|
11953
|
-
|
|
11954
|
-
|
|
11955
|
-
|
|
11956
|
-
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
12572
|
+
var CUSTOM_MODEL = "Custom\u2026";
|
|
12573
|
+
var PROVIDER_MODELS = {
|
|
12574
|
+
OpenAI: ["gpt-5.5", "gpt-5.5-pro", "gpt-5.4", "gpt-5.4-pro", "gpt-5.4-mini", "gpt-5.4-nano", "gpt-5.2", "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-4.1", "o4-mini"],
|
|
12575
|
+
Anthropic: ["claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "claude-opus-4", "claude-sonnet-4", "claude-3-7-sonnet-latest"],
|
|
12576
|
+
"Google Gemini": ["gemini-3-pro-preview", "gemini-3-flash-preview", "gemini-3.1-pro-preview", "gemini-3.1-flash-lite-preview", "gemini-3.5-flash", "gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite"],
|
|
12577
|
+
Mistral: ["mistral-large-2026", "mistral-medium-3", "mistral-small-3.2", "codestral-2026", "magistral-medium-2026", "ministral-8b-latest"],
|
|
12578
|
+
Groq: ["llama-4-maverick-17b-128e", "llama-4-scout-17b-16e", "llama-3.3-70b-versatile", "deepseek-r1-distill-llama-70b", "qwen-3-32b", "kimi-k2-instruct"],
|
|
12579
|
+
DeepSeek: ["deepseek-v3.5", "deepseek-v3", "deepseek-r1", "deepseek-coder-v3"],
|
|
12580
|
+
"Together AI": ["meta-llama/Llama-4-Maverick-17B-128E-Instruct", "meta-llama/Llama-4-Scout-17B-16E-Instruct", "deepseek-ai/DeepSeek-V3", "deepseek-ai/DeepSeek-R1", "Qwen/Qwen3-235B-A22B"],
|
|
12581
|
+
OpenRouter: ["openai/gpt-5.5", "openai/gpt-5.4", "anthropic/claude-opus-4.5", "anthropic/claude-sonnet-4.5", "google/gemini-3-pro-preview", "google/gemini-3-flash-preview", "meta-llama/llama-4-maverick", "deepseek/deepseek-v3.5", "x-ai/grok-4"],
|
|
12582
|
+
"Ollama (localhost)": ["llama3.3", "llama3.2", "qwen3", "qwen3:32b", "deepseek-r1", "deepseek-r1:70b", "mistral-small3", "phi4", "gemma3"],
|
|
12583
|
+
"LM Studio (localhost)": ["llama-3.3-70b-instruct", "qwen3-32b", "deepseek-r1-distill-qwen-32b", "mistral-small-3", "phi-4", "gemma-3-27b"]
|
|
12584
|
+
};
|
|
12585
|
+
var ProviderLogo = ({ label, url }) => {
|
|
12586
|
+
const [errored, setErrored] = useState13(false);
|
|
12587
|
+
let domain = PROVIDER_DOMAINS[label];
|
|
12588
|
+
if (!domain && url) {
|
|
12589
|
+
try {
|
|
12590
|
+
domain = new URL(url).hostname.replace(/^www\./, "");
|
|
12591
|
+
} catch {
|
|
12592
|
+
}
|
|
12593
|
+
}
|
|
12594
|
+
const src = domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
12595
|
+
const initial = label.trim().charAt(0).toUpperCase() || "?";
|
|
12596
|
+
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 }) });
|
|
12597
|
+
};
|
|
11962
12598
|
var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode }) => {
|
|
11963
12599
|
useSyncHostBaseUrl(globalUrl);
|
|
11964
12600
|
const { authStates, authenticatedApps, handleAuthChange, handleTestConnection, handleSaveAuth, refreshAuth } = useAppAuth();
|
|
@@ -11974,46 +12610,16 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
11974
12610
|
status: "pending",
|
|
11975
12611
|
credentials: {}
|
|
11976
12612
|
};
|
|
11977
|
-
const
|
|
11978
|
-
const
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
const failedEntries = openaiEntries.filter((e) => e.validation && e.validation.valid === false && e.id);
|
|
11982
|
-
if (failedEntries.length === 0) return;
|
|
11983
|
-
let cancelled = false;
|
|
11984
|
-
(async () => {
|
|
11985
|
-
let deletedAny = false;
|
|
11986
|
-
for (const entry of failedEntries) {
|
|
11987
|
-
const id = entry.id;
|
|
11988
|
-
if (attemptedDeletionRef.current.has(id)) continue;
|
|
11989
|
-
attemptedDeletionRef.current.add(id);
|
|
11990
|
-
try {
|
|
11991
|
-
const resp = await fetch(getApiUrl(`/api/v1/apps/authentication/${id}`), {
|
|
11992
|
-
method: "DELETE",
|
|
11993
|
-
credentials: "include",
|
|
11994
|
-
headers: { ...getAuthHeader() }
|
|
11995
|
-
});
|
|
11996
|
-
if (resp.ok) deletedAny = true;
|
|
11997
|
-
} catch (err) {
|
|
11998
|
-
console.error("[LocalLLMConfig] Failed to auto-delete failed OpenAI auth:", err);
|
|
11999
|
-
}
|
|
12000
|
-
}
|
|
12001
|
-
if (!cancelled && deletedAny) {
|
|
12002
|
-
await refreshAuth();
|
|
12003
|
-
refreshAllIntegrationStatus();
|
|
12004
|
-
}
|
|
12005
|
-
})();
|
|
12006
|
-
return () => {
|
|
12007
|
-
cancelled = true;
|
|
12008
|
-
};
|
|
12009
|
-
}, [openaiEntries, authState.status, refreshAuth]);
|
|
12613
|
+
const savedUrlFromEntry = (openaiEntries[0]?.fields || []).find((f) => (f?.key || "").toLowerCase() === "url")?.value || "";
|
|
12614
|
+
const currentUrl = (authState.credentials?.url || savedUrlFromEntry || "").trim();
|
|
12615
|
+
const [customModel, setCustomModel] = useState13("");
|
|
12616
|
+
const [customMode, setCustomMode] = useState13(false);
|
|
12010
12617
|
const hasOpenAIEntries = openaiEntries.length > 0;
|
|
12011
12618
|
const effectivePreset = useMemo7(() => {
|
|
12012
12619
|
if (selectedPreset) return selectedPreset;
|
|
12013
12620
|
if (!currentUrl && !hasOpenAIEntries) return SHUFFLE_AI_PRESET;
|
|
12014
12621
|
if (!currentUrl) return "";
|
|
12015
|
-
|
|
12016
|
-
return match ? match.label : CUSTOM_PRESET;
|
|
12622
|
+
return detectLLMProvider(currentUrl)?.label || CUSTOM_PRESET;
|
|
12017
12623
|
}, [selectedPreset, currentUrl, hasOpenAIEntries]);
|
|
12018
12624
|
const applyShuffleAI = async () => {
|
|
12019
12625
|
let deletedAny = false;
|
|
@@ -12050,7 +12656,16 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12050
12656
|
setSelectedPreset(label);
|
|
12051
12657
|
const preset = ENDPOINT_PRESETS.find((p) => p.label === label);
|
|
12052
12658
|
if (!preset) return;
|
|
12053
|
-
|
|
12659
|
+
const topModel = PROVIDER_MODELS[label]?.[0] || "";
|
|
12660
|
+
const existingModel = authState.credentials?.model || "";
|
|
12661
|
+
const nextModel = topModel || existingModel;
|
|
12662
|
+
setCustomMode(false);
|
|
12663
|
+
setCustomModel("");
|
|
12664
|
+
handleAuthChange(OPENAI_APP_ID, {
|
|
12665
|
+
...authState.credentials,
|
|
12666
|
+
url: preset.label === CUSTOM_PRESET ? customUrl : preset.url,
|
|
12667
|
+
...nextModel ? { model: nextModel } : {}
|
|
12668
|
+
});
|
|
12054
12669
|
};
|
|
12055
12670
|
const handleCustomUrlChange = (value) => {
|
|
12056
12671
|
setCustomUrl(value);
|
|
@@ -12102,14 +12717,30 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12102
12717
|
isOptionEqualToValue: (opt, val) => opt === val,
|
|
12103
12718
|
renderOption: (props, option) => {
|
|
12104
12719
|
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: [
|
|
12720
|
+
return /* @__PURE__ */ createElement2("li", { ...props, key: option }, /* @__PURE__ */ jsxs19(Box16, { sx: { display: "flex", alignItems: "center", gap: 1.25, width: "100%", minWidth: 0 }, children: [
|
|
12721
|
+
/* @__PURE__ */ jsx22(ProviderLogo, { label: option, url: preset?.url }),
|
|
12106
12722
|
/* @__PURE__ */ jsx22(Typography15, { sx: { fontSize: "0.85rem", color: "hsl(var(--popover-foreground))" }, children: option }),
|
|
12107
12723
|
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
12724
|
] }));
|
|
12109
12725
|
},
|
|
12110
|
-
renderInput: (params) =>
|
|
12726
|
+
renderInput: (params) => {
|
|
12727
|
+
const preset = ENDPOINT_PRESETS.find((p) => p.label === effectivePreset);
|
|
12728
|
+
return /* @__PURE__ */ jsx22(
|
|
12729
|
+
TextField6,
|
|
12730
|
+
{
|
|
12731
|
+
...params,
|
|
12732
|
+
placeholder: "Search a provider\u2026",
|
|
12733
|
+
slotProps: {
|
|
12734
|
+
input: {
|
|
12735
|
+
...params.InputProps,
|
|
12736
|
+
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
|
|
12737
|
+
}
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12740
|
+
);
|
|
12741
|
+
},
|
|
12111
12742
|
slotProps: {
|
|
12112
|
-
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
12743
|
+
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))", minWidth: 580 } },
|
|
12113
12744
|
popper: { sx: { zIndex: 9999 } }
|
|
12114
12745
|
}
|
|
12115
12746
|
}
|
|
@@ -12172,6 +12803,59 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12172
12803
|
hideDocsLink: true,
|
|
12173
12804
|
hideUrlFields: true,
|
|
12174
12805
|
borderless: true,
|
|
12806
|
+
compactAuthForm: true,
|
|
12807
|
+
extraFieldsSlot: (PROVIDER_MODELS[effectivePreset]?.length ?? 0) > 0 ? ({ credentials, setField }) => {
|
|
12808
|
+
const liveModel = credentials.model || "";
|
|
12809
|
+
const presetModels = PROVIDER_MODELS[effectivePreset] || [];
|
|
12810
|
+
const liveIsCustom = liveModel !== "" && !presetModels.includes(liveModel);
|
|
12811
|
+
const showCustom = customMode || liveIsCustom;
|
|
12812
|
+
const liveSelectValue = showCustom ? CUSTOM_MODEL : liveModel || null;
|
|
12813
|
+
return /* @__PURE__ */ jsxs19(Box16, { sx: { display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
12814
|
+
/* @__PURE__ */ jsx22(Typography15, { sx: { fontSize: "0.85rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: "Model" }),
|
|
12815
|
+
/* @__PURE__ */ jsx22(
|
|
12816
|
+
Autocomplete3,
|
|
12817
|
+
{
|
|
12818
|
+
size: "small",
|
|
12819
|
+
fullWidth: true,
|
|
12820
|
+
disableClearable: true,
|
|
12821
|
+
options: [...presetModels, CUSTOM_MODEL],
|
|
12822
|
+
value: liveSelectValue,
|
|
12823
|
+
onChange: (_e, val) => {
|
|
12824
|
+
if (!val) return;
|
|
12825
|
+
if (val === CUSTOM_MODEL) {
|
|
12826
|
+
setCustomMode(true);
|
|
12827
|
+
setField("model", customModel);
|
|
12828
|
+
} else {
|
|
12829
|
+
setCustomMode(false);
|
|
12830
|
+
setCustomModel("");
|
|
12831
|
+
setField("model", val);
|
|
12832
|
+
}
|
|
12833
|
+
},
|
|
12834
|
+
isOptionEqualToValue: (opt, val) => opt === val,
|
|
12835
|
+
slotProps: {
|
|
12836
|
+
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
12837
|
+
popper: { sx: { zIndex: 9999 } }
|
|
12838
|
+
},
|
|
12839
|
+
renderInput: (params) => /* @__PURE__ */ jsx22(TextField6, { ...params, placeholder: "Select a model\u2026" })
|
|
12840
|
+
}
|
|
12841
|
+
),
|
|
12842
|
+
showCustom && /* @__PURE__ */ jsx22(
|
|
12843
|
+
TextField6,
|
|
12844
|
+
{
|
|
12845
|
+
size: "small",
|
|
12846
|
+
fullWidth: true,
|
|
12847
|
+
placeholder: "Enter a custom model identifier",
|
|
12848
|
+
value: customModel || (liveIsCustom ? liveModel : ""),
|
|
12849
|
+
onChange: (e) => {
|
|
12850
|
+
setCustomModel(e.target.value);
|
|
12851
|
+
setField("model", e.target.value);
|
|
12852
|
+
},
|
|
12853
|
+
helperText: "Exact model name as expected by the provider's API",
|
|
12854
|
+
sx: { "& .MuiFormHelperText-root": { color: "hsl(var(--muted-foreground))" } }
|
|
12855
|
+
}
|
|
12856
|
+
)
|
|
12857
|
+
] });
|
|
12858
|
+
} : void 0,
|
|
12175
12859
|
globalUrl,
|
|
12176
12860
|
userdata,
|
|
12177
12861
|
isLoaded,
|
|
@@ -12249,9 +12933,16 @@ var AgentRunDrawer = ({
|
|
|
12249
12933
|
setActiveTab("localLLM");
|
|
12250
12934
|
}
|
|
12251
12935
|
};
|
|
12936
|
+
const onClose2 = () => {
|
|
12937
|
+
onClose();
|
|
12938
|
+
};
|
|
12252
12939
|
window.addEventListener("agent-drawer-open", onOpen);
|
|
12253
|
-
|
|
12254
|
-
|
|
12940
|
+
window.addEventListener("agent-drawer-close", onClose2);
|
|
12941
|
+
return () => {
|
|
12942
|
+
window.removeEventListener("agent-drawer-open", onOpen);
|
|
12943
|
+
window.removeEventListener("agent-drawer-close", onClose2);
|
|
12944
|
+
};
|
|
12945
|
+
}, [onClose]);
|
|
12255
12946
|
const effectiveLocalLLMSlot = localLLMSlot ?? /* @__PURE__ */ jsx23(
|
|
12256
12947
|
LocalLLMConfig_default,
|
|
12257
12948
|
{
|
|
@@ -12444,14 +13135,16 @@ import {
|
|
|
12444
13135
|
AlertCircle,
|
|
12445
13136
|
CheckCircle,
|
|
12446
13137
|
Clock,
|
|
13138
|
+
Database,
|
|
12447
13139
|
FileText,
|
|
12448
13140
|
GitBranch,
|
|
12449
13141
|
Globe,
|
|
13142
|
+
Hand,
|
|
12450
13143
|
Loader2,
|
|
12451
|
-
|
|
13144
|
+
Workflow as WorkflowIcon,
|
|
12452
13145
|
XCircle,
|
|
12453
13146
|
Zap,
|
|
12454
|
-
Search as
|
|
13147
|
+
Search as SearchIcon2
|
|
12455
13148
|
} from "lucide-react";
|
|
12456
13149
|
|
|
12457
13150
|
// agentActivity.ts
|
|
@@ -12750,7 +13443,7 @@ var STATUS_CONFIG = {
|
|
|
12750
13443
|
EXECUTING: { icon: /* @__PURE__ */ jsx24(Loader2, { size: 16 }), color: "hsl(var(--severity-medium, 38 92% 50%))", label: "Running" },
|
|
12751
13444
|
RUNNING: { icon: /* @__PURE__ */ jsx24(Loader2, { size: 16 }), color: "hsl(var(--severity-medium, 38 92% 50%))", label: "Running" },
|
|
12752
13445
|
WAITING: { icon: /* @__PURE__ */ jsx24(Clock, { size: 16 }), color: "hsl(var(--severity-info, 217 91% 60%))", label: "Waiting" },
|
|
12753
|
-
LIMIT_REACHED: { icon: /* @__PURE__ */ jsx24(AlertTriangle2, { size: 16 }), color: "hsl(var(--severity-
|
|
13446
|
+
LIMIT_REACHED: { icon: /* @__PURE__ */ jsx24(AlertTriangle2, { size: 16 }), color: "hsl(var(--severity-critical, 0 72% 55%))", label: "Limit reached" }
|
|
12754
13447
|
};
|
|
12755
13448
|
var getEffectiveStatus = (run) => {
|
|
12756
13449
|
const raw = (run.status || "").toUpperCase();
|
|
@@ -12763,21 +13456,126 @@ var getEffectiveStatus = (run) => {
|
|
|
12763
13456
|
}
|
|
12764
13457
|
return raw;
|
|
12765
13458
|
};
|
|
12766
|
-
var
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
if (arg
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
13459
|
+
var SOURCE_ICON_SIZE = 18;
|
|
13460
|
+
var looksLikeExecutionId = (s) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s.trim());
|
|
13461
|
+
var DATASTORE_KEY_RE = /\bKey:\s*(\S+)/i;
|
|
13462
|
+
var DATASTORE_CATEGORY_RE = /\bCategory:\s*(\S+)/i;
|
|
13463
|
+
var parseDatastoreTask = (arg) => {
|
|
13464
|
+
if (!arg) return null;
|
|
13465
|
+
const k = arg.match(DATASTORE_KEY_RE);
|
|
13466
|
+
const c = arg.match(DATASTORE_CATEGORY_RE);
|
|
13467
|
+
if (!k || !c) return null;
|
|
13468
|
+
const key = (k[1] || "").trim();
|
|
13469
|
+
const category = (c[1] || "").trim();
|
|
13470
|
+
if (!key || !category) return null;
|
|
13471
|
+
return { key, category };
|
|
13472
|
+
};
|
|
13473
|
+
var isAIAgentResult = (result) => String(result?.action?.app_name || "").trim().toLowerCase() === "ai agent";
|
|
13474
|
+
var getAIAgentResultPayload = (run) => {
|
|
13475
|
+
const results = Array.isArray(run.results) ? run.results : [];
|
|
13476
|
+
const agentResult = results.find(isAIAgentResult);
|
|
13477
|
+
if (!agentResult || typeof agentResult !== "object" || !("result" in agentResult)) return null;
|
|
13478
|
+
return tryParseJson(agentResult.result);
|
|
13479
|
+
};
|
|
13480
|
+
var getDirectAgentInput = (payload) => {
|
|
13481
|
+
if (!payload || typeof payload !== "object") return null;
|
|
13482
|
+
const obj = payload;
|
|
13483
|
+
if (typeof obj.original_input === "string" && obj.original_input.trim()) {
|
|
13484
|
+
return obj.original_input.trim();
|
|
13485
|
+
}
|
|
13486
|
+
if (typeof obj.input === "string" && obj.input.trim()) {
|
|
13487
|
+
return obj.input.trim();
|
|
13488
|
+
}
|
|
13489
|
+
return null;
|
|
13490
|
+
};
|
|
13491
|
+
var findDatastoreTaskInRun = (run) => {
|
|
13492
|
+
const agentInput = getDirectAgentInput(getAIAgentResultPayload(run));
|
|
13493
|
+
const agentHit = parseDatastoreTask(agentInput || void 0);
|
|
13494
|
+
if (agentHit) return agentHit;
|
|
13495
|
+
const anyRun = run;
|
|
13496
|
+
const candidates = [];
|
|
13497
|
+
if (typeof anyRun.original_input === "string") candidates.push(anyRun.original_input);
|
|
13498
|
+
if (typeof anyRun.input === "string") candidates.push(anyRun.input);
|
|
13499
|
+
if (run.execution_argument) candidates.push(run.execution_argument);
|
|
13500
|
+
if (run.result) candidates.push(run.result);
|
|
13501
|
+
if (Array.isArray(anyRun.results)) {
|
|
13502
|
+
try {
|
|
13503
|
+
candidates.push(JSON.stringify(anyRun.results));
|
|
13504
|
+
} catch {
|
|
13505
|
+
}
|
|
13506
|
+
}
|
|
13507
|
+
for (const c of candidates) {
|
|
13508
|
+
const hit = parseDatastoreTask(c);
|
|
13509
|
+
if (hit) return hit;
|
|
13510
|
+
}
|
|
13511
|
+
return null;
|
|
13512
|
+
};
|
|
13513
|
+
var classifyRunSource = (run) => {
|
|
13514
|
+
const raw = (run.execution_source || "").trim();
|
|
13515
|
+
const src = raw.toLowerCase();
|
|
13516
|
+
const ds = findDatastoreTaskInRun(run);
|
|
13517
|
+
if (ds || src.includes("datastore") || src.includes("enrichment") || src.includes("automation")) {
|
|
13518
|
+
return {
|
|
13519
|
+
kind: "datastore",
|
|
13520
|
+
label: "Datastore automation",
|
|
13521
|
+
reason: ds ? `Started by datastore automation (category "${ds.category}", key "${ds.key}"). Click to open in Datastore.` : "Started by a datastore automation (e.g. enrichment trigger).",
|
|
13522
|
+
icon: /* @__PURE__ */ jsx24(Database, { size: SOURCE_ICON_SIZE }),
|
|
13523
|
+
datastoreKey: ds?.key,
|
|
13524
|
+
datastoreCategory: ds?.category
|
|
13525
|
+
};
|
|
13526
|
+
}
|
|
13527
|
+
if (src.includes("schedule") || src.includes("cron")) {
|
|
13528
|
+
return {
|
|
13529
|
+
kind: "schedule",
|
|
13530
|
+
label: "Schedule",
|
|
13531
|
+
reason: "Started by a scheduled trigger (cron).",
|
|
13532
|
+
icon: /* @__PURE__ */ jsx24(Clock, { size: SOURCE_ICON_SIZE })
|
|
13533
|
+
};
|
|
13534
|
+
}
|
|
13535
|
+
if (src.includes("webhook") || src.includes("http")) {
|
|
13536
|
+
return {
|
|
13537
|
+
kind: "webhook",
|
|
13538
|
+
label: "Webhook",
|
|
13539
|
+
reason: "Started by an incoming webhook / HTTP trigger.",
|
|
13540
|
+
icon: /* @__PURE__ */ jsx24(Globe, { size: SOURCE_ICON_SIZE })
|
|
13541
|
+
};
|
|
13542
|
+
}
|
|
13543
|
+
if (src.includes("form")) {
|
|
13544
|
+
return {
|
|
13545
|
+
kind: "form",
|
|
13546
|
+
label: "Form",
|
|
13547
|
+
reason: "Started by a form submission.",
|
|
13548
|
+
icon: /* @__PURE__ */ jsx24(FileText, { size: SOURCE_ICON_SIZE })
|
|
13549
|
+
};
|
|
13550
|
+
}
|
|
13551
|
+
if (raw && looksLikeExecutionId(raw)) {
|
|
13552
|
+
return {
|
|
13553
|
+
kind: "workflow",
|
|
13554
|
+
label: "Workflow",
|
|
13555
|
+
reason: "Started by another workflow as a subflow.",
|
|
13556
|
+
icon: /* @__PURE__ */ jsx24(WorkflowIcon, { size: SOURCE_ICON_SIZE })
|
|
13557
|
+
};
|
|
13558
|
+
}
|
|
13559
|
+
if (src === "" || src === "manual" || src === "default" || src === "demo") {
|
|
13560
|
+
return {
|
|
13561
|
+
kind: "manual",
|
|
13562
|
+
label: "Manual",
|
|
13563
|
+
reason: "Started manually from the Agents UI.",
|
|
13564
|
+
icon: /* @__PURE__ */ jsx24(Hand, { size: SOURCE_ICON_SIZE })
|
|
13565
|
+
};
|
|
13566
|
+
}
|
|
13567
|
+
return {
|
|
13568
|
+
kind: "unknown",
|
|
13569
|
+
label: raw || "Unknown",
|
|
13570
|
+
reason: raw ? `Started by "${raw}".` : "Trigger source unknown.",
|
|
13571
|
+
icon: /* @__PURE__ */ jsx24(Zap, { size: SOURCE_ICON_SIZE })
|
|
13572
|
+
};
|
|
12775
13573
|
};
|
|
12776
13574
|
var getRunIconColor = (run) => {
|
|
12777
13575
|
const status = getEffectiveStatus(run);
|
|
12778
13576
|
if (status === "FINISHED" || status === "SUCCESS") return "hsl(var(--severity-low, 142 71% 45%))";
|
|
12779
13577
|
if (status === "FAILED" || status === "ABORTED") return "hsl(var(--severity-critical, 0 72% 55%))";
|
|
12780
|
-
if (status === "LIMIT_REACHED") return "hsl(var(--severity-
|
|
13578
|
+
if (status === "LIMIT_REACHED") return "hsl(var(--severity-critical, 0 72% 55%))";
|
|
12781
13579
|
if (status === "EXECUTING" || status === "RUNNING") return "hsl(var(--severity-medium, 38 92% 50%))";
|
|
12782
13580
|
return "hsl(var(--primary, 24 100% 50%))";
|
|
12783
13581
|
};
|
|
@@ -12875,9 +13673,12 @@ var tryParseJson = (s) => {
|
|
|
12875
13673
|
}
|
|
12876
13674
|
};
|
|
12877
13675
|
var getRunPrompt = (run) => {
|
|
12878
|
-
const
|
|
13676
|
+
const anyRun = run;
|
|
13677
|
+
const agentInput = getDirectAgentInput(getAIAgentResultPayload(run));
|
|
13678
|
+
if (agentInput) return agentInput;
|
|
13679
|
+
const results = Array.isArray(anyRun.results) ? anyRun.results : null;
|
|
12879
13680
|
if (results) {
|
|
12880
|
-
const agentResult = results.find(
|
|
13681
|
+
const agentResult = results.find(isAIAgentResult);
|
|
12881
13682
|
if (agentResult?.result) {
|
|
12882
13683
|
const hit = deepFindPrompt(tryParseJson(agentResult.result));
|
|
12883
13684
|
if (hit) return hit;
|
|
@@ -12888,6 +13689,12 @@ var getRunPrompt = (run) => {
|
|
|
12888
13689
|
if (hit) return hit;
|
|
12889
13690
|
}
|
|
12890
13691
|
}
|
|
13692
|
+
if (typeof anyRun.original_input === "string" && anyRun.original_input.trim()) {
|
|
13693
|
+
return anyRun.original_input.trim();
|
|
13694
|
+
}
|
|
13695
|
+
if (typeof anyRun.input === "string" && anyRun.input.trim()) {
|
|
13696
|
+
return anyRun.input.trim();
|
|
13697
|
+
}
|
|
12891
13698
|
if (run.result) {
|
|
12892
13699
|
const hit = deepFindPrompt(tryParseJson(run.result));
|
|
12893
13700
|
if (hit) return hit;
|
|
@@ -12928,7 +13735,9 @@ var getRunSubtitle = (run) => {
|
|
|
12928
13735
|
if (run.result.length < 120) return run.result;
|
|
12929
13736
|
}
|
|
12930
13737
|
}
|
|
12931
|
-
|
|
13738
|
+
const status = getEffectiveStatus(run);
|
|
13739
|
+
const isRunning = status === "EXECUTING" || status === "RUNNING" || status === "WAITING";
|
|
13740
|
+
return run.execution_source || (isRunning ? "Agent still running\u2026" : "Agent execution");
|
|
12932
13741
|
};
|
|
12933
13742
|
var normalizeResultStatus = (s) => {
|
|
12934
13743
|
const v = (s || "").toUpperCase();
|
|
@@ -13030,41 +13839,60 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13030
13839
|
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
13031
13840
|
],
|
|
13032
13841
|
children: [
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
{
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13842
|
+
(() => {
|
|
13843
|
+
const sourceInfo = classifyRunSource(run);
|
|
13844
|
+
const dsLink = sourceInfo.kind === "datastore" && sourceInfo.datastoreKey && sourceInfo.datastoreCategory ? `https://shuffler.io/admin?tab=datastore&category=${encodeURIComponent(sourceInfo.datastoreCategory)}&key=${encodeURIComponent(sourceInfo.datastoreKey)}` : null;
|
|
13845
|
+
return /* @__PURE__ */ jsx24(
|
|
13846
|
+
Tooltip12,
|
|
13847
|
+
{
|
|
13848
|
+
title: /* @__PURE__ */ jsxs21(Box18, { sx: { lineHeight: 1.4 }, children: [
|
|
13849
|
+
/* @__PURE__ */ jsx24(Box18, { sx: { fontWeight: 600 }, children: sourceInfo.label }),
|
|
13850
|
+
/* @__PURE__ */ jsx24(Box18, { sx: { opacity: 0.85 }, children: sourceInfo.reason })
|
|
13851
|
+
] }),
|
|
13852
|
+
placement: "top",
|
|
13853
|
+
arrow: true,
|
|
13854
|
+
children: /* @__PURE__ */ jsx24(
|
|
13855
|
+
Box18,
|
|
13856
|
+
{
|
|
13857
|
+
onClick: dsLink ? (e) => {
|
|
13858
|
+
e.stopPropagation();
|
|
13859
|
+
window.open(dsLink, "_blank", "noopener,noreferrer");
|
|
13860
|
+
} : void 0,
|
|
13861
|
+
sx: {
|
|
13862
|
+
width: 40,
|
|
13863
|
+
height: 40,
|
|
13864
|
+
borderRadius: "50%",
|
|
13865
|
+
display: "flex",
|
|
13866
|
+
alignItems: "center",
|
|
13867
|
+
justifyContent: "center",
|
|
13868
|
+
bgcolor: `${iconColor}15`,
|
|
13869
|
+
color: iconColor,
|
|
13870
|
+
flexShrink: 0,
|
|
13871
|
+
cursor: dsLink ? "pointer" : "inherit",
|
|
13872
|
+
transition: "background 0.15s ease",
|
|
13873
|
+
"&:hover": dsLink ? { bgcolor: `${iconColor}30` } : void 0
|
|
13874
|
+
},
|
|
13875
|
+
children: sourceInfo.icon
|
|
13876
|
+
}
|
|
13877
|
+
)
|
|
13878
|
+
}
|
|
13879
|
+
);
|
|
13880
|
+
})(),
|
|
13050
13881
|
/* @__PURE__ */ jsxs21(Box18, { sx: { flex: 1, minWidth: 0 }, children: [
|
|
13051
|
-
/* @__PURE__ */
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
{
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
),
|
|
13066
|
-
/* @__PURE__ */ jsx24(Box18, { sx: { display: "flex", alignItems: "center", color: cfg.color, flexShrink: 0 }, children: cfg.icon })
|
|
13067
|
-
] }),
|
|
13882
|
+
/* @__PURE__ */ jsx24(Box18, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 0.25 }, children: /* @__PURE__ */ jsx24(
|
|
13883
|
+
Typography17,
|
|
13884
|
+
{
|
|
13885
|
+
sx: {
|
|
13886
|
+
fontSize: "0.9rem",
|
|
13887
|
+
fontWeight: 500,
|
|
13888
|
+
color: "hsl(var(--foreground))",
|
|
13889
|
+
overflow: "hidden",
|
|
13890
|
+
textOverflow: "ellipsis",
|
|
13891
|
+
whiteSpace: "nowrap"
|
|
13892
|
+
},
|
|
13893
|
+
children: getRunTitle(run)
|
|
13894
|
+
}
|
|
13895
|
+
) }),
|
|
13068
13896
|
/* @__PURE__ */ jsx24(
|
|
13069
13897
|
Typography17,
|
|
13070
13898
|
{
|
|
@@ -13097,17 +13925,20 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13097
13925
|
] })
|
|
13098
13926
|
] })
|
|
13099
13927
|
] }),
|
|
13100
|
-
|
|
13928
|
+
/* @__PURE__ */ jsx24(
|
|
13101
13929
|
Box18,
|
|
13102
13930
|
{
|
|
13103
13931
|
onClick: (e) => e.stopPropagation(),
|
|
13104
13932
|
sx: {
|
|
13105
13933
|
display: { xs: "none", sm: "flex" },
|
|
13106
13934
|
alignItems: "center",
|
|
13935
|
+
justifyContent: "flex-end",
|
|
13107
13936
|
flexShrink: 0,
|
|
13108
|
-
ml: 1
|
|
13937
|
+
ml: 1,
|
|
13938
|
+
width: 140,
|
|
13939
|
+
minHeight: 28
|
|
13109
13940
|
},
|
|
13110
|
-
children: /* @__PURE__ */ jsx24(
|
|
13941
|
+
children: tools.length > 0 ? /* @__PURE__ */ jsx24(
|
|
13111
13942
|
AvatarGroup2,
|
|
13112
13943
|
{
|
|
13113
13944
|
max: 5,
|
|
@@ -13156,7 +13987,7 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13156
13987
|
) }, t.name);
|
|
13157
13988
|
})
|
|
13158
13989
|
}
|
|
13159
|
-
)
|
|
13990
|
+
) : null
|
|
13160
13991
|
}
|
|
13161
13992
|
)
|
|
13162
13993
|
]
|
|
@@ -13499,7 +14330,7 @@ var AgentActivityList = ({
|
|
|
13499
14330
|
onChange: (e) => updateSearchQuery(e.target.value),
|
|
13500
14331
|
slotProps: {
|
|
13501
14332
|
input: {
|
|
13502
|
-
startAdornment: /* @__PURE__ */ jsx24(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx24(
|
|
14333
|
+
startAdornment: /* @__PURE__ */ jsx24(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx24(SearchIcon2, { size: 18, color: "hsl(var(--muted-foreground))" }) })
|
|
13503
14334
|
}
|
|
13504
14335
|
},
|
|
13505
14336
|
sx: {
|
|
@@ -13979,6 +14810,15 @@ var AgentsView = ({
|
|
|
13979
14810
|
open: false,
|
|
13980
14811
|
tab: "localLLM"
|
|
13981
14812
|
});
|
|
14813
|
+
useEffect15(() => {
|
|
14814
|
+
if (typeof window === "undefined") return;
|
|
14815
|
+
const handler = (e) => {
|
|
14816
|
+
const detail = e.detail;
|
|
14817
|
+
setBuiltInDrawer({ open: true, tab: detail?.tab ?? "localLLM" });
|
|
14818
|
+
};
|
|
14819
|
+
window.addEventListener("agent-drawer-open", handler);
|
|
14820
|
+
return () => window.removeEventListener("agent-drawer-open", handler);
|
|
14821
|
+
}, []);
|
|
13982
14822
|
const effectiveSchedule = useCallback10(
|
|
13983
14823
|
async (info) => {
|
|
13984
14824
|
if (onSchedule) return onSchedule(info);
|
|
@@ -14370,7 +15210,9 @@ export {
|
|
|
14370
15210
|
deleteDatastoreItem,
|
|
14371
15211
|
deleteDatastoreItems,
|
|
14372
15212
|
diagnoseOutputWarning,
|
|
15213
|
+
extractActionAppNames,
|
|
14373
15214
|
extractValidatedIngestionApps,
|
|
15215
|
+
extractWorkflowActionAppNames,
|
|
14374
15216
|
extractWorkflowAppNames,
|
|
14375
15217
|
fetchApps,
|
|
14376
15218
|
fetchAppsViaApiConfig,
|