@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.js
CHANGED
|
@@ -422,7 +422,9 @@ __export(index_exports, {
|
|
|
422
422
|
deleteDatastoreItem: () => deleteDatastoreItem,
|
|
423
423
|
deleteDatastoreItems: () => deleteDatastoreItems,
|
|
424
424
|
diagnoseOutputWarning: () => diagnoseOutputWarning,
|
|
425
|
+
extractActionAppNames: () => extractActionAppNames,
|
|
425
426
|
extractValidatedIngestionApps: () => extractValidatedIngestionApps,
|
|
427
|
+
extractWorkflowActionAppNames: () => extractWorkflowActionAppNames,
|
|
426
428
|
extractWorkflowAppNames: () => extractWorkflowAppNames,
|
|
427
429
|
fetchApps: () => fetchApps,
|
|
428
430
|
fetchAppsViaApiConfig: () => fetchAppsViaApiConfig,
|
|
@@ -473,13 +475,13 @@ __export(index_exports, {
|
|
|
473
475
|
useSyncHostBaseUrl: () => useSyncHostBaseUrl
|
|
474
476
|
});
|
|
475
477
|
module.exports = __toCommonJS(index_exports);
|
|
476
|
-
var import_shuffle_mcp3 = require("./shuffle-mcp-
|
|
478
|
+
var import_shuffle_mcp3 = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
477
479
|
var import_react22 = __toESM(require("react"));
|
|
478
480
|
|
|
479
481
|
// ShuffleMcpThemeProvider.tsx
|
|
480
482
|
var import_react = __toESM(require("react"));
|
|
481
483
|
var import_material = require("@mui/material");
|
|
482
|
-
var import_shuffle_mcp = require("./shuffle-mcp-
|
|
484
|
+
var import_shuffle_mcp = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
483
485
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
484
486
|
var readHtmlDarkClass = () => {
|
|
485
487
|
if (typeof document === "undefined") return false;
|
|
@@ -1319,6 +1321,65 @@ var isIngestionApp = (appName) => {
|
|
|
1319
1321
|
return isEmailApp(appName) || CASES_PATTERNS.some((p) => name.includes(p)) || EDR_PATTERNS.some((p) => name.includes(p)) || SIEM_PATTERNS.some((p) => name.includes(p));
|
|
1320
1322
|
};
|
|
1321
1323
|
var normalizeAppName = (name) => name.toLowerCase().trim().replace(/[\s_\-]+/g, "_");
|
|
1324
|
+
var IGNORED_WORKFLOW_APP_NAMES = /* @__PURE__ */ new Set([
|
|
1325
|
+
"shuffle_tools",
|
|
1326
|
+
"singul",
|
|
1327
|
+
"integration",
|
|
1328
|
+
"ai_agent",
|
|
1329
|
+
"shuffle_agent",
|
|
1330
|
+
"shuffle_ai"
|
|
1331
|
+
]);
|
|
1332
|
+
var isIgnoredWorkflowAppName = (name) => IGNORED_WORKFLOW_APP_NAMES.has(normalizeAppName(name));
|
|
1333
|
+
var looksLikeOpaqueId = (raw) => {
|
|
1334
|
+
const trimmed = raw.trim();
|
|
1335
|
+
if (/^[a-f0-9]{16,}$/i.test(trimmed)) return true;
|
|
1336
|
+
if (/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(trimmed)) return true;
|
|
1337
|
+
return false;
|
|
1338
|
+
};
|
|
1339
|
+
var addWorkflowAppName = (names, seen, raw) => {
|
|
1340
|
+
if (typeof raw !== "string" || !raw.trim()) return;
|
|
1341
|
+
const parts = raw.includes(",") ? raw.split(",") : [raw];
|
|
1342
|
+
for (const part of parts) {
|
|
1343
|
+
const trimmed = part.trim();
|
|
1344
|
+
if (!trimmed) continue;
|
|
1345
|
+
const key = normalizeAppName(trimmed);
|
|
1346
|
+
if (!key || isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed) || seen.has(key)) continue;
|
|
1347
|
+
seen.add(key);
|
|
1348
|
+
names.push(trimmed);
|
|
1349
|
+
}
|
|
1350
|
+
};
|
|
1351
|
+
var collectParameterAppNames = (input, names, seen, depth = 0) => {
|
|
1352
|
+
if (!input || depth > 4) return;
|
|
1353
|
+
if (Array.isArray(input)) {
|
|
1354
|
+
input.forEach((item) => collectParameterAppNames(item, names, seen, depth + 1));
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
if (typeof input !== "object") return;
|
|
1358
|
+
const obj = input;
|
|
1359
|
+
if (String(obj.name || "").toLowerCase() === "app_name") addWorkflowAppName(names, seen, obj.value);
|
|
1360
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1361
|
+
const lower = key.toLowerCase();
|
|
1362
|
+
if (lower === "app_name") addWorkflowAppName(names, seen, value);
|
|
1363
|
+
else if (lower === "parameters" || lower === "fields" || lower === "value") collectParameterAppNames(value, names, seen, depth + 1);
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
function extractActionAppNames(action) {
|
|
1367
|
+
const names = [];
|
|
1368
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1369
|
+
collectParameterAppNames(action?.parameters, names, seen);
|
|
1370
|
+
addWorkflowAppName(names, seen, action?.app_name);
|
|
1371
|
+
addWorkflowAppName(names, seen, action?.app_id);
|
|
1372
|
+
return names;
|
|
1373
|
+
}
|
|
1374
|
+
function extractWorkflowActionAppNames(workflow) {
|
|
1375
|
+
const names = [];
|
|
1376
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1377
|
+
if (!workflow?.actions || !Array.isArray(workflow.actions)) return names;
|
|
1378
|
+
for (const action of workflow.actions) {
|
|
1379
|
+
for (const name of extractActionAppNames(action)) addWorkflowAppName(names, seen, name);
|
|
1380
|
+
}
|
|
1381
|
+
return names;
|
|
1382
|
+
}
|
|
1322
1383
|
var getIngestionCategory = (appName, appCategories) => {
|
|
1323
1384
|
const name = appName.toLowerCase();
|
|
1324
1385
|
const categories = (appCategories || []).map((c) => c.toLowerCase());
|
|
@@ -1332,20 +1393,14 @@ var INGEST_TICKETS_WORKFLOW_NAME = "Ingest Tickets";
|
|
|
1332
1393
|
var FORWARD_TICKETS_WORKFLOW_NAME = "Forward Tickets";
|
|
1333
1394
|
function extractWorkflowAppNames(workflow) {
|
|
1334
1395
|
const names = /* @__PURE__ */ new Set();
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
if (action.parameters) {
|
|
1344
|
-
for (const param of action.parameters) {
|
|
1345
|
-
if (param.name === "app_name" && param.value) {
|
|
1346
|
-
names.add(normalizeAppName(param.value));
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1396
|
+
for (const raw of extractWorkflowActionAppNames(workflow)) {
|
|
1397
|
+
const parts = typeof raw === "string" && raw.includes(",") ? raw.split(",") : [raw];
|
|
1398
|
+
for (const part of parts) {
|
|
1399
|
+
const trimmed = (part || "").trim();
|
|
1400
|
+
if (!trimmed) continue;
|
|
1401
|
+
if (isIgnoredWorkflowAppName(trimmed) || looksLikeOpaqueId(trimmed)) continue;
|
|
1402
|
+
const key = normalizeAppName(trimmed);
|
|
1403
|
+
if (key) names.add(key);
|
|
1349
1404
|
}
|
|
1350
1405
|
}
|
|
1351
1406
|
return names;
|
|
@@ -2060,6 +2115,7 @@ function AppTitleHeader({
|
|
|
2060
2115
|
isActivated = null,
|
|
2061
2116
|
activateLoading = false,
|
|
2062
2117
|
onActivateToggle,
|
|
2118
|
+
highlightActivate = false,
|
|
2063
2119
|
onAdd
|
|
2064
2120
|
}) {
|
|
2065
2121
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_framer_motion.motion.div, { initial: { opacity: 0, y: 12 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.3 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -2163,7 +2219,16 @@ function AppTitleHeader({
|
|
|
2163
2219
|
py: 0.5,
|
|
2164
2220
|
minHeight: 0,
|
|
2165
2221
|
flexShrink: 0,
|
|
2166
|
-
...isActivated ? { color: "hsl(var(--muted-foreground))", borderColor: "hsl(var(--border))", "&:hover": { borderColor: "hsl(var(--destructive))", color: "hsl(var(--destructive))", bgcolor: "hsla(var(--destructive) / 0.08)" } } : { bgcolor: "hsl(var(--primary))", "&:hover": { bgcolor: "hsl(var(--primary) / 0.85)" } }
|
|
2222
|
+
...isActivated ? { color: "hsl(var(--muted-foreground))", borderColor: "hsl(var(--border))", "&:hover": { borderColor: "hsl(var(--destructive))", color: "hsl(var(--destructive))", bgcolor: "hsla(var(--destructive) / 0.08)" } } : { bgcolor: "hsl(var(--primary))", "&:hover": { bgcolor: "hsl(var(--primary) / 0.85)" } },
|
|
2223
|
+
...highlightActivate ? {
|
|
2224
|
+
boxShadow: "0 0 0 0 hsla(var(--primary) / 0.6)",
|
|
2225
|
+
animation: "appTitleActivatePulse 1.1s ease-out infinite",
|
|
2226
|
+
"@keyframes appTitleActivatePulse": {
|
|
2227
|
+
"0%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0.55)" },
|
|
2228
|
+
"70%": { boxShadow: "0 0 0 10px hsla(var(--primary) / 0)" },
|
|
2229
|
+
"100%": { boxShadow: "0 0 0 0 hsla(var(--primary) / 0)" }
|
|
2230
|
+
}
|
|
2231
|
+
} : {}
|
|
2167
2232
|
},
|
|
2168
2233
|
children: activateLoading ? "\u2026" : isActivated ? "Deactivate" : "Activate"
|
|
2169
2234
|
}
|
|
@@ -2399,6 +2464,8 @@ var AppAuthCard = ({
|
|
|
2399
2464
|
hideDocsLink,
|
|
2400
2465
|
hideUrlFields,
|
|
2401
2466
|
borderless,
|
|
2467
|
+
compactAuthForm,
|
|
2468
|
+
extraFieldsSlot,
|
|
2402
2469
|
globalUrl,
|
|
2403
2470
|
userdata,
|
|
2404
2471
|
isLoaded,
|
|
@@ -2465,10 +2532,6 @@ var AppAuthCard = ({
|
|
|
2465
2532
|
if (!alreadyValid && newestId !== autoTestFiredRef.current) {
|
|
2466
2533
|
autoTestFiredRef.current = newestId;
|
|
2467
2534
|
setTimeout(() => {
|
|
2468
|
-
toast({
|
|
2469
|
-
title: "Auto-testing new authentication",
|
|
2470
|
-
description: `Verifying connection for ${app.name.replace(/_/g, " ")}...`
|
|
2471
|
-
});
|
|
2472
2535
|
setTestingAuthId(newestId);
|
|
2473
2536
|
onTestConnection(app.objectID, newestId);
|
|
2474
2537
|
}, 500);
|
|
@@ -2530,11 +2593,17 @@ var AppAuthCard = ({
|
|
|
2530
2593
|
executionId: authState.executionId,
|
|
2531
2594
|
errorCode: authState.errorCode
|
|
2532
2595
|
});
|
|
2596
|
+
if (autoTestFiredRef.current === testingAuthId) {
|
|
2597
|
+
setSelectedAuthId(ADD_NEW_AUTH);
|
|
2598
|
+
setUserHasSelected(true);
|
|
2599
|
+
setPendingFailedAuthId(testingAuthId);
|
|
2600
|
+
autoTestFiredRef.current = null;
|
|
2601
|
+
}
|
|
2533
2602
|
setTestingAuthId(null);
|
|
2534
2603
|
}
|
|
2535
2604
|
}, [authState.status, authState.errorMessage, authState.successMessage, authState.warningMessage, testingAuthId, apiAuthEntries, wasPreValidatedPerAuth]);
|
|
2536
2605
|
const isCredentialError = localTestMessages.errorCode === 401 || localTestMessages.errorCode === 403;
|
|
2537
|
-
const showAddNewForm = selectedAuthId === ADD_NEW_AUTH;
|
|
2606
|
+
const showAddNewForm = compactAuthForm ? true : selectedAuthId === ADD_NEW_AUTH;
|
|
2538
2607
|
const isConfigured = selectedAuth?.active === true;
|
|
2539
2608
|
const isTested = selectedAuth?.validation?.valid === true;
|
|
2540
2609
|
const getLastValidTimestamp = () => {
|
|
@@ -2556,6 +2625,8 @@ var AppAuthCard = ({
|
|
|
2556
2625
|
});
|
|
2557
2626
|
};
|
|
2558
2627
|
const [localCredentials, setLocalCredentials] = (0, import_react7.useState)(authState.credentials || {});
|
|
2628
|
+
const [revealedFields, setRevealedFields] = (0, import_react7.useState)({});
|
|
2629
|
+
const [pendingFailedAuthId, setPendingFailedAuthId] = (0, import_react7.useState)(null);
|
|
2559
2630
|
const [fieldErrors, setFieldErrors] = (0, import_react7.useState)({});
|
|
2560
2631
|
const [loading, setLoading] = (0, import_react7.useState)(false);
|
|
2561
2632
|
const [saving, setSaving] = (0, import_react7.useState)(false);
|
|
@@ -2631,7 +2702,8 @@ var AppAuthCard = ({
|
|
|
2631
2702
|
for (const [k, v] of Object.entries(incoming)) {
|
|
2632
2703
|
const lk = k.toLowerCase();
|
|
2633
2704
|
const isUrlish = lk.includes("url") || lk.includes("endpoint") || lk.includes("host");
|
|
2634
|
-
|
|
2705
|
+
const isModel = lk === "model";
|
|
2706
|
+
if ((isUrlish || isModel) && typeof v === "string" && v !== prev[k]) {
|
|
2635
2707
|
next[k] = v;
|
|
2636
2708
|
changed = true;
|
|
2637
2709
|
}
|
|
@@ -2827,7 +2899,7 @@ var AppAuthCard = ({
|
|
|
2827
2899
|
sx: {
|
|
2828
2900
|
"& .MuiOutlinedInput-root": {
|
|
2829
2901
|
backgroundColor: "hsl(var(--background))",
|
|
2830
|
-
borderRadius:
|
|
2902
|
+
borderRadius: 1,
|
|
2831
2903
|
"& fieldset": { borderColor: "hsl(var(--border))" },
|
|
2832
2904
|
"&:hover fieldset": { borderColor: "hsl(var(--border) / 0.8)" },
|
|
2833
2905
|
"&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
|
|
@@ -2850,7 +2922,7 @@ var AppAuthCard = ({
|
|
|
2850
2922
|
sx: {
|
|
2851
2923
|
"& .MuiOutlinedInput-root": {
|
|
2852
2924
|
backgroundColor: "hsl(var(--background))",
|
|
2853
|
-
borderRadius:
|
|
2925
|
+
borderRadius: 1,
|
|
2854
2926
|
"& fieldset": { borderColor: "hsl(var(--border))" },
|
|
2855
2927
|
"&:hover fieldset": { borderColor: "hsl(var(--border) / 0.8)" },
|
|
2856
2928
|
"&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
|
|
@@ -2875,7 +2947,7 @@ var AppAuthCard = ({
|
|
|
2875
2947
|
displayEmpty: true,
|
|
2876
2948
|
sx: {
|
|
2877
2949
|
backgroundColor: "action.hover",
|
|
2878
|
-
borderRadius:
|
|
2950
|
+
borderRadius: 1,
|
|
2879
2951
|
color: "text.primary",
|
|
2880
2952
|
"& .MuiOutlinedInput-notchedOutline": { borderColor: "divider" },
|
|
2881
2953
|
"&:hover .MuiOutlinedInput-notchedOutline": { borderColor: "text.disabled" },
|
|
@@ -2920,6 +2992,7 @@ var AppAuthCard = ({
|
|
|
2920
2992
|
const fieldKey = param.id || param.name || `param_${index}`;
|
|
2921
2993
|
const lowerName = (param.name || "").toLowerCase();
|
|
2922
2994
|
const isSecretField = lowerName.includes("password") || lowerName.includes("secret") || lowerName.includes("key") || lowerName.includes("token");
|
|
2995
|
+
const isRevealed = !!revealedFields[fieldKey];
|
|
2923
2996
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2924
2997
|
import_material4.TextField,
|
|
2925
2998
|
{
|
|
@@ -2950,13 +3023,25 @@ var AppAuthCard = ({
|
|
|
2950
3023
|
onFocus: (e) => {
|
|
2951
3024
|
e.target.removeAttribute("readonly");
|
|
2952
3025
|
}
|
|
2953
|
-
}
|
|
3026
|
+
},
|
|
3027
|
+
input: isSecretField ? {
|
|
3028
|
+
endAdornment: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3029
|
+
import_material4.IconButton,
|
|
3030
|
+
{
|
|
3031
|
+
size: "small",
|
|
3032
|
+
onClick: () => setRevealedFields((prev) => ({ ...prev, [fieldKey]: !prev[fieldKey] })),
|
|
3033
|
+
"aria-label": isRevealed ? `Hide ${param.name}` : `Show ${param.name}`,
|
|
3034
|
+
sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--foreground))" } },
|
|
3035
|
+
children: isRevealed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.EyeOff, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.Eye, { size: 16 })
|
|
3036
|
+
}
|
|
3037
|
+
)
|
|
3038
|
+
} : void 0
|
|
2954
3039
|
},
|
|
2955
3040
|
name: `auth-${fieldKey}-${app.objectID}-${Math.random().toString(36).slice(2, 8)}`,
|
|
2956
3041
|
sx: {
|
|
2957
3042
|
"& .MuiOutlinedInput-root": {
|
|
2958
3043
|
backgroundColor: isSecretField ? "hsl(var(--primary) / 0.06)" : "hsl(var(--muted))",
|
|
2959
|
-
borderRadius:
|
|
3044
|
+
borderRadius: 1,
|
|
2960
3045
|
"& fieldset": {
|
|
2961
3046
|
borderColor: fieldErrors[fieldKey] ? "hsl(var(--destructive))" : isSecretField ? "hsl(var(--primary) / 0.5)" : "hsl(var(--border))",
|
|
2962
3047
|
borderWidth: isSecretField ? 2 : 1
|
|
@@ -2968,7 +3053,7 @@ var AppAuthCard = ({
|
|
|
2968
3053
|
},
|
|
2969
3054
|
"& .MuiInputBase-input": {
|
|
2970
3055
|
color: "hsl(var(--foreground))",
|
|
2971
|
-
...isSecretField && {
|
|
3056
|
+
...isSecretField && !isRevealed && {
|
|
2972
3057
|
WebkitTextSecurity: "disc",
|
|
2973
3058
|
textSecurity: "disc",
|
|
2974
3059
|
fontFamily: "text-security-disc, monospace"
|
|
@@ -3019,7 +3104,6 @@ var AppAuthCard = ({
|
|
|
3019
3104
|
setSaveSuccess(success);
|
|
3020
3105
|
if (success) {
|
|
3021
3106
|
setUserHasSelected(false);
|
|
3022
|
-
setLocalCredentials({});
|
|
3023
3107
|
setFieldErrors({});
|
|
3024
3108
|
}
|
|
3025
3109
|
};
|
|
@@ -3227,7 +3311,7 @@ var AppAuthCard = ({
|
|
|
3227
3311
|
borderTop: borderless ? "none" : "1px solid hsl(var(--border))"
|
|
3228
3312
|
},
|
|
3229
3313
|
children: [
|
|
3230
|
-
apiAuthEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material4.Box, { sx: { mb: 3 }, children: [
|
|
3314
|
+
!compactAuthForm && apiAuthEntries.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material4.Box, { sx: { mb: 3 }, children: [
|
|
3231
3315
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.Typography, { variant: "body2", sx: { color: "hsl(var(--muted-foreground))", mb: 1 }, children: "Select authentication" }),
|
|
3232
3316
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.FormControl, { fullWidth: true, size: "small", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3233
3317
|
import_material4.Select,
|
|
@@ -3766,7 +3850,7 @@ var AppAuthCard = ({
|
|
|
3766
3850
|
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.Typography, { 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." })
|
|
3767
3851
|
}
|
|
3768
3852
|
),
|
|
3769
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.Typography, { variant: "subtitle2", sx: { color: "hsl(var(--foreground))", fontWeight: 600, mb: 2 }, children: apiAuthEntries.length === 0 ?
|
|
3853
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.Typography, { variant: "subtitle2", sx: { color: "hsl(var(--foreground))", fontWeight: 600, mb: 2 }, children: apiAuthEntries.length === 0 ? `Configure ${app.name.replace(/_/g, " ")}` : "Add New Authentication" }),
|
|
3770
3854
|
loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material4.Box, { sx: { display: "flex", alignItems: "center", justifyContent: "center", py: 4 }, children: [
|
|
3771
3855
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.CircularProgress, { size: 32, sx: { color: "hsl(var(--primary))" } }),
|
|
3772
3856
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_material4.Typography, { sx: { ml: 2, color: "hsl(var(--muted-foreground))" }, children: "Loading configuration..." })
|
|
@@ -3802,6 +3886,7 @@ var AppAuthCard = ({
|
|
|
3802
3886
|
] })
|
|
3803
3887
|
}
|
|
3804
3888
|
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material4.Box, { sx: { display: "flex", flexDirection: "column", gap: 3 }, children: [
|
|
3889
|
+
extraFieldsSlot?.({ credentials: localCredentials, setField: handleCredentialChange }),
|
|
3805
3890
|
renderOAuth2Fields(),
|
|
3806
3891
|
renderParameterFields(),
|
|
3807
3892
|
authState.status === "error" && authState.errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -3856,38 +3941,97 @@ var AppAuthCard = ({
|
|
|
3856
3941
|
children: "Failed to save authentication. Please try again."
|
|
3857
3942
|
}
|
|
3858
3943
|
),
|
|
3859
|
-
!isOAuth2 && /* @__PURE__ */ (0, import_jsx_runtime6.
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
e
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3944
|
+
!isOAuth2 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_material4.Box, { sx: { display: "flex", justifyContent: "flex-end", pt: 1.5, gap: 1, flexWrap: "wrap" }, children: [
|
|
3945
|
+
pendingFailedAuthId && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
3946
|
+
import_material4.Button,
|
|
3947
|
+
{
|
|
3948
|
+
variant: "text",
|
|
3949
|
+
size: "medium",
|
|
3950
|
+
onClick: async (e) => {
|
|
3951
|
+
e.stopPropagation();
|
|
3952
|
+
const previousFailedId = pendingFailedAuthId;
|
|
3953
|
+
setPendingFailedAuthId(null);
|
|
3954
|
+
setUserHasSelected(true);
|
|
3955
|
+
setFieldErrors({});
|
|
3956
|
+
await onSaveAuth(app.objectID, localCredentials);
|
|
3957
|
+
let entries = apiAuthEntries;
|
|
3958
|
+
if (onRefreshAuth) {
|
|
3959
|
+
await onRefreshAuth();
|
|
3960
|
+
}
|
|
3961
|
+
entries = apiAuthEntries || [];
|
|
3962
|
+
const sorted = [...entries].sort((a, b) => (b.created || 0) - (a.created || 0));
|
|
3963
|
+
const acceptId = sorted[0]?.id || previousFailedId;
|
|
3964
|
+
setSelectedAuthId(acceptId);
|
|
3965
|
+
const stale = entries.filter((e2) => e2.id && e2.id !== acceptId);
|
|
3966
|
+
await Promise.all(stale.map(async (entry) => {
|
|
3967
|
+
try {
|
|
3968
|
+
await fetch(getApiUrl(`/api/v1/apps/authentication/${entry.id}`), {
|
|
3969
|
+
method: "DELETE",
|
|
3970
|
+
credentials: "include",
|
|
3971
|
+
headers: { ...getAuthHeader() }
|
|
3972
|
+
});
|
|
3973
|
+
} catch (err) {
|
|
3974
|
+
console.error("[AppAuthCard] Failed to delete stale auth on Save anyway:", err);
|
|
3975
|
+
}
|
|
3976
|
+
}));
|
|
3977
|
+
if (onRefreshAuth) await onRefreshAuth();
|
|
3978
|
+
if (onSelectAuth) onSelectAuth(app.objectID, acceptId);
|
|
3979
|
+
if (typeof window !== "undefined") {
|
|
3980
|
+
window.dispatchEvent(new CustomEvent("integrations-changed"));
|
|
3981
|
+
window.dispatchEvent(new CustomEvent("agent-drawer-close"));
|
|
3982
|
+
}
|
|
3882
3983
|
},
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3984
|
+
sx: {
|
|
3985
|
+
color: "hsl(var(--muted-foreground))",
|
|
3986
|
+
fontWeight: 600,
|
|
3987
|
+
textTransform: "none",
|
|
3988
|
+
fontSize: "0.85rem",
|
|
3989
|
+
px: 2,
|
|
3990
|
+
py: 1,
|
|
3991
|
+
borderRadius: 2,
|
|
3992
|
+
"&:hover": {
|
|
3993
|
+
color: "hsl(var(--foreground))",
|
|
3994
|
+
backgroundColor: "hsl(var(--muted) / 0.5)"
|
|
3995
|
+
}
|
|
3996
|
+
},
|
|
3997
|
+
title: "Our test isn't always authoritative \u2014 keep the credentials you saved and dismiss the failure.",
|
|
3998
|
+
children: "Save anyway"
|
|
3999
|
+
}
|
|
4000
|
+
),
|
|
4001
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4002
|
+
import_material4.Button,
|
|
4003
|
+
{
|
|
4004
|
+
variant: "outlined",
|
|
4005
|
+
size: "medium",
|
|
4006
|
+
onClick: (e) => {
|
|
4007
|
+
e.stopPropagation();
|
|
4008
|
+
setPendingFailedAuthId(null);
|
|
4009
|
+
handleSave();
|
|
4010
|
+
},
|
|
4011
|
+
disabled: saving || !isFormValid(),
|
|
4012
|
+
sx: {
|
|
4013
|
+
borderColor: isFormValid() ? "hsl(var(--primary) / 0.5)" : "hsl(var(--border))",
|
|
4014
|
+
color: isFormValid() ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))",
|
|
4015
|
+
fontWeight: 600,
|
|
4016
|
+
textTransform: "none",
|
|
4017
|
+
fontSize: "0.9rem",
|
|
4018
|
+
px: 3,
|
|
4019
|
+
py: 1,
|
|
4020
|
+
borderRadius: 2,
|
|
4021
|
+
transition: "all 0.2s ease",
|
|
4022
|
+
"&:hover": {
|
|
4023
|
+
borderColor: "hsl(var(--primary))",
|
|
4024
|
+
backgroundColor: "hsl(var(--primary) / 0.08)"
|
|
4025
|
+
},
|
|
4026
|
+
"&.Mui-disabled": {
|
|
4027
|
+
borderColor: "hsl(var(--border))",
|
|
4028
|
+
color: "hsl(var(--muted-foreground))"
|
|
4029
|
+
}
|
|
4030
|
+
},
|
|
4031
|
+
children: saving ? "Testing..." : pendingFailedAuthId ? "Retry Test" : "Test Authentication"
|
|
4032
|
+
}
|
|
4033
|
+
)
|
|
4034
|
+
] }),
|
|
3891
4035
|
isOAuth2 && (() => {
|
|
3892
4036
|
const hasClientId = !!localCredentials["client_id"]?.trim();
|
|
3893
4037
|
const hasClientSecret = !!localCredentials["client_secret"]?.trim();
|
|
@@ -5706,6 +5850,7 @@ function AppDetailDrawer({
|
|
|
5706
5850
|
onAddToCanvas,
|
|
5707
5851
|
isAuthenticated = true,
|
|
5708
5852
|
activeOrgId,
|
|
5853
|
+
autoActivate = false,
|
|
5709
5854
|
globalUrl,
|
|
5710
5855
|
userdata,
|
|
5711
5856
|
isLoaded,
|
|
@@ -5903,8 +6048,9 @@ function AppDetailDrawer({
|
|
|
5903
6048
|
(0, import_react11.useEffect)(() => {
|
|
5904
6049
|
lastValidAuthRef.current = null;
|
|
5905
6050
|
}, [appName]);
|
|
5906
|
-
const handleActivateToggle = async () => {
|
|
6051
|
+
const handleActivateToggle = async (opts) => {
|
|
5907
6052
|
if (!appName || activateLoading) return;
|
|
6053
|
+
const silent = !!opts?.silent;
|
|
5908
6054
|
const wasActivated = isActivated;
|
|
5909
6055
|
const prevAppId = activatedAppId;
|
|
5910
6056
|
setIsActivated(!wasActivated);
|
|
@@ -5918,7 +6064,7 @@ function AppDetailDrawer({
|
|
|
5918
6064
|
});
|
|
5919
6065
|
if (!res.ok) throw new Error("Deactivate failed");
|
|
5920
6066
|
setActivatedAppId(null);
|
|
5921
|
-
toast.success(`${displayName} deactivated`);
|
|
6067
|
+
if (!silent) toast.success(`${displayName} deactivated`);
|
|
5922
6068
|
} else {
|
|
5923
6069
|
const appId2 = resolvedAlgoliaId;
|
|
5924
6070
|
if (!appId2) throw new Error("App ID not resolved yet");
|
|
@@ -5929,40 +6075,71 @@ function AppDetailDrawer({
|
|
|
5929
6075
|
});
|
|
5930
6076
|
if (!activateRes.ok) throw new Error(`Activate failed (${activateRes.status})`);
|
|
5931
6077
|
setActivatedAppId(appId2);
|
|
5932
|
-
toast.success(`${displayName} activated`);
|
|
6078
|
+
if (!silent) toast.success(`${displayName} activated`);
|
|
5933
6079
|
}
|
|
5934
6080
|
} catch (err) {
|
|
5935
6081
|
console.error("[Activate] Error:", err);
|
|
5936
|
-
toast.error(err?.message || "Activation failed");
|
|
6082
|
+
if (!silent) toast.error(err?.message || "Activation failed");
|
|
5937
6083
|
setIsActivated(wasActivated);
|
|
5938
6084
|
setActivatedAppId(prevAppId);
|
|
5939
6085
|
} finally {
|
|
5940
6086
|
setActivateLoading(false);
|
|
5941
6087
|
}
|
|
5942
6088
|
};
|
|
6089
|
+
const autoActivateFiredRef = (0, import_react11.useRef)(null);
|
|
6090
|
+
const [autoActivatePulse, setAutoActivatePulse] = (0, import_react11.useState)(false);
|
|
6091
|
+
(0, import_react11.useEffect)(() => {
|
|
6092
|
+
if (!open || !autoActivate || !appName) return;
|
|
6093
|
+
const key = `${appName}`;
|
|
6094
|
+
if (autoActivateFiredRef.current === key) return;
|
|
6095
|
+
if (isActivated !== false) return;
|
|
6096
|
+
if (!resolvedAlgoliaId) return;
|
|
6097
|
+
if (activateLoading) return;
|
|
6098
|
+
autoActivateFiredRef.current = key;
|
|
6099
|
+
setAutoActivatePulse(true);
|
|
6100
|
+
handleActivateToggle({ silent: true }).finally(() => {
|
|
6101
|
+
setTimeout(() => setAutoActivatePulse(false), 1200);
|
|
6102
|
+
});
|
|
6103
|
+
}, [open, autoActivate, appName, isActivated, resolvedAlgoliaId, activateLoading]);
|
|
6104
|
+
(0, import_react11.useEffect)(() => {
|
|
6105
|
+
if (!open) {
|
|
6106
|
+
autoActivateFiredRef.current = null;
|
|
6107
|
+
setAutoActivatePulse(false);
|
|
6108
|
+
}
|
|
6109
|
+
}, [open, appName]);
|
|
5943
6110
|
const isLoadingAll = appLoading || isAuthenticated && appAuthLoading;
|
|
6111
|
+
const drawerWidth = `min(${width}px, 100vw)`;
|
|
5944
6112
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
5945
6113
|
import_material9.Drawer,
|
|
5946
6114
|
{
|
|
5947
6115
|
anchor,
|
|
5948
6116
|
open,
|
|
5949
6117
|
onClose: handleClose,
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
6118
|
+
PaperProps: {
|
|
6119
|
+
className: scopeClassName,
|
|
6120
|
+
sx: {
|
|
6121
|
+
width: drawerWidth,
|
|
6122
|
+
minWidth: drawerWidth,
|
|
6123
|
+
maxWidth: drawerWidth,
|
|
6124
|
+
flex: `0 0 ${drawerWidth}`,
|
|
6125
|
+
height: "100vh",
|
|
6126
|
+
display: "flex",
|
|
6127
|
+
flexDirection: "column",
|
|
6128
|
+
overflow: "hidden",
|
|
6129
|
+
background: "linear-gradient(180deg, hsl(var(--card)) 0%, hsl(var(--background)) 100%)",
|
|
6130
|
+
borderLeft: anchor === "right" ? "1px solid hsl(var(--border))" : "none",
|
|
6131
|
+
borderRight: anchor === "left" ? "1px solid hsl(var(--border))" : "none"
|
|
5962
6132
|
}
|
|
5963
6133
|
},
|
|
5964
6134
|
sx: {
|
|
5965
|
-
|
|
6135
|
+
zIndex: 9999,
|
|
6136
|
+
"& .MuiDrawer-paper": {
|
|
6137
|
+
boxSizing: "border-box",
|
|
6138
|
+
width: `${drawerWidth} !important`,
|
|
6139
|
+
minWidth: `${drawerWidth} !important`,
|
|
6140
|
+
maxWidth: `${drawerWidth} !important`,
|
|
6141
|
+
flex: `0 0 ${drawerWidth} !important`
|
|
6142
|
+
}
|
|
5966
6143
|
},
|
|
5967
6144
|
children: [
|
|
5968
6145
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
@@ -6015,7 +6192,8 @@ function AppDetailDrawer({
|
|
|
6015
6192
|
categories: appInfo?.categories,
|
|
6016
6193
|
isActivated: onAddToCanvas ? null : effectiveActivated,
|
|
6017
6194
|
activateLoading,
|
|
6018
|
-
onActivateToggle: handleActivateToggle,
|
|
6195
|
+
onActivateToggle: () => handleActivateToggle(),
|
|
6196
|
+
highlightActivate: autoActivatePulse,
|
|
6019
6197
|
onAdd: onAddToCanvas && appName ? () => {
|
|
6020
6198
|
onAddToCanvas({ name: appName, icon: resolvedImage || "", algoliaId: resolvedAlgoliaId });
|
|
6021
6199
|
onClose();
|
|
@@ -6119,7 +6297,7 @@ function AppDetailDrawer({
|
|
|
6119
6297
|
}
|
|
6120
6298
|
|
|
6121
6299
|
// views/ShuffleMCP.tsx
|
|
6122
|
-
var import_shuffle_mcp2 = require("./shuffle-mcp-
|
|
6300
|
+
var import_shuffle_mcp2 = require("./shuffle-mcp-TWJGPBOQ.css");
|
|
6123
6301
|
init_appsCache();
|
|
6124
6302
|
|
|
6125
6303
|
// components/SegmentedControl.tsx
|
|
@@ -6287,7 +6465,7 @@ function SegmentedControl({
|
|
|
6287
6465
|
children: opt.label
|
|
6288
6466
|
}
|
|
6289
6467
|
),
|
|
6290
|
-
!isAction && typeof opt.count === "number" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6468
|
+
!isAction && (typeof opt.count === "number" || typeof opt.count === "string") && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
6291
6469
|
"span",
|
|
6292
6470
|
{
|
|
6293
6471
|
style: {
|
|
@@ -6786,8 +6964,8 @@ var ShuffleMCP = import_react12.default.forwardRef(({
|
|
|
6786
6964
|
value: sourceFilter,
|
|
6787
6965
|
onChange: (v) => setSourceFilter(v),
|
|
6788
6966
|
options: [
|
|
6789
|
-
{ value: "all", label: "All", count: results.length + filteredPrivateApps.length, title: "All available apps \u2014 both the public catalog and your private apps." },
|
|
6790
|
-
{ value: "public", label: "Public", count: results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6967
|
+
{ 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." },
|
|
6968
|
+
{ value: "public", label: "Public", count: results.length >= hitsPerPage ? `${results.length}+` : results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
|
|
6791
6969
|
{ value: "private", label: "Private", count: filteredPrivateApps.length, title: "Private apps are apps you have activated in your organization, or your own custom apps \u2014 not just from the public Algolia catalog." },
|
|
6792
6970
|
{ value: "authenticated", label: "Authenticated", count: [...filteredPrivateApps, ...results].filter((a, i, arr) => arr.findIndex((x) => x.name?.toLowerCase() === a.name?.toLowerCase()) === i).filter(isAppConfigured).length, title: "Apps you have authenticated and that are ready to use." }
|
|
6793
6971
|
]
|
|
@@ -6963,9 +7141,11 @@ function AppSearchDrawer({
|
|
|
6963
7141
|
pinnedApps,
|
|
6964
7142
|
highlightAppName,
|
|
6965
7143
|
highlightDelayMs = 5e3,
|
|
7144
|
+
realtimeHighlightAppNames,
|
|
6966
7145
|
multiSelect = false,
|
|
6967
7146
|
selectedApps,
|
|
6968
7147
|
onSelectionChange,
|
|
7148
|
+
autoActivate = false,
|
|
6969
7149
|
globalUrl,
|
|
6970
7150
|
theme,
|
|
6971
7151
|
colorMode
|
|
@@ -6992,6 +7172,7 @@ function AppSearchDrawer({
|
|
|
6992
7172
|
const t = setTimeout(() => setHighlightActive(true), highlightDelayMs);
|
|
6993
7173
|
return () => clearTimeout(t);
|
|
6994
7174
|
}, [open, highlightAppName, highlightDelayMs]);
|
|
7175
|
+
const drawerWidth = `min(${width}px, 100vw)`;
|
|
6995
7176
|
const handleClose = () => {
|
|
6996
7177
|
setDetailAppName(null);
|
|
6997
7178
|
setDetailAppId(null);
|
|
@@ -7068,29 +7249,38 @@ function AppSearchDrawer({
|
|
|
7068
7249
|
anchor,
|
|
7069
7250
|
open: open && detailAppName === null,
|
|
7070
7251
|
onClose: handleClose,
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7252
|
+
PaperProps: {
|
|
7253
|
+
className: scopeClassName,
|
|
7254
|
+
sx: {
|
|
7255
|
+
// Strict, environment-independent sizing so the drawer
|
|
7256
|
+
// looks identical on every host (Shuffle Security, /agents,
|
|
7257
|
+
// test page, embedded library, etc.). No breakpoint variance.
|
|
7258
|
+
// NOTE: use PaperProps (not slotProps.paper) — slotProps.paper
|
|
7259
|
+
// was added in MUI v6 and is silently ignored on MUI v5 hosts,
|
|
7260
|
+
// which made the drawer collapse to content width when
|
|
7261
|
+
// consumed from the published library.
|
|
7262
|
+
width: drawerWidth,
|
|
7263
|
+
minWidth: drawerWidth,
|
|
7264
|
+
maxWidth: drawerWidth,
|
|
7265
|
+
flex: `0 0 ${drawerWidth}`,
|
|
7266
|
+
height: "100vh",
|
|
7267
|
+
display: "flex",
|
|
7268
|
+
flexDirection: "column",
|
|
7269
|
+
overflow: "hidden",
|
|
7270
|
+
background: "linear-gradient(180deg, hsl(var(--card)) 0%, hsl(var(--background)) 100%)",
|
|
7271
|
+
borderLeft: anchor === "right" ? "1px solid hsl(var(--border))" : "none",
|
|
7272
|
+
borderRight: anchor === "left" ? "1px solid hsl(var(--border))" : "none"
|
|
7089
7273
|
}
|
|
7090
7274
|
},
|
|
7091
7275
|
sx: {
|
|
7092
7276
|
zIndex: 9999,
|
|
7093
|
-
"& .MuiDrawer-paper": {
|
|
7277
|
+
"& .MuiDrawer-paper": {
|
|
7278
|
+
boxSizing: "border-box",
|
|
7279
|
+
width: `${drawerWidth} !important`,
|
|
7280
|
+
minWidth: `${drawerWidth} !important`,
|
|
7281
|
+
maxWidth: `${drawerWidth} !important`,
|
|
7282
|
+
flex: `0 0 ${drawerWidth} !important`
|
|
7283
|
+
}
|
|
7094
7284
|
},
|
|
7095
7285
|
children: [
|
|
7096
7286
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
@@ -7122,7 +7312,7 @@ function AppSearchDrawer({
|
|
|
7122
7312
|
]
|
|
7123
7313
|
}
|
|
7124
7314
|
),
|
|
7125
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material11.Box, { sx: { flex: 1, boxSizing: "border-box", overflow: "hidden", p: 3, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
7315
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material11.Box, { sx: { flex: 1, width: "100%", minWidth: 0, boxSizing: "border-box", overflow: "hidden", p: 3, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
7126
7316
|
connectionPathApps && connectionPathApps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_material11.Box, { sx: { mb: 2.5 }, children: [
|
|
7127
7317
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material11.Typography, { sx: { color: "hsl(var(--muted-foreground))", fontSize: "0.7rem", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.05em", mb: 1 }, children: "In this usecase" }),
|
|
7128
7318
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material11.Box, { sx: { display: "flex", gap: 1.5, flexWrap: "wrap" }, children: connectionPathApps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_material11.Tooltip, { title: app.name.replace(/_/g, " "), arrow: true, placement: "bottom", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
@@ -7169,6 +7359,8 @@ function AppSearchDrawer({
|
|
|
7169
7359
|
{
|
|
7170
7360
|
sx: {
|
|
7171
7361
|
flex: 1,
|
|
7362
|
+
width: "100%",
|
|
7363
|
+
minWidth: 0,
|
|
7172
7364
|
minHeight: 0,
|
|
7173
7365
|
overflow: "hidden",
|
|
7174
7366
|
"& .singul-container, & .singul-search-bar-container": {
|
|
@@ -7181,16 +7373,22 @@ function AppSearchDrawer({
|
|
|
7181
7373
|
},
|
|
7182
7374
|
"& .singul-results-container": {
|
|
7183
7375
|
flex: 1,
|
|
7376
|
+
width: "100%",
|
|
7377
|
+
minWidth: 0,
|
|
7184
7378
|
minHeight: 0,
|
|
7185
7379
|
maxHeight: "none",
|
|
7186
7380
|
overflowY: "auto"
|
|
7187
7381
|
},
|
|
7188
7382
|
"& .singul-results-grid": {
|
|
7383
|
+
width: "100% !important",
|
|
7384
|
+
minWidth: "0 !important",
|
|
7189
7385
|
gridTemplateColumns: "repeat(2, minmax(0, 1fr)) !important",
|
|
7190
7386
|
gridAutoRows: "78px !important",
|
|
7191
7387
|
gap: "12px !important"
|
|
7192
7388
|
},
|
|
7193
7389
|
"& .singul-results-grid .singul-dropdown-item": {
|
|
7390
|
+
width: "100%",
|
|
7391
|
+
maxWidth: "100%",
|
|
7194
7392
|
minWidth: 0,
|
|
7195
7393
|
minHeight: "78px !important",
|
|
7196
7394
|
maxHeight: "78px !important",
|
|
@@ -7224,6 +7422,41 @@ function AppSearchDrawer({
|
|
|
7224
7422
|
"0%, 100%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 12px 1px hsl(var(--primary) / 0.4)" },
|
|
7225
7423
|
"50%": { boxShadow: "0 0 0 2px hsl(var(--primary)), 0 0 24px 4px hsl(var(--primary) / 0.75)" }
|
|
7226
7424
|
}
|
|
7425
|
+
} : {},
|
|
7426
|
+
...realtimeHighlightAppNames && realtimeHighlightAppNames.length > 0 ? {
|
|
7427
|
+
[realtimeHighlightAppNames.map((n) => `& .singul-dropdown-item[data-app-name="${n}"]`).join(", ")]: {
|
|
7428
|
+
position: "relative",
|
|
7429
|
+
zIndex: 2,
|
|
7430
|
+
borderColor: "hsl(var(--primary) / 0.78) !important",
|
|
7431
|
+
backgroundColor: "hsl(var(--primary) / 0.08) !important",
|
|
7432
|
+
outline: "none !important",
|
|
7433
|
+
boxShadow: "none !important",
|
|
7434
|
+
animation: "shuffleHighlightPulseStrong 1.5s ease-in-out infinite",
|
|
7435
|
+
transition: "border-color 120ms ease, background-color 120ms ease",
|
|
7436
|
+
"&::before": {
|
|
7437
|
+
content: '""',
|
|
7438
|
+
position: "absolute",
|
|
7439
|
+
left: "10px",
|
|
7440
|
+
top: "14px",
|
|
7441
|
+
bottom: "14px",
|
|
7442
|
+
width: "3px",
|
|
7443
|
+
borderRadius: "999px",
|
|
7444
|
+
backgroundColor: "hsl(var(--primary))"
|
|
7445
|
+
},
|
|
7446
|
+
"& .singul-app-info": {
|
|
7447
|
+
paddingLeft: "8px"
|
|
7448
|
+
}
|
|
7449
|
+
},
|
|
7450
|
+
"@keyframes shuffleHighlightPulseStrong": {
|
|
7451
|
+
"0%, 100%": {
|
|
7452
|
+
borderColor: "hsl(var(--primary) / 0.62)",
|
|
7453
|
+
backgroundColor: "hsl(var(--primary) / 0.06)"
|
|
7454
|
+
},
|
|
7455
|
+
"50%": {
|
|
7456
|
+
borderColor: "hsl(var(--primary) / 0.92)",
|
|
7457
|
+
backgroundColor: "hsl(var(--primary) / 0.12)"
|
|
7458
|
+
}
|
|
7459
|
+
}
|
|
7227
7460
|
} : {}
|
|
7228
7461
|
},
|
|
7229
7462
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_framer_motion8.AnimatePresence, { mode: "wait", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -7246,8 +7479,9 @@ function AppSearchDrawer({
|
|
|
7246
7479
|
layout: "grid",
|
|
7247
7480
|
gridColumns: 2,
|
|
7248
7481
|
inline: true,
|
|
7482
|
+
initialQuery,
|
|
7249
7483
|
initialFilterQuery: initialQuery,
|
|
7250
|
-
hitsPerPage:
|
|
7484
|
+
hitsPerPage: 20,
|
|
7251
7485
|
showDescription: false,
|
|
7252
7486
|
showCategories: true,
|
|
7253
7487
|
showCheckbox: multiSelect,
|
|
@@ -7338,7 +7572,8 @@ function AppSearchDrawer({
|
|
|
7338
7572
|
theme,
|
|
7339
7573
|
colorMode,
|
|
7340
7574
|
onRefresh: onClose,
|
|
7341
|
-
onAddToCanvas
|
|
7575
|
+
onAddToCanvas,
|
|
7576
|
+
autoActivate
|
|
7342
7577
|
}
|
|
7343
7578
|
)
|
|
7344
7579
|
] });
|
|
@@ -7605,11 +7840,173 @@ function ShufflePipelinesBanner() {
|
|
|
7605
7840
|
var ShufflePipelinesBanner_default = ShufflePipelinesBanner;
|
|
7606
7841
|
|
|
7607
7842
|
// components/AgentUI.tsx
|
|
7608
|
-
var import_react15 = require("react");
|
|
7843
|
+
var import_react15 = __toESM(require("react"));
|
|
7609
7844
|
var import_lucide_react11 = require("lucide-react");
|
|
7610
7845
|
var import_react_router_dom2 = require("react-router-dom");
|
|
7611
7846
|
var import_material16 = require("@mui/material");
|
|
7612
7847
|
var import_react_markdown4 = __toESM(require("react-markdown"));
|
|
7848
|
+
|
|
7849
|
+
// components/agentPromptSuggestions.ts
|
|
7850
|
+
var AGENT_PROMPT_SUGGESTIONS = [
|
|
7851
|
+
// — Email & comms ————————————————————————————————————————————————
|
|
7852
|
+
"Take care of my emails by pretending to be me and answering them",
|
|
7853
|
+
"Triage my inbox every hour and draft replies for anything urgent",
|
|
7854
|
+
"Summarise my unread emails from the last 24 hours and rank them by importance",
|
|
7855
|
+
"Forward any phishing-looking emails in my inbox to the security team and quarantine them",
|
|
7856
|
+
"Reply to scheduling requests in my inbox using my working hours and calendar availability",
|
|
7857
|
+
"Every morning, send me a digest of overnight emails grouped by sender and topic",
|
|
7858
|
+
"Auto-unsubscribe from marketing emails I have not opened in 60 days",
|
|
7859
|
+
"Snooze low-priority newsletters until Friday afternoon",
|
|
7860
|
+
"Flag and archive shipping notifications once the package is delivered",
|
|
7861
|
+
"Clean up my inbox by archiving anything older than 30 days that I have already read",
|
|
7862
|
+
// — Calendar & meetings ————————————————————————————————————————————
|
|
7863
|
+
"Block focus time on my calendar every weekday morning between 9 and 11",
|
|
7864
|
+
"Decline meetings that conflict with my focus blocks and propose alternatives",
|
|
7865
|
+
"Send me a daily agenda every weekday at 8am with prep notes per meeting",
|
|
7866
|
+
"Reschedule any meeting without an agenda 24 hours before it starts",
|
|
7867
|
+
"Send meeting notes and action items to all attendees after every call",
|
|
7868
|
+
"Find a 30-minute slot this week that works for me and the people I mention",
|
|
7869
|
+
"Cancel recurring meetings that I have skipped 3 times in a row",
|
|
7870
|
+
"Remind me 15 minutes before any meeting that I have not prepared for",
|
|
7871
|
+
// — Incidents & SOC operations ———————————————————————————————————
|
|
7872
|
+
"Triage new incidents every 15 minutes and assign severity, owner, and next steps",
|
|
7873
|
+
"Watch for new critical incidents and page the on-call engineer immediately",
|
|
7874
|
+
"Close incidents older than 30 days that have had no activity and no observables",
|
|
7875
|
+
"Merge duplicate incidents that share the same observable or hostname",
|
|
7876
|
+
"Enrich every new incident with threat intel and asset context within 2 minutes",
|
|
7877
|
+
"Auto-acknowledge incidents from known maintenance windows and link them to the change ticket",
|
|
7878
|
+
"Summarise yesterday's incidents into a daily standup brief for the SOC team",
|
|
7879
|
+
"Escalate any incident that breaches its SLA to the team lead",
|
|
7880
|
+
"Tag every incident with the MITRE ATT&CK technique that best matches its observables",
|
|
7881
|
+
"Watch the alert queue and group related alerts into a single incident",
|
|
7882
|
+
"Auto-resolve incidents whose root cause matches a previously closed incident",
|
|
7883
|
+
"Reopen any closed incident if the same observable shows up again within 7 days",
|
|
7884
|
+
"Send a weekly incident trend report every Monday morning to the security leadership",
|
|
7885
|
+
// — Threat intel & IOCs —————————————————————————————————————————
|
|
7886
|
+
"Pull new IOCs from my threat feeds every hour and push them to the firewall blocklist",
|
|
7887
|
+
"Check every external IP in today's incidents against VirusTotal and AbuseIPDB",
|
|
7888
|
+
"Sweep the environment for any host that has connected to a known bad domain in the last 7 days",
|
|
7889
|
+
"Subscribe to new CISA advisories and turn them into detection rules where possible",
|
|
7890
|
+
"Cross-reference observed file hashes against MalwareBazaar daily",
|
|
7891
|
+
"Watch for newly registered domains that look like our brand and report them",
|
|
7892
|
+
"Alert me whenever a new CVE with a known exploit affects software in our inventory",
|
|
7893
|
+
"Refresh the IOC datastore every 6 hours and prune entries older than 30 days",
|
|
7894
|
+
// — Detection engineering ———————————————————————————————————————
|
|
7895
|
+
"Review noisy detection rules every week and propose tuning suggestions",
|
|
7896
|
+
"Convert the latest Sigma rules from the public repo into our SIEM's format and stage them for review",
|
|
7897
|
+
"Tell me which detection rules have not fired in the last 90 days so I can retire them",
|
|
7898
|
+
"Audit MITRE ATT&CK coverage every Monday and flag techniques with zero detections",
|
|
7899
|
+
"Backtest new detection rules against the last 30 days of logs before promoting them to production",
|
|
7900
|
+
// — SIEM operations ———————————————————————————————————————————
|
|
7901
|
+
"Triage new Splunk alerts every 10 minutes and assign severity, owner, and next steps",
|
|
7902
|
+
"Watch Microsoft Sentinel for high-severity incidents and page the on-call analyst immediately",
|
|
7903
|
+
"Suppress noisy SIEM alerts that fire more than 50 times per hour and open a tuning ticket",
|
|
7904
|
+
"Correlate failed login spikes in the SIEM with VPN logs and flag possible brute-force attempts",
|
|
7905
|
+
"Hunt the SIEM every morning for sign-ins from countries we do not operate in",
|
|
7906
|
+
"Forward critical SIEM detections straight to Case Management and skip the alert queue",
|
|
7907
|
+
"Run a weekly SIEM data-source health check and alert me on any log source silent for over 1 hour",
|
|
7908
|
+
"Enrich every SIEM alert with asset owner, criticality, and recent vulnerabilities before triage",
|
|
7909
|
+
"Search the SIEM for the latest IOCs from threat intel feeds every 30 minutes",
|
|
7910
|
+
"Summarise top 10 noisiest SIEM rules every Friday and propose tuning candidates",
|
|
7911
|
+
"Detect lateral movement patterns in SIEM auth logs and open an incident with the affected hosts",
|
|
7912
|
+
"Watch the SIEM for any disable or delete of audit logging and treat it as a critical incident",
|
|
7913
|
+
// — EDR operations ————————————————————————————————————————————
|
|
7914
|
+
"Isolate any endpoint that triggers a critical CrowdStrike alert and notify the user's manager",
|
|
7915
|
+
"Kill any process on a flagged host that matches a known malware family in EDR telemetry",
|
|
7916
|
+
"Watch SentinelOne for ransomware behavior detections and auto-contain the host within 60 seconds",
|
|
7917
|
+
"Pull the process tree from EDR for every malware detection and attach it to the incident",
|
|
7918
|
+
"Sweep all endpoints for a given hash or filename when a new IOC arrives and report matches",
|
|
7919
|
+
"Detect newly created local admin accounts on any endpoint and require approval before keeping them",
|
|
7920
|
+
"Alert when an EDR agent goes offline for more than 1 hour and open a ticket against the asset owner",
|
|
7921
|
+
"Quarantine any binary flagged as suspicious by EDR and email the user with next steps",
|
|
7922
|
+
"Hunt EDR telemetry every night for LOLBins executed from user-writable directories",
|
|
7923
|
+
"Correlate EDR alerts with SIEM auth events to detect credential theft followed by execution",
|
|
7924
|
+
"Run a weekly EDR coverage report and list endpoints without an active agent",
|
|
7925
|
+
"Auto-resolve EDR alerts that match a known-good signed binary on our allowlist",
|
|
7926
|
+
// — Vulnerability management ————————————————————————————————————
|
|
7927
|
+
"Scan our asset inventory daily and open tickets for any new critical or high vulnerability",
|
|
7928
|
+
"Remind asset owners every Friday about open vulnerabilities older than 14 days",
|
|
7929
|
+
"Re-scan hosts that recently patched a critical vulnerability and close the ticket if clean",
|
|
7930
|
+
"Send the patch compliance report every Monday morning to IT and security leadership",
|
|
7931
|
+
"Correlate vulnerabilities with active exploits in the wild and re-prioritise the queue",
|
|
7932
|
+
// — Endpoint & host monitoring ———————————————————————————————————
|
|
7933
|
+
"Watch my host monitors and alert me if any agent goes offline for more than 1 hour",
|
|
7934
|
+
"Isolate any endpoint that triggers a critical EDR alert and notify the user's manager",
|
|
7935
|
+
"Kill any process on a flagged host that matches a known malware family",
|
|
7936
|
+
"Run an inventory of installed software on every endpoint every Sunday",
|
|
7937
|
+
"Detect new local admin accounts created on any endpoint and require approval",
|
|
7938
|
+
"Make sure full-disk encryption is on for every laptop and report exceptions weekly",
|
|
7939
|
+
// — Identity & access —————————————————————————————————————————
|
|
7940
|
+
"Review user access every quarter and flag anyone with privileges they have not used in 90 days",
|
|
7941
|
+
"Disable accounts that have not logged in for 60 days and notify their manager",
|
|
7942
|
+
"Watch for impossible travel sign-ins and force a password reset plus MFA re-enrolment",
|
|
7943
|
+
"Alert me whenever someone is added to an admin group and require justification within 24 hours",
|
|
7944
|
+
"Audit MFA enrolment weekly and email any user without a second factor",
|
|
7945
|
+
"Rotate service account credentials every 90 days and update the vault",
|
|
7946
|
+
"Detect dormant API keys older than 180 days and revoke them after notice",
|
|
7947
|
+
"Make sure new joiners get baseline access provisioned within 1 hour of their start date",
|
|
7948
|
+
"Make sure leavers have all access revoked within 15 minutes of their termination event",
|
|
7949
|
+
// — Cloud, infra & posture ————————————————————————————————————
|
|
7950
|
+
"Check our cloud accounts every hour for public S3 buckets and lock them down",
|
|
7951
|
+
"Detect new IAM roles with wildcard permissions and require review before they go live",
|
|
7952
|
+
"Watch for unencrypted databases in production and open a ticket against the owner",
|
|
7953
|
+
"Run a CIS benchmark scan against all production cloud accounts every Sunday",
|
|
7954
|
+
"Alert on any new security group that opens ports to 0.0.0.0/0",
|
|
7955
|
+
"Monitor cloud spend daily and warn me if any service's cost jumps more than 50% week-over-week",
|
|
7956
|
+
"Check certificate expiry across our domains weekly and renew anything within 30 days",
|
|
7957
|
+
"Watch our DNS records for unauthorised changes and revert them",
|
|
7958
|
+
// — Phishing & user reports ———————————————————————————————————
|
|
7959
|
+
"Investigate phishing reports from the abuse mailbox and respond to the reporter within 1 hour",
|
|
7960
|
+
"Detonate suspicious attachments in a sandbox and attach the verdict to the incident",
|
|
7961
|
+
"Pull URLs from reported phishing emails and submit them to URLhaus and PhishTank",
|
|
7962
|
+
"Send a phishing simulation to a sample of users every month and report results",
|
|
7963
|
+
// — Compliance, audit & reporting —————————————————————————————
|
|
7964
|
+
"Generate the SOC2 evidence pack at the start of every month",
|
|
7965
|
+
"Track changes to security policies and alert the GRC team when one is edited",
|
|
7966
|
+
"Send a weekly KPI report covering MTTD, MTTR, and open incident backlog",
|
|
7967
|
+
"Audit log retention every Sunday and confirm we still meet the 1-year requirement",
|
|
7968
|
+
"Generate a monthly executive summary of incidents, vulnerabilities, and detection coverage",
|
|
7969
|
+
// — Backups, DR & uptime ————————————————————————————————————
|
|
7970
|
+
"Verify nightly backups completed successfully and alert me if any failed",
|
|
7971
|
+
"Test restore from backup on a sample workload every month and report results",
|
|
7972
|
+
"Watch our public status page for incidents at our critical vendors and notify the team",
|
|
7973
|
+
"Ping our public endpoints every minute and open an incident if any return non-2xx for 3 minutes",
|
|
7974
|
+
// — Tickets, workflow & docs ——————————————————————————————————
|
|
7975
|
+
"Triage new Jira tickets in the security project every hour and assign by category",
|
|
7976
|
+
"Close tickets that have been waiting on the reporter for more than 14 days",
|
|
7977
|
+
"Summarise this week's closed tickets into release notes every Friday",
|
|
7978
|
+
"Pull action items out of meeting notes I share and create tickets for them",
|
|
7979
|
+
"Keep the on-call runbook in sync with the latest incident postmortems",
|
|
7980
|
+
"Review pull requests in our security repos and leave a summary comment within an hour",
|
|
7981
|
+
// — People, HR & onboarding ————————————————————————————————————
|
|
7982
|
+
"Send a welcome message and security training link to every new joiner on their start date",
|
|
7983
|
+
"Run the offboarding checklist whenever someone is marked as a leaver in HR",
|
|
7984
|
+
"Remind managers to complete quarterly performance reviews 1 week before the deadline",
|
|
7985
|
+
"Send birthday and work anniversary greetings from me on the right day",
|
|
7986
|
+
// — Personal / lightweight ops chores —————————————————————————
|
|
7987
|
+
"Order more office coffee whenever the inventory drops below 2 bags",
|
|
7988
|
+
"File my receipts every Friday and submit the expense report",
|
|
7989
|
+
"Track my open invoices and chase clients whose payment is more than 14 days overdue",
|
|
7990
|
+
"Send a polite follow-up to anyone I have emailed but who has not replied in 5 working days",
|
|
7991
|
+
"Read the security news feeds every morning and summarise the top 5 stories for me"
|
|
7992
|
+
];
|
|
7993
|
+
var matchAgentPromptSuggestions = (input, limit = 8) => {
|
|
7994
|
+
const q = (input || "").trim().toLowerCase();
|
|
7995
|
+
if (!q) return [];
|
|
7996
|
+
const scored = [];
|
|
7997
|
+
for (const text of AGENT_PROMPT_SUGGESTIONS) {
|
|
7998
|
+
const lower = text.toLowerCase();
|
|
7999
|
+
const idx = lower.indexOf(q);
|
|
8000
|
+
if (idx < 0) continue;
|
|
8001
|
+
const score = idx === 0 ? -1e3 + text.length : idx * 10 + text.length;
|
|
8002
|
+
scored.push({ text, score });
|
|
8003
|
+
}
|
|
8004
|
+
scored.sort((a, b) => a.score - b.score);
|
|
8005
|
+
return scored.slice(0, limit).map((s) => s.text);
|
|
8006
|
+
};
|
|
8007
|
+
var DEFAULT_AGENT_PROMPT_PLACEHOLDER = "Take care of my emails by pretending to be me and answering them";
|
|
8008
|
+
|
|
8009
|
+
// components/AgentUI.tsx
|
|
7613
8010
|
var import_remark_gfm4 = __toESM(require("remark-gfm"));
|
|
7614
8011
|
var import_remark_breaks = __toESM(require("remark-breaks"));
|
|
7615
8012
|
var import_react18_json_view2 = __toESM(require("react18-json-view"));
|
|
@@ -7755,6 +8152,73 @@ function invalidateResolvedApps() {
|
|
|
7755
8152
|
_cache.clear();
|
|
7756
8153
|
}
|
|
7757
8154
|
|
|
8155
|
+
// llmProviderDetect.ts
|
|
8156
|
+
var SHUFFLE_AI_PRESET = "Shuffle AI";
|
|
8157
|
+
var CUSTOM_PRESET = "Custom / self-hosted";
|
|
8158
|
+
var ENDPOINT_PRESETS = [
|
|
8159
|
+
{ label: SHUFFLE_AI_PRESET, url: "" },
|
|
8160
|
+
{ 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." },
|
|
8161
|
+
{ 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." },
|
|
8162
|
+
{ 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." },
|
|
8163
|
+
{ 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." },
|
|
8164
|
+
{ 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." },
|
|
8165
|
+
{ 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." },
|
|
8166
|
+
{ 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." },
|
|
8167
|
+
{ label: "OpenRouter", url: "https://openrouter.ai/api/v1", apiKeyUrl: "https://openrouter.ai/keys", apiKeyHint: "Create a key under Keys in your OpenRouter dashboard." },
|
|
8168
|
+
{ label: "Ollama (localhost)", url: "http://localhost:11434/v1", apiKeyHint: "Local Ollama does not require an API key \u2014 any non-empty value works." },
|
|
8169
|
+
{ 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." },
|
|
8170
|
+
{ label: CUSTOM_PRESET, url: "" }
|
|
8171
|
+
];
|
|
8172
|
+
var PROVIDER_DOMAINS = {
|
|
8173
|
+
"Shuffle AI": "shuffler.io",
|
|
8174
|
+
OpenAI: "openai.com",
|
|
8175
|
+
Anthropic: "anthropic.com",
|
|
8176
|
+
"Google Gemini": "gemini.google.com",
|
|
8177
|
+
Mistral: "mistral.ai",
|
|
8178
|
+
Groq: "groq.com",
|
|
8179
|
+
DeepSeek: "deepseek.com",
|
|
8180
|
+
"Together AI": "together.ai",
|
|
8181
|
+
OpenRouter: "openrouter.ai",
|
|
8182
|
+
"Ollama (localhost)": "ollama.com",
|
|
8183
|
+
"LM Studio (localhost)": "lmstudio.ai"
|
|
8184
|
+
};
|
|
8185
|
+
var hostnameOf = (url) => {
|
|
8186
|
+
try {
|
|
8187
|
+
return new URL(url).hostname.replace(/^www\./, "");
|
|
8188
|
+
} catch {
|
|
8189
|
+
return null;
|
|
8190
|
+
}
|
|
8191
|
+
};
|
|
8192
|
+
var detectLLMProvider = (url) => {
|
|
8193
|
+
if (!url) return null;
|
|
8194
|
+
const trimmed = url.trim();
|
|
8195
|
+
if (!trimmed) return null;
|
|
8196
|
+
const exact = ENDPOINT_PRESETS.find((p) => p.url && p.url === trimmed);
|
|
8197
|
+
if (exact) return exact;
|
|
8198
|
+
const host = hostnameOf(trimmed);
|
|
8199
|
+
if (host) {
|
|
8200
|
+
const byHost = ENDPOINT_PRESETS.find((p) => {
|
|
8201
|
+
const presetHost = hostnameOf(p.url);
|
|
8202
|
+
return presetHost && presetHost === host;
|
|
8203
|
+
});
|
|
8204
|
+
if (byHost) return byHost;
|
|
8205
|
+
if (host === "localhost" || host === "127.0.0.1") {
|
|
8206
|
+
if (trimmed.includes(":11434")) return ENDPOINT_PRESETS.find((p) => p.label === "Ollama (localhost)") || null;
|
|
8207
|
+
if (trimmed.includes(":1234")) return ENDPOINT_PRESETS.find((p) => p.label === "LM Studio (localhost)") || null;
|
|
8208
|
+
}
|
|
8209
|
+
}
|
|
8210
|
+
return ENDPOINT_PRESETS.find((p) => p.label === CUSTOM_PRESET) || null;
|
|
8211
|
+
};
|
|
8212
|
+
var getProviderLogoUrl = (label, url) => {
|
|
8213
|
+
if (!label && !url) return "";
|
|
8214
|
+
let domain = label ? PROVIDER_DOMAINS[label] : void 0;
|
|
8215
|
+
if (!domain && url) {
|
|
8216
|
+
const host = hostnameOf(url);
|
|
8217
|
+
if (host) domain = host;
|
|
8218
|
+
}
|
|
8219
|
+
return domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
8220
|
+
};
|
|
8221
|
+
|
|
7758
8222
|
// agentRun.ts
|
|
7759
8223
|
init_api();
|
|
7760
8224
|
var resolveTarget = (path, opts = {}) => {
|
|
@@ -8669,10 +9133,10 @@ var AgentRunDiagnosisBanner = ({ run, sx, onJumpToEvidence, executionId }) => {
|
|
|
8669
9133
|
const outputWarning = !isFailed && hasOutputWarning(run);
|
|
8670
9134
|
const diagnosis = outputWarning ? diagnoseOutputWarning(run) : null;
|
|
8671
9135
|
if (!failureInfo && !diagnosis) return null;
|
|
8672
|
-
const isCritical = !!failureInfo;
|
|
9136
|
+
const isCritical = !!failureInfo || diagnosis?.kind === "token_limit";
|
|
8673
9137
|
const tone = isCritical ? "critical" : "medium";
|
|
8674
9138
|
const Icon = isCritical ? import_lucide_react10.AlertTriangle : import_lucide_react10.HelpCircle;
|
|
8675
|
-
const message =
|
|
9139
|
+
const message = failureInfo ? failureInfo.reason : `${diagnosis.title} \u2014 ${diagnosis.remediation}`;
|
|
8676
9140
|
const firstEvidence = diagnosis?.evidence?.[0] || null;
|
|
8677
9141
|
const jumpDecisionIndex = firstEvidence ? extractDecisionIndex(firstEvidence.path) : null;
|
|
8678
9142
|
const canJump = !!(onJumpToEvidence && jumpDecisionIndex !== null);
|
|
@@ -9211,7 +9675,7 @@ var TimelineRow = ({
|
|
|
9211
9675
|
),
|
|
9212
9676
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: {
|
|
9213
9677
|
flex: 1,
|
|
9214
|
-
minWidth:
|
|
9678
|
+
minWidth: 180,
|
|
9215
9679
|
fontSize: "0.85rem",
|
|
9216
9680
|
color: "hsl(var(--foreground))",
|
|
9217
9681
|
maxHeight: 60,
|
|
@@ -9221,7 +9685,7 @@ var TimelineRow = ({
|
|
|
9221
9685
|
"& a": { color: "hsl(var(--primary))", textDecoration: "underline", textUnderlineOffset: "2px" },
|
|
9222
9686
|
"& a:hover": { opacity: 0.85 }
|
|
9223
9687
|
}, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react_markdown4.default, { remarkPlugins: [import_remark_gfm4.default, import_remark_breaks.default], children: normalizeMarkdown(displayLabel) }) }),
|
|
9224
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Tooltip, { title: hasTiming ? `Duration: ${dur.toFixed(2)}s \xB7 ${new Date(itemStart * 1e3).toLocaleString()}` : "No timing data", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: { width: maxWidth, position: "relative", height: 10, flexShrink:
|
|
9688
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Tooltip, { title: hasTiming ? `Duration: ${dur.toFixed(2)}s \xB7 ${new Date(itemStart * 1e3).toLocaleString()}` : "No timing data", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: { width: maxWidth, maxWidth, minWidth: 40, position: "relative", height: 10, flexShrink: 1, flexBasis: maxWidth }, children: dur > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: {
|
|
9225
9689
|
position: "absolute",
|
|
9226
9690
|
left: Math.max(0, offset),
|
|
9227
9691
|
width,
|
|
@@ -9547,7 +10011,7 @@ var AgentUI = ({
|
|
|
9547
10011
|
autoLoadApps = true,
|
|
9548
10012
|
title = "What do you want to do?",
|
|
9549
10013
|
subtitle,
|
|
9550
|
-
placeholder =
|
|
10014
|
+
placeholder = DEFAULT_AGENT_PROMPT_PLACEHOLDER,
|
|
9551
10015
|
defaultInput = "",
|
|
9552
10016
|
autoSubmit = false,
|
|
9553
10017
|
hideHeroIcon = false,
|
|
@@ -9599,6 +10063,29 @@ var AgentUI = ({
|
|
|
9599
10063
|
const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
|
|
9600
10064
|
const navigate = (0, import_react_router_dom2.useNavigate)();
|
|
9601
10065
|
const [actionInput, setActionInput] = (0, import_react15.useState)(defaultInput);
|
|
10066
|
+
const promptAnchorRef = import_react15.default.useRef(null);
|
|
10067
|
+
const [suggestionsDismissed, setSuggestionsDismissed] = (0, import_react15.useState)(false);
|
|
10068
|
+
const [suggestionIndex, setSuggestionIndex] = (0, import_react15.useState)(-1);
|
|
10069
|
+
const promptSuggestions = (0, import_react15.useMemo)(
|
|
10070
|
+
() => matchAgentPromptSuggestions(actionInput, 8),
|
|
10071
|
+
[actionInput]
|
|
10072
|
+
);
|
|
10073
|
+
(0, import_react15.useEffect)(() => {
|
|
10074
|
+
setSuggestionIndex(-1);
|
|
10075
|
+
setSuggestionsDismissed(false);
|
|
10076
|
+
}, [actionInput]);
|
|
10077
|
+
const suggestionsOpen = promptSuggestions.length > 0 && !suggestionsDismissed;
|
|
10078
|
+
const acceptSuggestion = (0, import_react15.useCallback)((s) => {
|
|
10079
|
+
setActionInput(s);
|
|
10080
|
+
setSuggestionsDismissed(true);
|
|
10081
|
+
setSuggestionIndex(-1);
|
|
10082
|
+
requestAnimationFrame(() => {
|
|
10083
|
+
try {
|
|
10084
|
+
inputRef.current?.focus();
|
|
10085
|
+
} catch {
|
|
10086
|
+
}
|
|
10087
|
+
});
|
|
10088
|
+
}, []);
|
|
9602
10089
|
const BUILTIN_DEFAULT_APPS = [
|
|
9603
10090
|
{ name: "http" },
|
|
9604
10091
|
{ name: "shuffle_tools" }
|
|
@@ -9606,6 +10093,7 @@ var AgentUI = ({
|
|
|
9606
10093
|
const [chosenApps, setChosenApps] = (0, import_react15.useState)(apps ?? defaultApps ?? BUILTIN_DEFAULT_APPS);
|
|
9607
10094
|
const [availableApps, setAvailableApps] = (0, import_react15.useState)([]);
|
|
9608
10095
|
const [authAppsLoading, setAuthAppsLoading] = (0, import_react15.useState)(autoLoadApps && hasApiKey);
|
|
10096
|
+
const [detectedLLM, setDetectedLLM] = (0, import_react15.useState)(null);
|
|
9609
10097
|
const [executionApps, setExecutionApps] = (0, import_react15.useState)([]);
|
|
9610
10098
|
const [resolvedToolApps, setResolvedToolApps] = (0, import_react15.useState)({});
|
|
9611
10099
|
const [appSearchOpen, setAppSearchOpen] = (0, import_react15.useState)(false);
|
|
@@ -9640,9 +10128,25 @@ var AgentUI = ({
|
|
|
9640
10128
|
const [error, setError] = (0, import_react15.useState)(null);
|
|
9641
10129
|
const [searchParams, setSearchParams] = (0, import_react_router_dom2.useSearchParams)();
|
|
9642
10130
|
const initialViewParam = searchParams.get("agentView");
|
|
9643
|
-
const
|
|
9644
|
-
initialViewParam === "detailed"
|
|
9645
|
-
|
|
10131
|
+
const readStoredViewMode = () => {
|
|
10132
|
+
if (initialViewParam === "detailed") return "detailed";
|
|
10133
|
+
if (typeof window === "undefined") return "simple";
|
|
10134
|
+
try {
|
|
10135
|
+
const stored = window.localStorage.getItem("shuffle-agents-view-mode");
|
|
10136
|
+
if (stored === "detailed" || stored === "simple") return stored;
|
|
10137
|
+
} catch {
|
|
10138
|
+
}
|
|
10139
|
+
return "simple";
|
|
10140
|
+
};
|
|
10141
|
+
const [viewMode, setViewMode] = (0, import_react15.useState)(readStoredViewMode);
|
|
10142
|
+
(0, import_react15.useEffect)(() => {
|
|
10143
|
+
try {
|
|
10144
|
+
if (typeof window !== "undefined") {
|
|
10145
|
+
window.localStorage.setItem("shuffle-agents-view-mode", viewMode);
|
|
10146
|
+
}
|
|
10147
|
+
} catch {
|
|
10148
|
+
}
|
|
10149
|
+
}, [viewMode]);
|
|
9646
10150
|
const [attachedImages, setAttachedImages] = (0, import_react15.useState)([]);
|
|
9647
10151
|
const [nowTick, setNowTick] = (0, import_react15.useState)(() => Math.floor(Date.now() / 1e3));
|
|
9648
10152
|
const [localRunStart, setLocalRunStart] = (0, import_react15.useState)(null);
|
|
@@ -9878,12 +10382,23 @@ var AgentUI = ({
|
|
|
9878
10382
|
const list = Array.isArray(result) ? result : result?.data || [];
|
|
9879
10383
|
const seen = /* @__PURE__ */ new Set();
|
|
9880
10384
|
const loaded = [];
|
|
10385
|
+
let detectedFromEntries = null;
|
|
9881
10386
|
for (const entry of list) {
|
|
9882
10387
|
const app = entry?.app || entry;
|
|
9883
10388
|
const name = app?.name;
|
|
9884
10389
|
if (!name) continue;
|
|
9885
10390
|
const valid = entry?.active || entry?.validation?.valid || entry?.hasValidAuth || app?.is_valid || app?.tested;
|
|
9886
10391
|
if (valid === false) continue;
|
|
10392
|
+
if (!detectedFromEntries && (name.toLowerCase() === "openai" || app?.id === "5d19dd82517870c68d40cacad9b5ca91")) {
|
|
10393
|
+
const urlField = (entry?.fields || []).find((f) => (f?.key || "").toLowerCase() === "url");
|
|
10394
|
+
const urlVal = (urlField?.value || "").trim();
|
|
10395
|
+
if (urlVal) {
|
|
10396
|
+
const preset = detectLLMProvider(urlVal);
|
|
10397
|
+
if (preset) {
|
|
10398
|
+
detectedFromEntries = { label: preset.label, url: urlVal, logo: getProviderLogoUrl(preset.label, urlVal) };
|
|
10399
|
+
}
|
|
10400
|
+
}
|
|
10401
|
+
}
|
|
9887
10402
|
const key = normalizeAgentAppName(name);
|
|
9888
10403
|
if (seen.has(key)) continue;
|
|
9889
10404
|
seen.add(key);
|
|
@@ -9895,6 +10410,7 @@ var AgentUI = ({
|
|
|
9895
10410
|
}
|
|
9896
10411
|
if (signal?.cancelled) return;
|
|
9897
10412
|
setAvailableApps(loaded);
|
|
10413
|
+
setDetectedLLM(detectedFromEntries);
|
|
9898
10414
|
} catch {
|
|
9899
10415
|
} finally {
|
|
9900
10416
|
if (!signal?.cancelled) setAuthAppsLoading(false);
|
|
@@ -10156,7 +10672,12 @@ var AgentUI = ({
|
|
|
10156
10672
|
setSimpleSubmitAttempted(false);
|
|
10157
10673
|
setError(null);
|
|
10158
10674
|
setLocalRunStart(null);
|
|
10159
|
-
|
|
10675
|
+
try {
|
|
10676
|
+
const stored = typeof window !== "undefined" ? window.localStorage.getItem("shuffle-agents-view-mode") : null;
|
|
10677
|
+
setViewMode(stored === "detailed" ? "detailed" : "simple");
|
|
10678
|
+
} catch {
|
|
10679
|
+
setViewMode("simple");
|
|
10680
|
+
}
|
|
10160
10681
|
setShowStarter(false);
|
|
10161
10682
|
userPickedStartRef.current = false;
|
|
10162
10683
|
if (readUrlParams && typeof window !== "undefined") {
|
|
@@ -10592,6 +11113,34 @@ var AgentUI = ({
|
|
|
10592
11113
|
}
|
|
10593
11114
|
}, [submitOverride, actionInput, chosenApps, submitInput]);
|
|
10594
11115
|
const onKeyDown = (e) => {
|
|
11116
|
+
if (suggestionsOpen && promptSuggestions.length > 0) {
|
|
11117
|
+
if (e.key === "ArrowDown") {
|
|
11118
|
+
e.preventDefault();
|
|
11119
|
+
setSuggestionIndex((i) => (i + 1) % promptSuggestions.length);
|
|
11120
|
+
return;
|
|
11121
|
+
}
|
|
11122
|
+
if (e.key === "ArrowUp") {
|
|
11123
|
+
e.preventDefault();
|
|
11124
|
+
setSuggestionIndex((i) => i <= 0 ? promptSuggestions.length - 1 : i - 1);
|
|
11125
|
+
return;
|
|
11126
|
+
}
|
|
11127
|
+
if (e.key === "Escape") {
|
|
11128
|
+
e.preventDefault();
|
|
11129
|
+
setSuggestionsDismissed(true);
|
|
11130
|
+
setSuggestionIndex(-1);
|
|
11131
|
+
return;
|
|
11132
|
+
}
|
|
11133
|
+
if (e.key === "Tab" && suggestionIndex >= 0) {
|
|
11134
|
+
e.preventDefault();
|
|
11135
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
11136
|
+
return;
|
|
11137
|
+
}
|
|
11138
|
+
if (e.key === "Enter" && suggestionIndex >= 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey) {
|
|
11139
|
+
e.preventDefault();
|
|
11140
|
+
acceptSuggestion(promptSuggestions[suggestionIndex]);
|
|
11141
|
+
return;
|
|
11142
|
+
}
|
|
11143
|
+
}
|
|
10595
11144
|
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
|
10596
11145
|
e.preventDefault();
|
|
10597
11146
|
handlePrimarySubmit();
|
|
@@ -11249,7 +11798,7 @@ var AgentUI = ({
|
|
|
11249
11798
|
mt: -1,
|
|
11250
11799
|
maxWidth: 600
|
|
11251
11800
|
}, children: subtitle }),
|
|
11252
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { sx: {
|
|
11801
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { ref: promptAnchorRef, sx: {
|
|
11253
11802
|
width: "100%",
|
|
11254
11803
|
display: "flex",
|
|
11255
11804
|
flexDirection: "column",
|
|
@@ -11457,6 +12006,67 @@ var AgentUI = ({
|
|
|
11457
12006
|
) }) })
|
|
11458
12007
|
] })
|
|
11459
12008
|
] }),
|
|
12009
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
12010
|
+
import_material16.Popper,
|
|
12011
|
+
{
|
|
12012
|
+
open: suggestionsOpen,
|
|
12013
|
+
anchorEl: promptAnchorRef.current,
|
|
12014
|
+
placement: "bottom-start",
|
|
12015
|
+
style: { zIndex: 1300, width: promptAnchorRef.current?.offsetWidth },
|
|
12016
|
+
modifiers: [{ name: "offset", options: { offset: [0, 6] } }],
|
|
12017
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.ClickAwayListener, { onClickAway: () => setSuggestionsDismissed(true), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
12018
|
+
import_material16.Paper,
|
|
12019
|
+
{
|
|
12020
|
+
elevation: 6,
|
|
12021
|
+
sx: {
|
|
12022
|
+
bgcolor: "hsl(var(--card))",
|
|
12023
|
+
border: "1px solid hsl(var(--border))",
|
|
12024
|
+
borderRadius: 2,
|
|
12025
|
+
overflow: "hidden",
|
|
12026
|
+
maxHeight: 320,
|
|
12027
|
+
overflowY: "auto"
|
|
12028
|
+
},
|
|
12029
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.MenuList, { dense: true, disablePadding: true, children: promptSuggestions.map((s, i) => {
|
|
12030
|
+
const q = actionInput.trim();
|
|
12031
|
+
const lower = s.toLowerCase();
|
|
12032
|
+
const idx = q ? lower.indexOf(q.toLowerCase()) : -1;
|
|
12033
|
+
const before = idx >= 0 ? s.slice(0, idx) : s;
|
|
12034
|
+
const match = idx >= 0 ? s.slice(idx, idx + q.length) : "";
|
|
12035
|
+
const after = idx >= 0 ? s.slice(idx + q.length) : "";
|
|
12036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
12037
|
+
import_material16.MenuItem,
|
|
12038
|
+
{
|
|
12039
|
+
selected: i === suggestionIndex,
|
|
12040
|
+
onMouseEnter: () => setSuggestionIndex(i),
|
|
12041
|
+
onMouseDown: (e) => {
|
|
12042
|
+
e.preventDefault();
|
|
12043
|
+
acceptSuggestion(s);
|
|
12044
|
+
},
|
|
12045
|
+
sx: {
|
|
12046
|
+
fontSize: "0.88rem",
|
|
12047
|
+
color: "hsl(var(--foreground))",
|
|
12048
|
+
py: 0.75,
|
|
12049
|
+
px: 2,
|
|
12050
|
+
"&.Mui-selected, &.Mui-selected:hover": {
|
|
12051
|
+
bgcolor: "hsl(var(--muted) / 0.6)"
|
|
12052
|
+
}
|
|
12053
|
+
},
|
|
12054
|
+
children: [
|
|
12055
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.Search, { size: 14, style: { marginRight: 10, color: "hsl(var(--muted-foreground))", flexShrink: 0 } }),
|
|
12056
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { component: "span", sx: { whiteSpace: "normal", lineHeight: 1.4 }, children: [
|
|
12057
|
+
before,
|
|
12058
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { component: "span", sx: { fontWeight: 700, color: "hsl(var(--foreground))" }, children: match }),
|
|
12059
|
+
after
|
|
12060
|
+
] })
|
|
12061
|
+
]
|
|
12062
|
+
},
|
|
12063
|
+
s
|
|
12064
|
+
);
|
|
12065
|
+
}) })
|
|
12066
|
+
}
|
|
12067
|
+
) })
|
|
12068
|
+
}
|
|
12069
|
+
),
|
|
11460
12070
|
!hideAppPicker && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_material16.Box, { sx: {
|
|
11461
12071
|
display: "inline-flex",
|
|
11462
12072
|
flexWrap: "wrap",
|
|
@@ -11507,8 +12117,19 @@ var AgentUI = ({
|
|
|
11507
12117
|
"&:hover": { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted) / 0.5)" }
|
|
11508
12118
|
},
|
|
11509
12119
|
children: [
|
|
11510
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
11511
|
-
|
|
12120
|
+
detectedLLM?.logo ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
12121
|
+
import_material16.Box,
|
|
12122
|
+
{
|
|
12123
|
+
component: "img",
|
|
12124
|
+
src: detectedLLM.logo,
|
|
12125
|
+
alt: "",
|
|
12126
|
+
sx: { width: 14, height: 14, borderRadius: "3px", objectFit: "contain", display: "block" },
|
|
12127
|
+
onError: (e) => {
|
|
12128
|
+
e.currentTarget.style.display = "none";
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12131
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react11.Settings, { size: 14 }),
|
|
12132
|
+
detectedLLM?.label || "Choose LLM"
|
|
11512
12133
|
]
|
|
11513
12134
|
}
|
|
11514
12135
|
) }),
|
|
@@ -11742,7 +12363,7 @@ var AgentUI = ({
|
|
|
11742
12363
|
AgentRunDiagnosisBanner_default,
|
|
11743
12364
|
{
|
|
11744
12365
|
run: execution?.results?.length ? execution : agentData,
|
|
11745
|
-
sx: { px:
|
|
12366
|
+
sx: { px: 1.5, pb: 0, mb: 2 },
|
|
11746
12367
|
executionId: execution?.execution_id,
|
|
11747
12368
|
onJumpToEvidence: (decisionIndex) => {
|
|
11748
12369
|
const dec = (agentData?.decisions || [])[decisionIndex];
|
|
@@ -11967,14 +12588,14 @@ var AgentUI = ({
|
|
|
11967
12588
|
] })
|
|
11968
12589
|
] });
|
|
11969
12590
|
})() : !finishAnswer && isRunning ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Typography, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "Waiting for the agent to produce the first step." }) : !finishAnswer ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Typography, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "No final answer was returned. Open Detailed to inspect each step." }) : null,
|
|
11970
|
-
|
|
12591
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_material16.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
11971
12592
|
import_material16.Button,
|
|
11972
12593
|
{
|
|
11973
12594
|
size: "small",
|
|
11974
12595
|
variant: "text",
|
|
11975
12596
|
onClick: () => setViewMode("detailed"),
|
|
11976
12597
|
sx: { color: "hsl(var(--primary))", textTransform: "none", px: 0 },
|
|
11977
|
-
children: "View detailed timeline \u2192"
|
|
12598
|
+
children: isRunning ? "View live detailed timeline \u2192" : "View detailed timeline \u2192"
|
|
11978
12599
|
}
|
|
11979
12600
|
) })
|
|
11980
12601
|
] });
|
|
@@ -12255,8 +12876,6 @@ var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
|
12255
12876
|
var import_react17 = require("react");
|
|
12256
12877
|
var OPENAI_APP_NAME = "OpenAI";
|
|
12257
12878
|
var OPENAI_APP_ID = "5d19dd82517870c68d40cacad9b5ca91";
|
|
12258
|
-
var SHUFFLE_AI_PRESET = "Shuffle AI";
|
|
12259
|
-
var CUSTOM_PRESET = "Custom / self-hosted";
|
|
12260
12879
|
var OPENAI_ALGOLIA_APP = {
|
|
12261
12880
|
name: OPENAI_APP_NAME,
|
|
12262
12881
|
description: "OpenAI-compatible LLM endpoint for agent operations",
|
|
@@ -12276,20 +12895,32 @@ var OPENAI_ALGOLIA_APP = {
|
|
|
12276
12895
|
triggers: [],
|
|
12277
12896
|
verified: true
|
|
12278
12897
|
};
|
|
12279
|
-
var
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
|
|
12898
|
+
var CUSTOM_MODEL = "Custom\u2026";
|
|
12899
|
+
var PROVIDER_MODELS = {
|
|
12900
|
+
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"],
|
|
12901
|
+
Anthropic: ["claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5", "claude-opus-4", "claude-sonnet-4", "claude-3-7-sonnet-latest"],
|
|
12902
|
+
"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"],
|
|
12903
|
+
Mistral: ["mistral-large-2026", "mistral-medium-3", "mistral-small-3.2", "codestral-2026", "magistral-medium-2026", "ministral-8b-latest"],
|
|
12904
|
+
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"],
|
|
12905
|
+
DeepSeek: ["deepseek-v3.5", "deepseek-v3", "deepseek-r1", "deepseek-coder-v3"],
|
|
12906
|
+
"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"],
|
|
12907
|
+
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"],
|
|
12908
|
+
"Ollama (localhost)": ["llama3.3", "llama3.2", "qwen3", "qwen3:32b", "deepseek-r1", "deepseek-r1:70b", "mistral-small3", "phi4", "gemma3"],
|
|
12909
|
+
"LM Studio (localhost)": ["llama-3.3-70b-instruct", "qwen3-32b", "deepseek-r1-distill-qwen-32b", "mistral-small-3", "phi-4", "gemma-3-27b"]
|
|
12910
|
+
};
|
|
12911
|
+
var ProviderLogo = ({ label, url }) => {
|
|
12912
|
+
const [errored, setErrored] = (0, import_react16.useState)(false);
|
|
12913
|
+
let domain = PROVIDER_DOMAINS[label];
|
|
12914
|
+
if (!domain && url) {
|
|
12915
|
+
try {
|
|
12916
|
+
domain = new URL(url).hostname.replace(/^www\./, "");
|
|
12917
|
+
} catch {
|
|
12918
|
+
}
|
|
12919
|
+
}
|
|
12920
|
+
const src = domain ? `https://www.google.com/s2/favicons?domain=${domain}&sz=64` : "";
|
|
12921
|
+
const initial = label.trim().charAt(0).toUpperCase() || "?";
|
|
12922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Box, { sx: { width: 18, height: 18, borderRadius: "4px", display: "flex", alignItems: "center", justifyContent: "center", bgcolor: "hsl(var(--muted))", overflow: "hidden", flexShrink: 0 }, children: src && !errored ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src, alt: "", width: 18, height: 18, style: { display: "block" }, onError: () => setErrored(true) }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { sx: { fontSize: "0.65rem", fontWeight: 600, color: "hsl(var(--muted-foreground))", lineHeight: 1 }, children: initial }) });
|
|
12923
|
+
};
|
|
12293
12924
|
var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode }) => {
|
|
12294
12925
|
useSyncHostBaseUrl(globalUrl);
|
|
12295
12926
|
const { authStates, authenticatedApps, handleAuthChange, handleTestConnection, handleSaveAuth, refreshAuth } = useAppAuth();
|
|
@@ -12305,46 +12936,16 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12305
12936
|
status: "pending",
|
|
12306
12937
|
credentials: {}
|
|
12307
12938
|
};
|
|
12308
|
-
const
|
|
12309
|
-
const
|
|
12310
|
-
(0, import_react16.
|
|
12311
|
-
|
|
12312
|
-
const failedEntries = openaiEntries.filter((e) => e.validation && e.validation.valid === false && e.id);
|
|
12313
|
-
if (failedEntries.length === 0) return;
|
|
12314
|
-
let cancelled = false;
|
|
12315
|
-
(async () => {
|
|
12316
|
-
let deletedAny = false;
|
|
12317
|
-
for (const entry of failedEntries) {
|
|
12318
|
-
const id = entry.id;
|
|
12319
|
-
if (attemptedDeletionRef.current.has(id)) continue;
|
|
12320
|
-
attemptedDeletionRef.current.add(id);
|
|
12321
|
-
try {
|
|
12322
|
-
const resp = await fetch(getApiUrl(`/api/v1/apps/authentication/${id}`), {
|
|
12323
|
-
method: "DELETE",
|
|
12324
|
-
credentials: "include",
|
|
12325
|
-
headers: { ...getAuthHeader() }
|
|
12326
|
-
});
|
|
12327
|
-
if (resp.ok) deletedAny = true;
|
|
12328
|
-
} catch (err) {
|
|
12329
|
-
console.error("[LocalLLMConfig] Failed to auto-delete failed OpenAI auth:", err);
|
|
12330
|
-
}
|
|
12331
|
-
}
|
|
12332
|
-
if (!cancelled && deletedAny) {
|
|
12333
|
-
await refreshAuth();
|
|
12334
|
-
refreshAllIntegrationStatus();
|
|
12335
|
-
}
|
|
12336
|
-
})();
|
|
12337
|
-
return () => {
|
|
12338
|
-
cancelled = true;
|
|
12339
|
-
};
|
|
12340
|
-
}, [openaiEntries, authState.status, refreshAuth]);
|
|
12939
|
+
const savedUrlFromEntry = (openaiEntries[0]?.fields || []).find((f) => (f?.key || "").toLowerCase() === "url")?.value || "";
|
|
12940
|
+
const currentUrl = (authState.credentials?.url || savedUrlFromEntry || "").trim();
|
|
12941
|
+
const [customModel, setCustomModel] = (0, import_react16.useState)("");
|
|
12942
|
+
const [customMode, setCustomMode] = (0, import_react16.useState)(false);
|
|
12341
12943
|
const hasOpenAIEntries = openaiEntries.length > 0;
|
|
12342
12944
|
const effectivePreset = (0, import_react16.useMemo)(() => {
|
|
12343
12945
|
if (selectedPreset) return selectedPreset;
|
|
12344
12946
|
if (!currentUrl && !hasOpenAIEntries) return SHUFFLE_AI_PRESET;
|
|
12345
12947
|
if (!currentUrl) return "";
|
|
12346
|
-
|
|
12347
|
-
return match ? match.label : CUSTOM_PRESET;
|
|
12948
|
+
return detectLLMProvider(currentUrl)?.label || CUSTOM_PRESET;
|
|
12348
12949
|
}, [selectedPreset, currentUrl, hasOpenAIEntries]);
|
|
12349
12950
|
const applyShuffleAI = async () => {
|
|
12350
12951
|
let deletedAny = false;
|
|
@@ -12381,7 +12982,16 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12381
12982
|
setSelectedPreset(label);
|
|
12382
12983
|
const preset = ENDPOINT_PRESETS.find((p) => p.label === label);
|
|
12383
12984
|
if (!preset) return;
|
|
12384
|
-
|
|
12985
|
+
const topModel = PROVIDER_MODELS[label]?.[0] || "";
|
|
12986
|
+
const existingModel = authState.credentials?.model || "";
|
|
12987
|
+
const nextModel = topModel || existingModel;
|
|
12988
|
+
setCustomMode(false);
|
|
12989
|
+
setCustomModel("");
|
|
12990
|
+
handleAuthChange(OPENAI_APP_ID, {
|
|
12991
|
+
...authState.credentials,
|
|
12992
|
+
url: preset.label === CUSTOM_PRESET ? customUrl : preset.url,
|
|
12993
|
+
...nextModel ? { model: nextModel } : {}
|
|
12994
|
+
});
|
|
12385
12995
|
};
|
|
12386
12996
|
const handleCustomUrlChange = (value) => {
|
|
12387
12997
|
setCustomUrl(value);
|
|
@@ -12433,14 +13043,30 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12433
13043
|
isOptionEqualToValue: (opt, val) => opt === val,
|
|
12434
13044
|
renderOption: (props, option) => {
|
|
12435
13045
|
const preset = ENDPOINT_PRESETS.find((p) => p.label === option);
|
|
12436
|
-
return /* @__PURE__ */ (0, import_react17.createElement)("li", { ...props, key: option }, /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 1, width: "100%", minWidth: 0 }, children: [
|
|
13046
|
+
return /* @__PURE__ */ (0, import_react17.createElement)("li", { ...props, key: option }, /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 1.25, width: "100%", minWidth: 0 }, children: [
|
|
13047
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ProviderLogo, { label: option, url: preset?.url }),
|
|
12437
13048
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { sx: { fontSize: "0.85rem", color: "hsl(var(--popover-foreground))" }, children: option }),
|
|
12438
13049
|
preset?.url && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { component: "span", sx: { ml: "auto", color: "hsl(var(--muted-foreground))", fontSize: "0.75rem", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: preset.url })
|
|
12439
13050
|
] }));
|
|
12440
13051
|
},
|
|
12441
|
-
renderInput: (params) =>
|
|
13052
|
+
renderInput: (params) => {
|
|
13053
|
+
const preset = ENDPOINT_PRESETS.find((p) => p.label === effectivePreset);
|
|
13054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
13055
|
+
import_material18.TextField,
|
|
13056
|
+
{
|
|
13057
|
+
...params,
|
|
13058
|
+
placeholder: "Search a provider\u2026",
|
|
13059
|
+
slotProps: {
|
|
13060
|
+
input: {
|
|
13061
|
+
...params.InputProps,
|
|
13062
|
+
startAdornment: effectivePreset ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Box, { sx: { display: "flex", alignItems: "center", pl: 0.5, mr: 0.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ProviderLogo, { label: effectivePreset, url: preset?.url }) }) : void 0
|
|
13063
|
+
}
|
|
13064
|
+
}
|
|
13065
|
+
}
|
|
13066
|
+
);
|
|
13067
|
+
},
|
|
12442
13068
|
slotProps: {
|
|
12443
|
-
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
13069
|
+
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))", minWidth: 580 } },
|
|
12444
13070
|
popper: { sx: { zIndex: 9999 } }
|
|
12445
13071
|
}
|
|
12446
13072
|
}
|
|
@@ -12503,6 +13129,59 @@ var LocalLLMConfig = ({ compact, globalUrl, userdata, isLoaded, isLoggedIn, serv
|
|
|
12503
13129
|
hideDocsLink: true,
|
|
12504
13130
|
hideUrlFields: true,
|
|
12505
13131
|
borderless: true,
|
|
13132
|
+
compactAuthForm: true,
|
|
13133
|
+
extraFieldsSlot: (PROVIDER_MODELS[effectivePreset]?.length ?? 0) > 0 ? ({ credentials, setField }) => {
|
|
13134
|
+
const liveModel = credentials.model || "";
|
|
13135
|
+
const presetModels = PROVIDER_MODELS[effectivePreset] || [];
|
|
13136
|
+
const liveIsCustom = liveModel !== "" && !presetModels.includes(liveModel);
|
|
13137
|
+
const showCustom = customMode || liveIsCustom;
|
|
13138
|
+
const liveSelectValue = showCustom ? CUSTOM_MODEL : liveModel || null;
|
|
13139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", flexDirection: "column", gap: 1 }, children: [
|
|
13140
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Typography, { sx: { fontSize: "0.85rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: "Model" }),
|
|
13141
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
13142
|
+
import_material18.Autocomplete,
|
|
13143
|
+
{
|
|
13144
|
+
size: "small",
|
|
13145
|
+
fullWidth: true,
|
|
13146
|
+
disableClearable: true,
|
|
13147
|
+
options: [...presetModels, CUSTOM_MODEL],
|
|
13148
|
+
value: liveSelectValue,
|
|
13149
|
+
onChange: (_e, val) => {
|
|
13150
|
+
if (!val) return;
|
|
13151
|
+
if (val === CUSTOM_MODEL) {
|
|
13152
|
+
setCustomMode(true);
|
|
13153
|
+
setField("model", customModel);
|
|
13154
|
+
} else {
|
|
13155
|
+
setCustomMode(false);
|
|
13156
|
+
setCustomModel("");
|
|
13157
|
+
setField("model", val);
|
|
13158
|
+
}
|
|
13159
|
+
},
|
|
13160
|
+
isOptionEqualToValue: (opt, val) => opt === val,
|
|
13161
|
+
slotProps: {
|
|
13162
|
+
paper: { sx: { bgcolor: "hsl(var(--popover))", color: "hsl(var(--popover-foreground))", border: "1px solid hsl(var(--border))" } },
|
|
13163
|
+
popper: { sx: { zIndex: 9999 } }
|
|
13164
|
+
},
|
|
13165
|
+
renderInput: (params) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.TextField, { ...params, placeholder: "Select a model\u2026" })
|
|
13166
|
+
}
|
|
13167
|
+
),
|
|
13168
|
+
showCustom && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
13169
|
+
import_material18.TextField,
|
|
13170
|
+
{
|
|
13171
|
+
size: "small",
|
|
13172
|
+
fullWidth: true,
|
|
13173
|
+
placeholder: "Enter a custom model identifier",
|
|
13174
|
+
value: customModel || (liveIsCustom ? liveModel : ""),
|
|
13175
|
+
onChange: (e) => {
|
|
13176
|
+
setCustomModel(e.target.value);
|
|
13177
|
+
setField("model", e.target.value);
|
|
13178
|
+
},
|
|
13179
|
+
helperText: "Exact model name as expected by the provider's API",
|
|
13180
|
+
sx: { "& .MuiFormHelperText-root": { color: "hsl(var(--muted-foreground))" } }
|
|
13181
|
+
}
|
|
13182
|
+
)
|
|
13183
|
+
] });
|
|
13184
|
+
} : void 0,
|
|
12506
13185
|
globalUrl,
|
|
12507
13186
|
userdata,
|
|
12508
13187
|
isLoaded,
|
|
@@ -12580,9 +13259,16 @@ var AgentRunDrawer = ({
|
|
|
12580
13259
|
setActiveTab("localLLM");
|
|
12581
13260
|
}
|
|
12582
13261
|
};
|
|
13262
|
+
const onClose2 = () => {
|
|
13263
|
+
onClose();
|
|
13264
|
+
};
|
|
12583
13265
|
window.addEventListener("agent-drawer-open", onOpen);
|
|
12584
|
-
|
|
12585
|
-
|
|
13266
|
+
window.addEventListener("agent-drawer-close", onClose2);
|
|
13267
|
+
return () => {
|
|
13268
|
+
window.removeEventListener("agent-drawer-open", onOpen);
|
|
13269
|
+
window.removeEventListener("agent-drawer-close", onClose2);
|
|
13270
|
+
};
|
|
13271
|
+
}, [onClose]);
|
|
12586
13272
|
const effectiveLocalLLMSlot = localLLMSlot ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
12587
13273
|
LocalLLMConfig_default,
|
|
12588
13274
|
{
|
|
@@ -13054,7 +13740,7 @@ var STATUS_CONFIG = {
|
|
|
13054
13740
|
EXECUTING: { icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Loader2, { size: 16 }), color: "hsl(var(--severity-medium, 38 92% 50%))", label: "Running" },
|
|
13055
13741
|
RUNNING: { icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Loader2, { size: 16 }), color: "hsl(var(--severity-medium, 38 92% 50%))", label: "Running" },
|
|
13056
13742
|
WAITING: { icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Clock, { size: 16 }), color: "hsl(var(--severity-info, 217 91% 60%))", label: "Waiting" },
|
|
13057
|
-
LIMIT_REACHED: { icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.AlertTriangle, { size: 16 }), color: "hsl(var(--severity-
|
|
13743
|
+
LIMIT_REACHED: { icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.AlertTriangle, { size: 16 }), color: "hsl(var(--severity-critical, 0 72% 55%))", label: "Limit reached" }
|
|
13058
13744
|
};
|
|
13059
13745
|
var getEffectiveStatus = (run) => {
|
|
13060
13746
|
const raw = (run.status || "").toUpperCase();
|
|
@@ -13067,21 +13753,126 @@ var getEffectiveStatus = (run) => {
|
|
|
13067
13753
|
}
|
|
13068
13754
|
return raw;
|
|
13069
13755
|
};
|
|
13070
|
-
var
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
if (arg
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13756
|
+
var SOURCE_ICON_SIZE = 18;
|
|
13757
|
+
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());
|
|
13758
|
+
var DATASTORE_KEY_RE = /\bKey:\s*(\S+)/i;
|
|
13759
|
+
var DATASTORE_CATEGORY_RE = /\bCategory:\s*(\S+)/i;
|
|
13760
|
+
var parseDatastoreTask = (arg) => {
|
|
13761
|
+
if (!arg) return null;
|
|
13762
|
+
const k = arg.match(DATASTORE_KEY_RE);
|
|
13763
|
+
const c = arg.match(DATASTORE_CATEGORY_RE);
|
|
13764
|
+
if (!k || !c) return null;
|
|
13765
|
+
const key = (k[1] || "").trim();
|
|
13766
|
+
const category = (c[1] || "").trim();
|
|
13767
|
+
if (!key || !category) return null;
|
|
13768
|
+
return { key, category };
|
|
13769
|
+
};
|
|
13770
|
+
var isAIAgentResult = (result) => String(result?.action?.app_name || "").trim().toLowerCase() === "ai agent";
|
|
13771
|
+
var getAIAgentResultPayload = (run) => {
|
|
13772
|
+
const results = Array.isArray(run.results) ? run.results : [];
|
|
13773
|
+
const agentResult = results.find(isAIAgentResult);
|
|
13774
|
+
if (!agentResult || typeof agentResult !== "object" || !("result" in agentResult)) return null;
|
|
13775
|
+
return tryParseJson(agentResult.result);
|
|
13776
|
+
};
|
|
13777
|
+
var getDirectAgentInput = (payload) => {
|
|
13778
|
+
if (!payload || typeof payload !== "object") return null;
|
|
13779
|
+
const obj = payload;
|
|
13780
|
+
if (typeof obj.original_input === "string" && obj.original_input.trim()) {
|
|
13781
|
+
return obj.original_input.trim();
|
|
13782
|
+
}
|
|
13783
|
+
if (typeof obj.input === "string" && obj.input.trim()) {
|
|
13784
|
+
return obj.input.trim();
|
|
13785
|
+
}
|
|
13786
|
+
return null;
|
|
13787
|
+
};
|
|
13788
|
+
var findDatastoreTaskInRun = (run) => {
|
|
13789
|
+
const agentInput = getDirectAgentInput(getAIAgentResultPayload(run));
|
|
13790
|
+
const agentHit = parseDatastoreTask(agentInput || void 0);
|
|
13791
|
+
if (agentHit) return agentHit;
|
|
13792
|
+
const anyRun = run;
|
|
13793
|
+
const candidates = [];
|
|
13794
|
+
if (typeof anyRun.original_input === "string") candidates.push(anyRun.original_input);
|
|
13795
|
+
if (typeof anyRun.input === "string") candidates.push(anyRun.input);
|
|
13796
|
+
if (run.execution_argument) candidates.push(run.execution_argument);
|
|
13797
|
+
if (run.result) candidates.push(run.result);
|
|
13798
|
+
if (Array.isArray(anyRun.results)) {
|
|
13799
|
+
try {
|
|
13800
|
+
candidates.push(JSON.stringify(anyRun.results));
|
|
13801
|
+
} catch {
|
|
13802
|
+
}
|
|
13803
|
+
}
|
|
13804
|
+
for (const c of candidates) {
|
|
13805
|
+
const hit = parseDatastoreTask(c);
|
|
13806
|
+
if (hit) return hit;
|
|
13807
|
+
}
|
|
13808
|
+
return null;
|
|
13809
|
+
};
|
|
13810
|
+
var classifyRunSource = (run) => {
|
|
13811
|
+
const raw = (run.execution_source || "").trim();
|
|
13812
|
+
const src = raw.toLowerCase();
|
|
13813
|
+
const ds = findDatastoreTaskInRun(run);
|
|
13814
|
+
if (ds || src.includes("datastore") || src.includes("enrichment") || src.includes("automation")) {
|
|
13815
|
+
return {
|
|
13816
|
+
kind: "datastore",
|
|
13817
|
+
label: "Datastore automation",
|
|
13818
|
+
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).",
|
|
13819
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Database, { size: SOURCE_ICON_SIZE }),
|
|
13820
|
+
datastoreKey: ds?.key,
|
|
13821
|
+
datastoreCategory: ds?.category
|
|
13822
|
+
};
|
|
13823
|
+
}
|
|
13824
|
+
if (src.includes("schedule") || src.includes("cron")) {
|
|
13825
|
+
return {
|
|
13826
|
+
kind: "schedule",
|
|
13827
|
+
label: "Schedule",
|
|
13828
|
+
reason: "Started by a scheduled trigger (cron).",
|
|
13829
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Clock, { size: SOURCE_ICON_SIZE })
|
|
13830
|
+
};
|
|
13831
|
+
}
|
|
13832
|
+
if (src.includes("webhook") || src.includes("http")) {
|
|
13833
|
+
return {
|
|
13834
|
+
kind: "webhook",
|
|
13835
|
+
label: "Webhook",
|
|
13836
|
+
reason: "Started by an incoming webhook / HTTP trigger.",
|
|
13837
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Globe, { size: SOURCE_ICON_SIZE })
|
|
13838
|
+
};
|
|
13839
|
+
}
|
|
13840
|
+
if (src.includes("form")) {
|
|
13841
|
+
return {
|
|
13842
|
+
kind: "form",
|
|
13843
|
+
label: "Form",
|
|
13844
|
+
reason: "Started by a form submission.",
|
|
13845
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.FileText, { size: SOURCE_ICON_SIZE })
|
|
13846
|
+
};
|
|
13847
|
+
}
|
|
13848
|
+
if (raw && looksLikeExecutionId(raw)) {
|
|
13849
|
+
return {
|
|
13850
|
+
kind: "workflow",
|
|
13851
|
+
label: "Workflow",
|
|
13852
|
+
reason: "Started by another workflow as a subflow.",
|
|
13853
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Workflow, { size: SOURCE_ICON_SIZE })
|
|
13854
|
+
};
|
|
13855
|
+
}
|
|
13856
|
+
if (src === "" || src === "manual" || src === "default" || src === "demo") {
|
|
13857
|
+
return {
|
|
13858
|
+
kind: "manual",
|
|
13859
|
+
label: "Manual",
|
|
13860
|
+
reason: "Started manually from the Agents UI.",
|
|
13861
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Hand, { size: SOURCE_ICON_SIZE })
|
|
13862
|
+
};
|
|
13863
|
+
}
|
|
13864
|
+
return {
|
|
13865
|
+
kind: "unknown",
|
|
13866
|
+
label: raw || "Unknown",
|
|
13867
|
+
reason: raw ? `Started by "${raw}".` : "Trigger source unknown.",
|
|
13868
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react13.Zap, { size: SOURCE_ICON_SIZE })
|
|
13869
|
+
};
|
|
13079
13870
|
};
|
|
13080
13871
|
var getRunIconColor = (run) => {
|
|
13081
13872
|
const status = getEffectiveStatus(run);
|
|
13082
13873
|
if (status === "FINISHED" || status === "SUCCESS") return "hsl(var(--severity-low, 142 71% 45%))";
|
|
13083
13874
|
if (status === "FAILED" || status === "ABORTED") return "hsl(var(--severity-critical, 0 72% 55%))";
|
|
13084
|
-
if (status === "LIMIT_REACHED") return "hsl(var(--severity-
|
|
13875
|
+
if (status === "LIMIT_REACHED") return "hsl(var(--severity-critical, 0 72% 55%))";
|
|
13085
13876
|
if (status === "EXECUTING" || status === "RUNNING") return "hsl(var(--severity-medium, 38 92% 50%))";
|
|
13086
13877
|
return "hsl(var(--primary, 24 100% 50%))";
|
|
13087
13878
|
};
|
|
@@ -13179,9 +13970,12 @@ var tryParseJson = (s) => {
|
|
|
13179
13970
|
}
|
|
13180
13971
|
};
|
|
13181
13972
|
var getRunPrompt = (run) => {
|
|
13182
|
-
const
|
|
13973
|
+
const anyRun = run;
|
|
13974
|
+
const agentInput = getDirectAgentInput(getAIAgentResultPayload(run));
|
|
13975
|
+
if (agentInput) return agentInput;
|
|
13976
|
+
const results = Array.isArray(anyRun.results) ? anyRun.results : null;
|
|
13183
13977
|
if (results) {
|
|
13184
|
-
const agentResult = results.find(
|
|
13978
|
+
const agentResult = results.find(isAIAgentResult);
|
|
13185
13979
|
if (agentResult?.result) {
|
|
13186
13980
|
const hit = deepFindPrompt(tryParseJson(agentResult.result));
|
|
13187
13981
|
if (hit) return hit;
|
|
@@ -13192,6 +13986,12 @@ var getRunPrompt = (run) => {
|
|
|
13192
13986
|
if (hit) return hit;
|
|
13193
13987
|
}
|
|
13194
13988
|
}
|
|
13989
|
+
if (typeof anyRun.original_input === "string" && anyRun.original_input.trim()) {
|
|
13990
|
+
return anyRun.original_input.trim();
|
|
13991
|
+
}
|
|
13992
|
+
if (typeof anyRun.input === "string" && anyRun.input.trim()) {
|
|
13993
|
+
return anyRun.input.trim();
|
|
13994
|
+
}
|
|
13195
13995
|
if (run.result) {
|
|
13196
13996
|
const hit = deepFindPrompt(tryParseJson(run.result));
|
|
13197
13997
|
if (hit) return hit;
|
|
@@ -13232,7 +14032,9 @@ var getRunSubtitle = (run) => {
|
|
|
13232
14032
|
if (run.result.length < 120) return run.result;
|
|
13233
14033
|
}
|
|
13234
14034
|
}
|
|
13235
|
-
|
|
14035
|
+
const status = getEffectiveStatus(run);
|
|
14036
|
+
const isRunning = status === "EXECUTING" || status === "RUNNING" || status === "WAITING";
|
|
14037
|
+
return run.execution_source || (isRunning ? "Agent still running\u2026" : "Agent execution");
|
|
13236
14038
|
};
|
|
13237
14039
|
var normalizeResultStatus = (s) => {
|
|
13238
14040
|
const v = (s || "").toUpperCase();
|
|
@@ -13334,41 +14136,60 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13334
14136
|
...Array.isArray(sx) ? sx : sx ? [sx] : []
|
|
13335
14137
|
],
|
|
13336
14138
|
children: [
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
{
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
13343
|
-
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
14139
|
+
(() => {
|
|
14140
|
+
const sourceInfo = classifyRunSource(run);
|
|
14141
|
+
const dsLink = sourceInfo.kind === "datastore" && sourceInfo.datastoreKey && sourceInfo.datastoreCategory ? `https://shuffler.io/admin?tab=datastore&category=${encodeURIComponent(sourceInfo.datastoreCategory)}&key=${encodeURIComponent(sourceInfo.datastoreKey)}` : null;
|
|
14142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
14143
|
+
import_material20.Tooltip,
|
|
14144
|
+
{
|
|
14145
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material20.Box, { sx: { lineHeight: 1.4 }, children: [
|
|
14146
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material20.Box, { sx: { fontWeight: 600 }, children: sourceInfo.label }),
|
|
14147
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material20.Box, { sx: { opacity: 0.85 }, children: sourceInfo.reason })
|
|
14148
|
+
] }),
|
|
14149
|
+
placement: "top",
|
|
14150
|
+
arrow: true,
|
|
14151
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
14152
|
+
import_material20.Box,
|
|
14153
|
+
{
|
|
14154
|
+
onClick: dsLink ? (e) => {
|
|
14155
|
+
e.stopPropagation();
|
|
14156
|
+
window.open(dsLink, "_blank", "noopener,noreferrer");
|
|
14157
|
+
} : void 0,
|
|
14158
|
+
sx: {
|
|
14159
|
+
width: 40,
|
|
14160
|
+
height: 40,
|
|
14161
|
+
borderRadius: "50%",
|
|
14162
|
+
display: "flex",
|
|
14163
|
+
alignItems: "center",
|
|
14164
|
+
justifyContent: "center",
|
|
14165
|
+
bgcolor: `${iconColor}15`,
|
|
14166
|
+
color: iconColor,
|
|
14167
|
+
flexShrink: 0,
|
|
14168
|
+
cursor: dsLink ? "pointer" : "inherit",
|
|
14169
|
+
transition: "background 0.15s ease",
|
|
14170
|
+
"&:hover": dsLink ? { bgcolor: `${iconColor}30` } : void 0
|
|
14171
|
+
},
|
|
14172
|
+
children: sourceInfo.icon
|
|
14173
|
+
}
|
|
14174
|
+
)
|
|
14175
|
+
}
|
|
14176
|
+
);
|
|
14177
|
+
})(),
|
|
13354
14178
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_material20.Box, { sx: { flex: 1, minWidth: 0 }, children: [
|
|
13355
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
{
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
),
|
|
13370
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material20.Box, { sx: { display: "flex", alignItems: "center", color: cfg.color, flexShrink: 0 }, children: cfg.icon })
|
|
13371
|
-
] }),
|
|
14179
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_material20.Box, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 0.25 }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
14180
|
+
import_material20.Typography,
|
|
14181
|
+
{
|
|
14182
|
+
sx: {
|
|
14183
|
+
fontSize: "0.9rem",
|
|
14184
|
+
fontWeight: 500,
|
|
14185
|
+
color: "hsl(var(--foreground))",
|
|
14186
|
+
overflow: "hidden",
|
|
14187
|
+
textOverflow: "ellipsis",
|
|
14188
|
+
whiteSpace: "nowrap"
|
|
14189
|
+
},
|
|
14190
|
+
children: getRunTitle(run)
|
|
14191
|
+
}
|
|
14192
|
+
) }),
|
|
13372
14193
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13373
14194
|
import_material20.Typography,
|
|
13374
14195
|
{
|
|
@@ -13401,17 +14222,20 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13401
14222
|
] })
|
|
13402
14223
|
] })
|
|
13403
14224
|
] }),
|
|
13404
|
-
|
|
14225
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13405
14226
|
import_material20.Box,
|
|
13406
14227
|
{
|
|
13407
14228
|
onClick: (e) => e.stopPropagation(),
|
|
13408
14229
|
sx: {
|
|
13409
14230
|
display: { xs: "none", sm: "flex" },
|
|
13410
14231
|
alignItems: "center",
|
|
14232
|
+
justifyContent: "flex-end",
|
|
13411
14233
|
flexShrink: 0,
|
|
13412
|
-
ml: 1
|
|
14234
|
+
ml: 1,
|
|
14235
|
+
width: 140,
|
|
14236
|
+
minHeight: 28
|
|
13413
14237
|
},
|
|
13414
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
14238
|
+
children: tools.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
13415
14239
|
import_material20.AvatarGroup,
|
|
13416
14240
|
{
|
|
13417
14241
|
max: 5,
|
|
@@ -13460,7 +14284,7 @@ var AgentRunRow = ({ run, onClick, sx, appIcons, onAppClick }) => {
|
|
|
13460
14284
|
) }, t.name);
|
|
13461
14285
|
})
|
|
13462
14286
|
}
|
|
13463
|
-
)
|
|
14287
|
+
) : null
|
|
13464
14288
|
}
|
|
13465
14289
|
)
|
|
13466
14290
|
]
|
|
@@ -14281,6 +15105,15 @@ var AgentsView = ({
|
|
|
14281
15105
|
open: false,
|
|
14282
15106
|
tab: "localLLM"
|
|
14283
15107
|
});
|
|
15108
|
+
(0, import_react20.useEffect)(() => {
|
|
15109
|
+
if (typeof window === "undefined") return;
|
|
15110
|
+
const handler = (e) => {
|
|
15111
|
+
const detail = e.detail;
|
|
15112
|
+
setBuiltInDrawer({ open: true, tab: detail?.tab ?? "localLLM" });
|
|
15113
|
+
};
|
|
15114
|
+
window.addEventListener("agent-drawer-open", handler);
|
|
15115
|
+
return () => window.removeEventListener("agent-drawer-open", handler);
|
|
15116
|
+
}, []);
|
|
14284
15117
|
const effectiveSchedule = (0, import_react20.useCallback)(
|
|
14285
15118
|
async (info) => {
|
|
14286
15119
|
if (onSchedule) return onSchedule(info);
|
|
@@ -14677,7 +15510,9 @@ var LocalLLMConfig2 = withMcpTheme(LocalLLMConfig_default, "LocalLLMConfig");
|
|
|
14677
15510
|
deleteDatastoreItem,
|
|
14678
15511
|
deleteDatastoreItems,
|
|
14679
15512
|
diagnoseOutputWarning,
|
|
15513
|
+
extractActionAppNames,
|
|
14680
15514
|
extractValidatedIngestionApps,
|
|
15515
|
+
extractWorkflowActionAppNames,
|
|
14681
15516
|
extractWorkflowAppNames,
|
|
14682
15517
|
fetchApps,
|
|
14683
15518
|
fetchAppsViaApiConfig,
|