@shuffleio/shuffle-mcps 0.0.57 → 0.0.59

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.js CHANGED
@@ -3638,6 +3638,7 @@ var deleteDatastoreItems = async (keys2, category) => {
3638
3638
  };
3639
3639
  var DATASTORE_CATEGORIES = {
3640
3640
  INCIDENTS: "shuffle-security_incidents",
3641
+ EVENTS: "shuffle-security_events",
3641
3642
  VULNERABILITIES: "shuffle-security_vulns",
3642
3643
  VULNS: "shuffle-security_vulns",
3643
3644
  ASSETS: "shuffle-security_assets",
@@ -4273,7 +4274,7 @@ var applyValidationStaleness = (data) => {
4273
4274
  });
4274
4275
  };
4275
4276
  var doFetch3 = async (crossOrgId) => {
4276
- if (!hasShuffleAuth()) return [];
4277
+ if (!hasShuffleAuth()) return { data: [], failed: false };
4277
4278
  const headers = {
4278
4279
  ...getAuthHeader(crossOrgId ?? void 0)
4279
4280
  };
@@ -4282,12 +4283,13 @@ var doFetch3 = async (crossOrgId) => {
4282
4283
  credentials: "include",
4283
4284
  headers
4284
4285
  });
4285
- if (!resp.ok) return [];
4286
+ if (!resp.ok) return { data: [], failed: true };
4286
4287
  const result = await resp.json();
4287
4288
  const data = result?.data || result;
4288
- return Array.isArray(data) ? applyValidationStaleness(data) : [];
4289
+ if (!Array.isArray(data)) return { data: [], failed: true };
4290
+ return { data: applyValidationStaleness(data), failed: false };
4289
4291
  } catch {
4290
- return [];
4292
+ return { data: [], failed: true };
4291
4293
  }
4292
4294
  };
4293
4295
  var fetchAuthenticatedApps = (crossOrgId) => {
@@ -4297,12 +4299,17 @@ var fetchAuthenticatedApps = (crossOrgId) => {
4297
4299
  return Promise.resolve(entry.data);
4298
4300
  }
4299
4301
  if (entry.promise) return entry.promise;
4300
- const promise = doFetch3(crossOrgId).then((data) => {
4301
- cache3.set(key, { data, fetchedAt: Date.now() });
4302
- return data;
4303
- }).catch((err) => {
4302
+ const promise = doFetch3(crossOrgId).then((outcome) => {
4303
+ if (outcome.failed) {
4304
+ const previous = cache3.get(key)?.data;
4305
+ cache3.delete(key);
4306
+ return previous || [];
4307
+ }
4308
+ cache3.set(key, { data: outcome.data, fetchedAt: Date.now() });
4309
+ return outcome.data;
4310
+ }).catch(() => {
4304
4311
  cache3.delete(key);
4305
- throw err;
4312
+ return [];
4306
4313
  });
4307
4314
  cache3.set(key, { ...entry, promise });
4308
4315
  return promise;
@@ -9656,30 +9663,237 @@ function AppDetailContent({
9656
9663
 
9657
9664
  // drawerLayer.ts
9658
9665
  var import_react14 = require("react");
9666
+ var STACK_KEY = "__shuffleOverlayStack";
9659
9667
  var COUNTER_KEY = "__shuffleDrawerLayerTop";
9660
- var DRAWER_LAYER_BASE = 10011;
9661
- var STEP = 10;
9662
- var getTop = (base3) => {
9663
- const store = globalThis;
9664
- const current = store[COUNTER_KEY];
9665
- return typeof current === "number" ? current : base3;
9666
- };
9667
- var useDrawerLayer = (open, base3 = DRAWER_LAYER_BASE) => {
9668
- const [zIndex, setZIndex] = (0, import_react14.useState)(base3);
9668
+ var AUTO_LAYER_KEY = "__shuffleOverlayAutoLayerInstalled";
9669
+ var OVERLAY_BASE = 10010;
9670
+ var DRAWER_LAYER_BASE = OVERLAY_BASE;
9671
+ var SURFACE_STEP = 20;
9672
+ var POPUP_OFFSET = 6;
9673
+ var TOOLTIP_OFFSET = 12;
9674
+ var getStore = () => globalThis;
9675
+ var getOverlayStack = () => {
9676
+ const store = getStore();
9677
+ if (!Array.isArray(store[STACK_KEY])) {
9678
+ store[STACK_KEY] = [];
9679
+ }
9680
+ return store[STACK_KEY];
9681
+ };
9682
+ var getTopSurfaceZIndex = (base3 = OVERLAY_BASE) => {
9683
+ const stack = getOverlayStack();
9684
+ const surfaces = stack.filter((r) => r.type === "surface");
9685
+ if (surfaces.length === 0) {
9686
+ const store = getStore();
9687
+ store[COUNTER_KEY] = base3;
9688
+ return base3;
9689
+ }
9690
+ let maxZ = base3;
9691
+ for (const s of surfaces) {
9692
+ if (s.zIndex > maxZ) {
9693
+ maxZ = s.zIndex;
9694
+ }
9695
+ }
9696
+ getStore()[COUNTER_KEY] = maxZ;
9697
+ return maxZ;
9698
+ };
9699
+ var syncGlobalCounter = (base3 = OVERLAY_BASE) => {
9700
+ getTopSurfaceZIndex(base3);
9701
+ };
9702
+ var allocateSurfaceLayer = (id, element2, base3 = OVERLAY_BASE) => {
9703
+ const stack = getOverlayStack();
9704
+ const existing = stack.find((r) => r.id === id || element2 && r.element === element2);
9705
+ if (existing) {
9706
+ return existing.zIndex;
9707
+ }
9708
+ const currentTop = getTopSurfaceZIndex(base3);
9709
+ const nextZ = currentTop + SURFACE_STEP;
9710
+ stack.push({ id, element: element2, zIndex: nextZ, type: "surface" });
9711
+ syncGlobalCounter(base3);
9712
+ return nextZ;
9713
+ };
9714
+ var releaseOverlayLayer = (idOrElement) => {
9715
+ const stack = getOverlayStack();
9716
+ const index = stack.findIndex(
9717
+ (r) => r.id === idOrElement || typeof idOrElement !== "string" && r.element === idOrElement
9718
+ );
9719
+ if (index !== -1) {
9720
+ stack.splice(index, 1);
9721
+ }
9722
+ syncGlobalCounter();
9723
+ };
9724
+ var bringSurfaceToFront = (idOrElement) => {
9725
+ const stack = getOverlayStack();
9726
+ const record = stack.find(
9727
+ (r) => r.id === idOrElement || typeof idOrElement !== "string" && r.element === idOrElement
9728
+ );
9729
+ if (!record || record.type !== "surface") {
9730
+ return typeof idOrElement === "string" ? allocateSurfaceLayer(idOrElement, null) : allocateSurfaceLayer("surface_" + Math.random().toString(36).substring(2, 9), idOrElement);
9731
+ }
9732
+ const currentTop = getTopSurfaceZIndex();
9733
+ if (record.zIndex >= currentTop) {
9734
+ return record.zIndex;
9735
+ }
9736
+ record.zIndex = currentTop + SURFACE_STEP;
9737
+ syncGlobalCounter();
9738
+ return record.zIndex;
9739
+ };
9740
+ var useOverlayLayer = (open, options) => {
9741
+ const base3 = options?.base ?? OVERLAY_BASE;
9742
+ const [zIndex, setZIndex] = (0, import_react14.useState)(() => open ? getTopSurfaceZIndex(base3) + SURFACE_STEP : base3);
9669
9743
  (0, import_react14.useEffect)(() => {
9670
9744
  if (!open) return;
9671
- const store = globalThis;
9672
- const next = Math.max(base3, getTop(base3) + STEP);
9673
- store[COUNTER_KEY] = next;
9674
- setZIndex(next);
9745
+ const id = "hook_" + Math.random().toString(36).substring(2, 9);
9746
+ const allocated = allocateSurfaceLayer(id, null, base3);
9747
+ setZIndex(allocated);
9675
9748
  return () => {
9676
- if (store[COUNTER_KEY] === next) {
9677
- store[COUNTER_KEY] = next - STEP;
9678
- }
9749
+ releaseOverlayLayer(id);
9679
9750
  };
9680
9751
  }, [open, base3]);
9681
9752
  return zIndex;
9682
9753
  };
9754
+ var useDrawerLayer = (open, base3 = DRAWER_LAYER_BASE) => useOverlayLayer(open, { base: base3 });
9755
+ var isShuffleOwnedOverlay = (el) => el.classList.contains("shuffle-core-scope") || el.classList.contains("shuffle-mcp-scope") || el.querySelector(".shuffle-core-scope, .shuffle-mcp-scope") !== null || el.closest("[data-radix-portal]") !== null;
9756
+ var isSurfaceElement = (el) => {
9757
+ if (!(el instanceof HTMLElement)) return false;
9758
+ return el.classList.contains("MuiDialog-root") || el.classList.contains("MuiDrawer-root") || el.classList.contains("MuiModal-root") && !el.classList.contains("MuiPopover-root") && !el.classList.contains("MuiMenu-root") || el.getAttribute("role") === "dialog" || el.getAttribute("role") === "alertdialog" || Boolean(el.closest("[data-radix-portal]"));
9759
+ };
9760
+ var isChildPopupElement = (el) => {
9761
+ if (!(el instanceof HTMLElement)) return false;
9762
+ return el.classList.contains("MuiPopover-root") || el.classList.contains("MuiMenu-root") || el.classList.contains("MuiAutocomplete-popper") || Boolean(el.closest("[data-radix-popper-content-wrapper]")) || el.classList.contains("MuiPopper-root") && !el.classList.contains("MuiTooltip-popper");
9763
+ };
9764
+ var isTooltipElement = (el) => {
9765
+ if (!(el instanceof HTMLElement)) return false;
9766
+ return el.classList.contains("MuiTooltip-popper") || el.getAttribute("role") === "tooltip";
9767
+ };
9768
+ var isElementOpen = (el) => {
9769
+ if (el.getAttribute("aria-hidden") === "true") return false;
9770
+ if (el.getAttribute("data-state") === "closed") return false;
9771
+ if (el.classList.contains("MuiModal-hidden")) return false;
9772
+ const style = el.style;
9773
+ if (style.display === "none" || style.visibility === "hidden") return false;
9774
+ return true;
9775
+ };
9776
+ var observerInstance = null;
9777
+ var installGlobalOverlayAutoLayer = () => {
9778
+ if (typeof window === "undefined" || typeof document === "undefined") return;
9779
+ const store = getStore();
9780
+ if (store[AUTO_LAYER_KEY]) return;
9781
+ store[AUTO_LAYER_KEY] = true;
9782
+ const handleElementOpen = (el) => {
9783
+ if (!isShuffleOwnedOverlay(el)) return;
9784
+ if (isSurfaceElement(el)) {
9785
+ let layerId = el.dataset.shuffleLayerId;
9786
+ if (!layerId) {
9787
+ layerId = "dom_" + Math.random().toString(36).substring(2, 9);
9788
+ el.dataset.shuffleLayerId = layerId;
9789
+ }
9790
+ const targetZ = allocateSurfaceLayer(layerId, el);
9791
+ el.dataset.shuffleLayerZ = String(targetZ);
9792
+ el.style.setProperty("z-index", String(targetZ), "important");
9793
+ const dialogContent = el.querySelector('[role="dialog"], [role="alertdialog"]');
9794
+ if (dialogContent && dialogContent !== el) {
9795
+ dialogContent.style.setProperty("z-index", String(targetZ), "important");
9796
+ }
9797
+ return;
9798
+ }
9799
+ if (isChildPopupElement(el)) {
9800
+ const topZ = getTopSurfaceZIndex();
9801
+ const popupZ = topZ + POPUP_OFFSET;
9802
+ el.dataset.shuffleLayerZ = String(popupZ);
9803
+ el.style.setProperty("z-index", String(popupZ), "important");
9804
+ return;
9805
+ }
9806
+ if (isTooltipElement(el)) {
9807
+ const topZ = getTopSurfaceZIndex();
9808
+ const tooltipZ = topZ + TOOLTIP_OFFSET;
9809
+ el.dataset.shuffleLayerZ = String(tooltipZ);
9810
+ el.style.setProperty("z-index", String(tooltipZ), "important");
9811
+ return;
9812
+ }
9813
+ };
9814
+ const handleElementClose = (el) => {
9815
+ const layerId = el.dataset.shuffleLayerId;
9816
+ if (layerId) {
9817
+ releaseOverlayLayer(layerId);
9818
+ delete el.dataset.shuffleLayerId;
9819
+ delete el.dataset.shuffleLayerZ;
9820
+ } else {
9821
+ releaseOverlayLayer(el);
9822
+ }
9823
+ };
9824
+ const scanNode = (node) => {
9825
+ if (!(node instanceof HTMLElement)) return;
9826
+ if (isSurfaceElement(node) || isChildPopupElement(node) || isTooltipElement(node)) {
9827
+ if (isElementOpen(node)) {
9828
+ handleElementOpen(node);
9829
+ } else {
9830
+ handleElementClose(node);
9831
+ }
9832
+ }
9833
+ const children2 = node.children;
9834
+ for (let i = 0; i < children2.length; i++) {
9835
+ const child = children2[i];
9836
+ if (child instanceof HTMLElement) {
9837
+ if (isSurfaceElement(child) || isChildPopupElement(child) || isTooltipElement(child)) {
9838
+ if (isElementOpen(child)) {
9839
+ handleElementOpen(child);
9840
+ } else {
9841
+ handleElementClose(child);
9842
+ }
9843
+ }
9844
+ }
9845
+ }
9846
+ };
9847
+ observerInstance = new MutationObserver((mutations) => {
9848
+ for (const m of mutations) {
9849
+ if (m.type === "childList") {
9850
+ m.addedNodes.forEach(scanNode);
9851
+ m.removedNodes.forEach((node) => {
9852
+ if (node instanceof HTMLElement) {
9853
+ handleElementClose(node);
9854
+ }
9855
+ });
9856
+ } else if (m.type === "attributes") {
9857
+ const target = m.target;
9858
+ if (target instanceof HTMLElement) {
9859
+ scanNode(target);
9860
+ }
9861
+ }
9862
+ }
9863
+ });
9864
+ const body = document.body;
9865
+ if (body) {
9866
+ observerInstance.observe(body, {
9867
+ childList: true,
9868
+ subtree: true,
9869
+ attributes: true,
9870
+ attributeFilter: ["class", "style", "aria-hidden", "data-state"]
9871
+ });
9872
+ Array.from(body.children).forEach(scanNode);
9873
+ }
9874
+ document.addEventListener(
9875
+ "pointerdown",
9876
+ (e) => {
9877
+ const target = e.target;
9878
+ if (!target) return;
9879
+ const surface = target.closest(
9880
+ '.MuiDialog-root, .MuiDrawer-root, .MuiModal-root:not(.MuiPopover-root):not(.MuiMenu-root), [role="dialog"], [role="alertdialog"]'
9881
+ );
9882
+ if (!surface || !surface.dataset.shuffleLayerId) return;
9883
+ const currentZ = Number(surface.dataset.shuffleLayerZ || 0);
9884
+ const topZ = getTopSurfaceZIndex();
9885
+ if (currentZ > 0 && currentZ < topZ) {
9886
+ const newZ = bringSurfaceToFront(surface.dataset.shuffleLayerId);
9887
+ surface.dataset.shuffleLayerZ = String(newZ);
9888
+ surface.style.setProperty("z-index", String(newZ), "important");
9889
+ }
9890
+ },
9891
+ true
9892
+ );
9893
+ };
9894
+ if (typeof window !== "undefined") {
9895
+ installGlobalOverlayAutoLayer();
9896
+ }
9683
9897
 
9684
9898
  // views/AppDetailDrawer.tsx
9685
9899
  var import_jsx_runtime17 = require("react/jsx-runtime");
@@ -10141,6 +10355,11 @@ var ShuffleMCP = import_react15.default.forwardRef(({
10141
10355
  const [isOpen, setIsOpen] = (0, import_react15.useState)(false);
10142
10356
  const [selectedIndex, setSelectedIndex] = (0, import_react15.useState)(-1);
10143
10357
  const [internalSelectedApps, setInternalSelectedApps] = (0, import_react15.useState)(selectedApps);
10358
+ (0, import_react15.useEffect)(() => {
10359
+ if (selectedApps) {
10360
+ setInternalSelectedApps(selectedApps);
10361
+ }
10362
+ }, [selectedApps]);
10144
10363
  const [authenticatedApps, setAuthenticatedApps] = (0, import_react15.useState)(externalAuthenticatedApps || []);
10145
10364
  const [authenticatedAppsLoading, setAuthenticatedAppsLoading] = (0, import_react15.useState)(!externalAuthenticatedApps);
10146
10365
  const [drawerApp, setDrawerApp] = (0, import_react15.useState)(null);
@@ -11325,6 +11544,7 @@ var AddAppDialog = ({
11325
11544
  maxLength = 1024,
11326
11545
  initialInput = ""
11327
11546
  }) => {
11547
+ const dialogZIndex = useOverlayLayer(open);
11328
11548
  const [input, setInput] = (0, import_react16.useState)(initialInput);
11329
11549
  const [stage, setStage] = (0, import_react16.useState)("idle");
11330
11550
  const [spec, setSpec] = (0, import_react16.useState)(null);
@@ -11491,6 +11711,12 @@ var AddAppDialog = ({
11491
11711
  onClose: () => onOpenChange(false),
11492
11712
  fullWidth: true,
11493
11713
  maxWidth: "sm",
11714
+ sx: {
11715
+ zIndex: dialogZIndex,
11716
+ "& .MuiBackdrop-root": {
11717
+ zIndex: dialogZIndex
11718
+ }
11719
+ },
11494
11720
  PaperProps: {
11495
11721
  sx: {
11496
11722
  maxWidth: 640,
@@ -11499,7 +11725,8 @@ var AddAppDialog = ({
11499
11725
  color: "hsl(var(--foreground))",
11500
11726
  border: "1px solid hsl(var(--border))",
11501
11727
  borderRadius: 2,
11502
- boxSizing: "border-box"
11728
+ boxSizing: "border-box",
11729
+ zIndex: dialogZIndex
11503
11730
  }
11504
11731
  },
11505
11732
  children: [
@@ -12548,6 +12775,8 @@ var AiAgentPromptsEditor = ({
12548
12775
  prompts,
12549
12776
  apps,
12550
12777
  readOnly = false,
12778
+ skillLabel,
12779
+ isBuiltInApp,
12551
12780
  onChangePrompt,
12552
12781
  onRemovePrompt,
12553
12782
  onAddPrompt,
@@ -12635,16 +12864,44 @@ var AiAgentPromptsEditor = ({
12635
12864
  ] }),
12636
12865
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
12637
12866
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12638
- import_material18.Typography,
12867
+ import_material18.Tooltip,
12639
12868
  {
12640
- sx: {
12641
- fontSize: "0.65rem",
12642
- fontWeight: 600,
12643
- color: "hsl(var(--muted-foreground))",
12644
- textTransform: "uppercase",
12645
- letterSpacing: "0.05em"
12646
- },
12647
- children: "Allowed apps"
12869
+ title: skillLabel ? `Allowed apps are shared with ${skillLabel} permissions. Changes made here apply to all automations and agent runs.` : "Apps this AI Agent prompt is permitted to run.",
12870
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "inline-flex", alignItems: "center", gap: 0.75 }, children: [
12871
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12872
+ import_material18.Typography,
12873
+ {
12874
+ sx: {
12875
+ fontSize: "0.65rem",
12876
+ fontWeight: 600,
12877
+ color: "hsl(var(--muted-foreground))",
12878
+ textTransform: "uppercase",
12879
+ letterSpacing: "0.05em"
12880
+ },
12881
+ children: "Allowed apps"
12882
+ }
12883
+ ),
12884
+ skillLabel && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
12885
+ import_material18.Typography,
12886
+ {
12887
+ component: "span",
12888
+ sx: {
12889
+ fontSize: "0.62rem",
12890
+ fontWeight: 600,
12891
+ color: "hsl(var(--primary))",
12892
+ bgcolor: "hsl(var(--primary) / 0.1)",
12893
+ px: 0.6,
12894
+ py: 0.1,
12895
+ borderRadius: 0.75,
12896
+ letterSpacing: "0.02em"
12897
+ },
12898
+ children: [
12899
+ skillLabel,
12900
+ " permissions"
12901
+ ]
12902
+ }
12903
+ )
12904
+ ] })
12648
12905
  }
12649
12906
  ),
12650
12907
  /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_material18.Box, { sx: { display: "flex", alignItems: "center", gap: 0.5, flexWrap: "wrap", flex: 1 }, children: [
@@ -12653,8 +12910,9 @@ var AiAgentPromptsEditor = ({
12653
12910
  const meta = resolveAppMeta(appKey);
12654
12911
  const displayName2 = meta.name;
12655
12912
  const img = meta.image || `https://shuffler.io/images/apps/${displayName2}.png`;
12913
+ const isBuiltIn = isBuiltInApp ? isBuiltInApp(appKey) : false;
12656
12914
  const clickable = !readOnly && !!onRemoveApp;
12657
- const tip = clickable ? `Remove ${displayName2.replace(/_/g, " ")}` : displayName2.replace(/_/g, " ");
12915
+ const tip = isBuiltIn ? `${displayName2.replace(/_/g, " ")} (Default built-in app for ${skillLabel || "skill"})` : clickable ? `Remove ${displayName2.replace(/_/g, " ")} (Assigned permission)` : displayName2.replace(/_/g, " ");
12658
12916
  return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Tooltip, { title: tip, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12659
12917
  import_material18.IconButton,
12660
12918
  {
@@ -12664,12 +12922,12 @@ var AiAgentPromptsEditor = ({
12664
12922
  sx: {
12665
12923
  width: 26,
12666
12924
  height: 26,
12667
- border: "1px solid hsl(var(--severity-low) / 0.3)",
12668
- bgcolor: "hsl(var(--severity-low) / 0.1)",
12925
+ border: isBuiltIn ? "1px solid hsl(var(--primary) / 0.35)" : "1px solid hsl(var(--severity-low) / 0.3)",
12926
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)",
12669
12927
  borderRadius: 1,
12670
12928
  "&.Mui-disabled": {
12671
12929
  opacity: 1,
12672
- bgcolor: "hsl(var(--severity-low) / 0.1)"
12930
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)"
12673
12931
  },
12674
12932
  "&:hover": clickable ? {
12675
12933
  bgcolor: "hsl(var(--destructive) / 0.15)",
@@ -12688,7 +12946,7 @@ var AiAgentPromptsEditor = ({
12688
12946
  }
12689
12947
  ) }, appKey);
12690
12948
  }),
12691
- !readOnly && onAddAppRequested && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Tooltip, { title: "Add allowed app", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12949
+ !readOnly && onAddAppRequested && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_material18.Tooltip, { title: skillLabel ? `Assign tools to ${skillLabel}` : "Add allowed app", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
12692
12950
  import_material18.IconButton,
12693
12951
  {
12694
12952
  size: "small",
@@ -13397,7 +13655,7 @@ var AGENT_PRESETS = [
13397
13655
  icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react11.ShieldAlert, { size: 16 }),
13398
13656
  enabled: true,
13399
13657
  tag: "Beta",
13400
- defaultApps: [{ name: "shuffle_incidents" }, { name: "shuffle_datastore" }]
13658
+ defaultApps: [{ name: "shuffle_incidents" }]
13401
13659
  },
13402
13660
  {
13403
13661
  id: "host-monitor-control",
@@ -13858,6 +14116,150 @@ var AgentPresets = ({ variant = "default", onSelectPreset, selectedPreset, onRem
13858
14116
  };
13859
14117
  var AgentPresets_default = AgentPresets;
13860
14118
 
14119
+ // ../lib/agentTools.ts
14120
+ var STORAGE_KEY3 = "agent_tools_config";
14121
+ var AGENT_TOOLS_CHANGED_EVENT = "agent-tools-changed";
14122
+ var DEFAULT_AGENT = "default";
14123
+ var DEFAULT_ACTION_TYPE = "timeline_reply";
14124
+ var getActiveOrgId = () => {
14125
+ if (typeof window === "undefined") return null;
14126
+ try {
14127
+ const raw = localStorage.getItem("shuffle_user_info") || localStorage.getItem("userinfo") || localStorage.getItem("user_info");
14128
+ if (!raw) return null;
14129
+ const parsed = JSON.parse(raw);
14130
+ return parsed?.active_org?.id || parsed?.org_id || parsed?.active_org_id || Array.isArray(parsed?.orgs) && parsed.orgs[0]?.id || parsed?.id || null;
14131
+ } catch {
14132
+ return null;
14133
+ }
14134
+ };
14135
+ var getStorageKey = (orgId) => {
14136
+ const resolved = orgId || getActiveOrgId();
14137
+ return resolved ? `${STORAGE_KEY3}_${resolved}` : STORAGE_KEY3;
14138
+ };
14139
+ var coerceTool = (raw) => {
14140
+ if (typeof raw === "string") {
14141
+ const trimmed = raw.trim();
14142
+ if (!trimmed) return null;
14143
+ return { name: trimmed, id: trimmed };
14144
+ }
14145
+ if (raw && typeof raw === "object") {
14146
+ const obj = raw;
14147
+ const name = typeof obj.name === "string" ? obj.name.trim() : "";
14148
+ const id = typeof obj.id === "string" && obj.id.trim() ? obj.id.trim() : name;
14149
+ if (!name) return null;
14150
+ return { name, id };
14151
+ }
14152
+ return null;
14153
+ };
14154
+ var sanitize2 = (parsed) => {
14155
+ let target = parsed;
14156
+ if (target && typeof target === "object" && !Array.isArray(target)) {
14157
+ const obj = target;
14158
+ if (Array.isArray(obj.entries)) {
14159
+ target = obj.entries;
14160
+ }
14161
+ }
14162
+ if (!Array.isArray(target)) return [];
14163
+ return target.filter((e) => e && typeof e.agent === "string" && typeof e.actionType === "string" && Array.isArray(e.tools)).map((e) => ({
14164
+ agent: e.agent,
14165
+ actionType: e.actionType,
14166
+ tools: e.tools.map(coerceTool).filter((t) => !!t),
14167
+ updatedAt: typeof e.updatedAt === "number" ? e.updatedAt : void 0
14168
+ }));
14169
+ };
14170
+ var extractUpdatedAt = (parsed) => {
14171
+ if (parsed && typeof parsed === "object") {
14172
+ const obj = parsed;
14173
+ if (typeof obj.updatedAt === "number") return obj.updatedAt;
14174
+ }
14175
+ return 0;
14176
+ };
14177
+ var readCacheRecord = () => {
14178
+ if (typeof window === "undefined") return { entries: [], updatedAt: 0 };
14179
+ try {
14180
+ const key = getStorageKey();
14181
+ let raw = localStorage.getItem(key);
14182
+ let parsed = null;
14183
+ let entries = [];
14184
+ let updatedAt = 0;
14185
+ if (raw) {
14186
+ try {
14187
+ parsed = JSON.parse(raw);
14188
+ entries = sanitize2(parsed);
14189
+ updatedAt = extractUpdatedAt(parsed) || entries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0);
14190
+ } catch {
14191
+ }
14192
+ }
14193
+ if (entries.length === 0 || entries.every((e) => e.tools.length === 0)) {
14194
+ if (key !== STORAGE_KEY3) {
14195
+ const fallbackRaw = localStorage.getItem(STORAGE_KEY3);
14196
+ if (fallbackRaw) {
14197
+ try {
14198
+ const fallbackParsed = JSON.parse(fallbackRaw);
14199
+ const fallbackEntries = sanitize2(fallbackParsed);
14200
+ if (fallbackEntries.some((e) => e.tools.length > 0)) {
14201
+ entries = fallbackEntries;
14202
+ updatedAt = extractUpdatedAt(fallbackParsed) || fallbackEntries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0) || Date.now();
14203
+ writeCache(entries, updatedAt);
14204
+ }
14205
+ } catch {
14206
+ }
14207
+ }
14208
+ }
14209
+ }
14210
+ return { entries, updatedAt };
14211
+ } catch {
14212
+ return { entries: [], updatedAt: 0 };
14213
+ }
14214
+ };
14215
+ var readAll = () => readCacheRecord().entries;
14216
+ var writeCache = (entries, explicitUpdatedAt) => {
14217
+ if (typeof window === "undefined") return;
14218
+ try {
14219
+ const updatedAt = explicitUpdatedAt ?? Date.now();
14220
+ const payload = {
14221
+ version: 1,
14222
+ updatedAt,
14223
+ entries
14224
+ };
14225
+ const serialized = JSON.stringify(payload);
14226
+ const orgKey = getStorageKey();
14227
+ localStorage.setItem(orgKey, serialized);
14228
+ if (orgKey !== STORAGE_KEY3) {
14229
+ localStorage.setItem(STORAGE_KEY3, serialized);
14230
+ }
14231
+ window.dispatchEvent(
14232
+ new CustomEvent(AGENT_TOOLS_CHANGED_EVENT, { detail: { updatedAt, entries } })
14233
+ );
14234
+ } catch {
14235
+ }
14236
+ };
14237
+ var getAgentTools = (agent = DEFAULT_AGENT, actionType = DEFAULT_ACTION_TYPE) => {
14238
+ const all = readAll();
14239
+ const entry = all.find((e) => e.agent === agent && e.actionType === actionType);
14240
+ if (entry && entry.tools && entry.tools.length > 0) {
14241
+ return entry.tools;
14242
+ }
14243
+ if (agent === "incident-handler" || agent === "incident-response" || agent === DEFAULT_AGENT) {
14244
+ const found = all.find(
14245
+ (e) => (e.agent === "incident-handler" || e.agent === "incident-response" || e.agent === DEFAULT_AGENT) && e.actionType === actionType && e.tools && e.tools.length > 0
14246
+ );
14247
+ if (found?.tools && found.tools.length > 0) return found.tools;
14248
+ }
14249
+ return [];
14250
+ };
14251
+ var getToolsForSkill = (skillOrPresetId) => {
14252
+ const normalized = (skillOrPresetId || "").toLowerCase().trim();
14253
+ if (normalized === "incident-handler" || normalized === "incident-response" || normalized === "default") {
14254
+ const ih = getAgentTools("incident-handler");
14255
+ if (ih.length > 0) return ih;
14256
+ const ir = getAgentTools("incident-response");
14257
+ if (ir.length > 0) return ir;
14258
+ return getAgentTools(DEFAULT_AGENT);
14259
+ }
14260
+ return getAgentTools(normalized);
14261
+ };
14262
+
13861
14263
  // useAgentPromptPrefix.ts
13862
14264
  var import_react20 = require("react");
13863
14265
  var AGENT_PROMPT_PREFIX_CATEGORY = "agent-prompt-prefix";
@@ -14078,6 +14480,9 @@ var runAgent = async (request) => {
14078
14480
  if (request.incidentId) {
14079
14481
  input.incident_id = request.incidentId;
14080
14482
  }
14483
+ if (request.incidentContext) {
14484
+ input.incident_context = request.incidentContext;
14485
+ }
14081
14486
  if (request.vulnerabilityId) {
14082
14487
  input.vulnerability_id = request.vulnerabilityId;
14083
14488
  }
@@ -14356,16 +14761,143 @@ var getCachedGroupDocs = (groupId, folder) => {
14356
14761
  }));
14357
14762
  };
14358
14763
 
14764
+ // ../lib/incidentPromptContext.ts
14765
+ var GLOBAL_INCIDENT_KEY = "__shuffleActiveIncidentContext";
14766
+ var getGlobalScope = () => {
14767
+ if (typeof globalThis !== "undefined") return globalThis;
14768
+ if (typeof window !== "undefined") return window;
14769
+ if (typeof global !== "undefined") return global;
14770
+ return null;
14771
+ };
14772
+ var getActiveIncidentPromptContext = () => {
14773
+ const scope = getGlobalScope();
14774
+ if (!scope) return null;
14775
+ const info = scope[GLOBAL_INCIDENT_KEY];
14776
+ if (info && typeof info === "object") {
14777
+ return info;
14778
+ }
14779
+ return null;
14780
+ };
14781
+ var INCIDENT_PROMPT_DELIMITER_START = "=== INCIDENT CONTEXT ===";
14782
+ var INCIDENT_PROMPT_DELIMITER_END = "=== END INCIDENT CONTEXT ===";
14783
+ var formatObservableType = (type) => {
14784
+ if (!type) return "Indicator";
14785
+ const clean = type.toLowerCase().trim();
14786
+ switch (clean) {
14787
+ case "ip":
14788
+ case "ipv4":
14789
+ case "ip_address":
14790
+ return "IPv4";
14791
+ case "ipv6":
14792
+ return "IPv6";
14793
+ case "hash":
14794
+ case "sha256":
14795
+ case "file_hash":
14796
+ return "SHA256";
14797
+ case "md5":
14798
+ return "MD5";
14799
+ case "sha1":
14800
+ return "SHA1";
14801
+ case "hostname":
14802
+ case "host":
14803
+ case "endpoint":
14804
+ return "Hostname";
14805
+ case "domain":
14806
+ return "Domain";
14807
+ case "url":
14808
+ return "URL";
14809
+ case "user":
14810
+ case "username":
14811
+ case "account":
14812
+ return "User";
14813
+ case "email":
14814
+ return "Email";
14815
+ case "process":
14816
+ case "process_name":
14817
+ return "Process";
14818
+ case "file":
14819
+ case "filename":
14820
+ return "File";
14821
+ default:
14822
+ return type.charAt(0).toUpperCase() + type.slice(1);
14823
+ }
14824
+ };
14825
+ var isIncidentInjectedPrompt = (prompt) => {
14826
+ if (!prompt || typeof prompt !== "string") return false;
14827
+ return prompt.includes(INCIDENT_PROMPT_DELIMITER_START) || prompt.includes("OPERATIONAL DIRECTIVES:") || prompt.includes("INCIDENT OBSERVABLES / IOCs:");
14828
+ };
14829
+ var extractCleanIncidentPrompt = (prompt) => {
14830
+ if (!prompt || typeof prompt !== "string") return "";
14831
+ const trimmed = prompt.trim();
14832
+ const taskMatch = trimmed.match(/TASK TO EXECUTE:\s*\n\s*-\s*Task:\s*([^\n]+)/i);
14833
+ if (taskMatch && taskMatch[1]?.trim()) {
14834
+ return `Task: ${taskMatch[1].trim()}`;
14835
+ }
14836
+ const legacyMatch = trimmed.match(/\n\s*Task:\s*([^\n]+)/i);
14837
+ if (legacyMatch && legacyMatch[1]?.trim()) {
14838
+ return `Task: ${legacyMatch[1].trim()}`;
14839
+ }
14840
+ if (trimmed.includes(INCIDENT_PROMPT_DELIMITER_START)) {
14841
+ const before = trimmed.split(INCIDENT_PROMPT_DELIMITER_START)[0]?.trim();
14842
+ if (before) return before;
14843
+ }
14844
+ return trimmed;
14845
+ };
14846
+ var composeIncidentPromptInput = (rawInput, context) => {
14847
+ if (!rawInput || typeof rawInput !== "string") return "";
14848
+ const trimmed = rawInput.trim();
14849
+ if (isIncidentInjectedPrompt(trimmed)) {
14850
+ return trimmed;
14851
+ }
14852
+ const ctx = context || getActiveIncidentPromptContext();
14853
+ if (!ctx || !ctx.id) {
14854
+ return trimmed;
14855
+ }
14856
+ const incidentRef = ctx.id ? `#${ctx.id}` : "";
14857
+ const incidentTitle = ctx.title?.trim() || "Incident";
14858
+ const severity = ctx.severity || "Medium";
14859
+ const status = ctx.status || "In Progress";
14860
+ const description = ctx.description?.trim() || "No description provided.";
14861
+ const seenObservables = /* @__PURE__ */ new Set();
14862
+ const formattedObservables = [];
14863
+ if (Array.isArray(ctx.observables)) {
14864
+ for (const obs of ctx.observables) {
14865
+ if (!obs || obs.archived || !obs.value?.trim()) continue;
14866
+ const val = obs.value.trim();
14867
+ const typeLabel = formatObservableType(obs.type);
14868
+ const key = `${typeLabel.toLowerCase()}:${val.toLowerCase()}`;
14869
+ if (seenObservables.has(key)) continue;
14870
+ seenObservables.add(key);
14871
+ formattedObservables.push(`- ${typeLabel}: ${val}`);
14872
+ }
14873
+ }
14874
+ const observablesBlock = formattedObservables.length > 0 ? formattedObservables.slice(0, 50).join("\n") : "- None recorded yet";
14875
+ return `${trimmed}
14876
+
14877
+ ${INCIDENT_PROMPT_DELIMITER_START}
14878
+ INCIDENT CONTEXT:
14879
+ - Incident: ${incidentRef} ("${incidentTitle}")
14880
+ - Severity: ${severity} | Status: ${status}
14881
+ - Summary: ${description}
14882
+
14883
+ INCIDENT OBSERVABLES / IOCs:
14884
+ ${observablesBlock}
14885
+ ${INCIDENT_PROMPT_DELIMITER_END}
14886
+
14887
+ DIRECTIVES:
14888
+ - Relevant incident details and observables are provided above. Do not call "get_incident" unless raw external logs are required.`;
14889
+ };
14890
+
14359
14891
  // ../lib/docsPromptContext.ts
14360
14892
  var GLOBAL_DOC_KEY = "__shuffleActiveDocInfo";
14361
- var getGlobalScope = () => {
14893
+ var getGlobalScope2 = () => {
14362
14894
  if (typeof globalThis !== "undefined") return globalThis;
14363
14895
  if (typeof window !== "undefined") return window;
14364
14896
  if (typeof global !== "undefined") return global;
14365
14897
  return null;
14366
14898
  };
14367
14899
  var getActiveDocPromptContext = () => {
14368
- const scope = getGlobalScope();
14900
+ const scope = getGlobalScope2();
14369
14901
  if (!scope) return null;
14370
14902
  const info = scope[GLOBAL_DOC_KEY];
14371
14903
  if (info && typeof info === "object") {
@@ -14406,6 +14938,9 @@ var isDocInjectedPrompt = (prompt) => {
14406
14938
  var extractCleanDisplayPrompt = (prompt) => {
14407
14939
  if (!prompt || typeof prompt !== "string") return "";
14408
14940
  const trimmed = prompt.trim();
14941
+ if (isIncidentInjectedPrompt(trimmed)) {
14942
+ return extractCleanIncidentPrompt(trimmed);
14943
+ }
14409
14944
  if (!isDocInjectedPrompt(trimmed)) return trimmed;
14410
14945
  if (trimmed.includes(DOC_PROMPT_DELIMITER_END)) {
14411
14946
  const parts = trimmed.split(DOC_PROMPT_DELIMITER_END);
@@ -14445,7 +14980,7 @@ var composeDocPromptInput = (userQuestion, pathname, fallbackTitle, overrideDocI
14445
14980
  return trimmedQuestion;
14446
14981
  }
14447
14982
  const activeDoc = overrideDocInfo ?? getActiveDocPromptContext();
14448
- const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
14983
+ const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope2()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
14449
14984
  const title = normalizeDocPromptTitle(rawTitle);
14450
14985
  const groupLabel = activeDoc?.groupLabel;
14451
14986
  const groupId = activeDoc?.groupId;
@@ -17102,6 +17637,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
17102
17637
  const cleanId = formatEntityDisplayId(params.id);
17103
17638
  return `Investigate incident ${cleanId} and recommend next steps: `;
17104
17639
  },
17640
+ composeInput: (raw) => composeIncidentPromptInput(raw),
17105
17641
  placeholder: "Ask about this incident, triage observables, or correlate...",
17106
17642
  getStorageKey: (params) => `incident_${params.id}`,
17107
17643
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -17126,6 +17662,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
17126
17662
  const cleanId = formatEntityDisplayId(params.id);
17127
17663
  return `Investigate incident ${cleanId} and recommend next steps: `;
17128
17664
  },
17665
+ composeInput: (raw) => composeIncidentPromptInput(raw),
17129
17666
  placeholder: "Ask about this incident, triage observables, or correlate...",
17130
17667
  getStorageKey: (params) => `incident_${params.id}`,
17131
17668
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -17148,6 +17685,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
17148
17685
  const cleanId = formatEntityDisplayId(params.id);
17149
17686
  return `Investigate case ${cleanId} and recommend next steps: `;
17150
17687
  },
17688
+ composeInput: (raw) => composeIncidentPromptInput(raw),
17151
17689
  placeholder: "Review case evidence, correlate events, or recommend response actions...",
17152
17690
  getStorageKey: (params) => `case_${params.id}`,
17153
17691
  description: "Focused on the currently viewed case with Shuffle Incidents MCP"
@@ -17878,6 +18416,18 @@ var readPresetAppsOverride = (presetId) => {
17878
18416
  return null;
17879
18417
  }
17880
18418
  };
18419
+ var resolvePresetApps = (preset) => {
18420
+ const baseApps = (preset.defaultApps || []).map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon }));
18421
+ const assigned = getToolsForSkill(preset.id);
18422
+ const merged = [...baseApps];
18423
+ for (const t of assigned) {
18424
+ const key = (t.id || t.name).toLowerCase();
18425
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
18426
+ merged.push({ name: t.name, id: t.id, icon: t.icon || void 0 });
18427
+ }
18428
+ }
18429
+ return merged;
18430
+ };
17881
18431
  var writePresetAppsOverride = (presetId, apps) => {
17882
18432
  try {
17883
18433
  const raw = localStorage.getItem(PRESET_APPS_STORAGE_KEY);
@@ -18256,8 +18806,12 @@ var extractAuthRequest = (decision) => {
18256
18806
  } else if (raw && typeof raw === "object") {
18257
18807
  parsed = raw;
18258
18808
  }
18259
- const needsAuth = parsed && (parsed.action === "app_authentication" || parsed.app_authentication === true);
18260
- if (!needsAuth) return null;
18809
+ const candidateObjects = [
18810
+ parsed,
18811
+ decision?.result,
18812
+ decision?.run_details,
18813
+ decision
18814
+ ].filter(Boolean);
18261
18815
  let toolAppName;
18262
18816
  let appId = null;
18263
18817
  if (typeof decision?.tool === "string") {
@@ -18270,8 +18824,36 @@ var extractAuthRequest = (decision) => {
18270
18824
  toolAppName = t;
18271
18825
  }
18272
18826
  }
18273
- let appName = parsed.app || parsed.app_name || parsed.appname;
18274
- if (!appName) appName = toolAppName;
18827
+ let needsAuth = false;
18828
+ let candidateAppName;
18829
+ for (const obj of candidateObjects) {
18830
+ if (obj.action === "app_authentication" || obj.app_authentication === true || obj.action === "authenticate" || obj.needs_auth === true || obj.auth_required === true) {
18831
+ needsAuth = true;
18832
+ }
18833
+ const candidate = obj.app || obj.app_name || obj.appname;
18834
+ if (typeof candidate === "string" && candidate.trim()) {
18835
+ candidateAppName = candidate.trim();
18836
+ }
18837
+ }
18838
+ const textSources = [
18839
+ decision?.error,
18840
+ decision?.reason,
18841
+ decision?.status_message,
18842
+ decision?.message,
18843
+ decision?.run_details?.error,
18844
+ typeof raw === "string" ? raw : ""
18845
+ ];
18846
+ const combinedText = textSources.filter(Boolean).join(" ").toLowerCase();
18847
+ if (combinedText.includes("app_authentication") || combinedText.includes("requires authentication") || combinedText.includes("missing authentication") || combinedText.includes("unauthorized") || combinedText.includes("not authenticated") || combinedText.includes("invalid credentials") || combinedText.includes("missing api key")) {
18848
+ needsAuth = true;
18849
+ }
18850
+ if (!needsAuth && (decision?.status === "WAITING" || decision?.status === "PENDING" || decision?.run_details?.status === "WAITING" || decision?.run_details?.status === "PENDING")) {
18851
+ if (toolAppName && appRequiresAuthentication(toolAppName)) {
18852
+ needsAuth = true;
18853
+ }
18854
+ }
18855
+ if (!needsAuth) return null;
18856
+ let appName = candidateAppName || toolAppName;
18275
18857
  if (!appName) {
18276
18858
  const f = (decision?.fields || []).find((x) => x?.key === "app" || x?.key === "app_name");
18277
18859
  if (f?.value) appName = f.value;
@@ -18286,12 +18868,17 @@ var STATUS_COLORS = {
18286
18868
  running: "hsl(var(--primary))"
18287
18869
  };
18288
18870
  var TERMINAL_RUN_STATUSES = ["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"];
18289
- var resolveRunStatus = (executionStatus, agentStatus) => {
18290
- const exec = String(executionStatus || "").toUpperCase();
18291
- const agent = String(agentStatus || "").toUpperCase();
18292
- if (TERMINAL_RUN_STATUSES.includes(exec)) return exec;
18293
- if (TERMINAL_RUN_STATUSES.includes(agent)) return agent;
18294
- return exec || agent || "";
18871
+ var resolveRunStatus = (execStatus, agentStatus) => {
18872
+ const e = (execStatus || "").toUpperCase();
18873
+ const a = (agentStatus || "").toUpperCase();
18874
+ if (e === "FINISHED" || a === "FINISHED") return "FINISHED";
18875
+ if (e === "FAILURE" || a === "FAILURE") return "FAILURE";
18876
+ if (e === "ABORTED" || a === "ABORTED") return "ABORTED";
18877
+ if (e === "CANCELLED" || a === "CANCELLED" || e === "CANCELED" || a === "CANCELED") return "CANCELLED";
18878
+ if (e === "WAITING" || a === "WAITING") return "WAITING";
18879
+ if (e === "PENDING" || a === "PENDING") return "PENDING";
18880
+ if (e === "RUNNING" || a === "RUNNING" || e === "EXECUTING" || a === "EXECUTING") return "RUNNING";
18881
+ return e || a || "FINISHED";
18295
18882
  };
18296
18883
  var buildToolName = (apps) => {
18297
18884
  if (!apps.length) return "API";
@@ -18315,7 +18902,11 @@ var DurationCountdown = ({ resumeAtMs }) => {
18315
18902
  const remaining = resumeAtMs - nowMs;
18316
18903
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: `Scheduled to continue at ${new Date(resumeAtMs).toLocaleString()}`, arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { component: "span", sx: { whiteSpace: "nowrap", cursor: "default" }, children: remaining > 0 ? `in ${formatTimeLeft(remaining)}` : "due now" }) });
18317
18904
  };
18318
- var StatusIcon = ({ status, resumeAtMs }) => {
18905
+ var StatusIcon = ({
18906
+ status,
18907
+ resumeAtMs,
18908
+ authBlockedApp
18909
+ }) => {
18319
18910
  const s = (status || "").toUpperCase();
18320
18911
  const isScheduledWait = s === "WAITING" && !!resumeAtMs;
18321
18912
  const [nowMs, setNowMs] = (0, import_react24.useState)(() => Date.now());
@@ -18326,7 +18917,10 @@ var StatusIcon = ({ status, resumeAtMs }) => {
18326
18917
  }, [isScheduledWait]);
18327
18918
  let node;
18328
18919
  let label;
18329
- if (s === "RUNNING" || s === "EXECUTING" || s === "") {
18920
+ if (authBlockedApp) {
18921
+ node = /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.Lock, { size: 20, color: "hsl(var(--destructive))" });
18922
+ label = `Authentication required for ${formatAppDisplayName(authBlockedApp)} \u2014 step cannot proceed until connected`;
18923
+ } else if (s === "RUNNING" || s === "EXECUTING" || s === "") {
18330
18924
  node = /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.CircularProgress, { size: 18, sx: { color: STATUS_COLORS.running } });
18331
18925
  label = "Running";
18332
18926
  } else if (s === "WAITING") {
@@ -18525,8 +19119,10 @@ var TimelineRow = ({
18525
19119
  const s = (effectiveStatus || "").toUpperCase();
18526
19120
  return s === "WAITING" || s === "RUNNING" || s === "EXECUTING" || s === "";
18527
19121
  })();
18528
- const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : isFailed ? STATUS_COLORS.error : "hsl(var(--muted-foreground) / 0.35)";
18529
- const hoverBarColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : effectiveStatus === "FINISHED" || effectiveStatus === "IGNORED" ? STATUS_COLORS.finished : isFailed ? STATUS_COLORS.error : STATUS_COLORS.running;
19122
+ const rowAuthReq = extractAuthRequest(details);
19123
+ const isRowAuthBlocked = !!rowAuthReq && !isAppAuthenticated?.(rowAuthReq.appName, rowAuthReq.appId) && (effectiveStatus === "WAITING" || effectiveStatus === "PENDING" || effectiveStatus === "FAILURE" || effectiveStatus === "ABORTED");
19124
+ const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : isFailed || isRowAuthBlocked ? STATUS_COLORS.error : "hsl(var(--muted-foreground) / 0.35)";
19125
+ const hoverBarColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : effectiveStatus === "FINISHED" || effectiveStatus === "IGNORED" ? STATUS_COLORS.finished : isFailed || isRowAuthBlocked ? STATUS_COLORS.error : STATUS_COLORS.running;
18530
19126
  const isRerunTarget = !!rerunningDecisionId && item.type === "decision" && details?.run_details?.id === rerunningDecisionId;
18531
19127
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
18532
19128
  import_material26.Box,
@@ -18535,9 +19131,25 @@ var TimelineRow = ({
18535
19131
  sx: {
18536
19132
  borderTop: index === 0 ? "none" : "1px solid hsl(var(--border))",
18537
19133
  bgcolor: highlight ? "hsla(var(--severity-medium) / 0.12)" : isRerunTarget ? "hsla(var(--primary) / 0.08)" : open ? "hsl(var(--muted) / 0.3)" : "transparent",
18538
- transition: "background 0.6s ease, box-shadow 0.6s ease, opacity 0.2s ease",
18539
- scrollMarginTop: 96,
19134
+ transition: "background-color 0.2s ease",
19135
+ "&:hover": {
19136
+ bgcolor: "hsl(var(--muted) / 0.4)"
19137
+ },
18540
19138
  position: "relative",
19139
+ "&::before": {
19140
+ content: '""',
19141
+ position: "absolute",
19142
+ left: 0,
19143
+ top: 0,
19144
+ bottom: 0,
19145
+ width: 3,
19146
+ bgcolor: barColor,
19147
+ transition: "background-color 0.15s ease"
19148
+ },
19149
+ "&:hover::before": {
19150
+ bgcolor: hoverBarColor
19151
+ },
19152
+ scrollMarginTop: 96,
18541
19153
  boxShadow: highlight ? "inset 0 0 0 2px hsla(var(--severity-medium) / 0.55)" : isRerunTarget ? "inset 0 0 0 1px hsla(var(--primary) / 0.5)" : "none",
18542
19154
  opacity: dimmedByRerun ? 0.35 : 1,
18543
19155
  pointerEvents: dimmedByRerun ? "none" : "auto"
@@ -18546,22 +19158,17 @@ var TimelineRow = ({
18546
19158
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
18547
19159
  import_material26.Box,
18548
19160
  {
18549
- onClick: isProcessing ? void 0 : onToggle,
19161
+ onClick: onToggle,
18550
19162
  sx: {
18551
19163
  display: "flex",
18552
19164
  alignItems: "center",
18553
19165
  gap: 1.5,
18554
- px: 2,
18555
- py: 1.25,
18556
- cursor: isProcessing ? "default" : "pointer",
18557
- "--timeline-bar-color": barColor,
18558
- "&:hover": isProcessing ? {} : {
18559
- bgcolor: "hsl(var(--muted) / 0.4)",
18560
- "--timeline-bar-color": hoverBarColor
18561
- }
19166
+ p: 1.5,
19167
+ cursor: "pointer",
19168
+ userSelect: "none"
18562
19169
  },
18563
19170
  children: [
18564
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isRerunTarget ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.CircularProgress, { size: 14, sx: { color: "hsl(var(--primary))" } }) : isProcessing ? isLikelyTimedOut ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: "No new activity for over a minute \u2014 this run has most likely timed out.", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { display: "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.AlertTriangle, { size: 14, color: STATUS_COLORS.warning }) }) }) : isLiveProcessing ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.CircularProgress, { size: 12, sx: { color: "hsl(var(--muted-foreground))" } }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 6, height: 6, borderRadius: "50%", bgcolor: "hsl(var(--muted-foreground) / 0.5)" } }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(StatusIcon, { status: effectiveStatus, resumeAtMs: scheduledResumeMs }) }),
19171
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isRerunTarget ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.CircularProgress, { size: 14, sx: { color: "hsl(var(--primary))" } }) : isProcessing ? isLikelyTimedOut ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: "No new activity for over a minute \u2014 this run has most likely timed out.", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { display: "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.AlertTriangle, { size: 14, color: STATUS_COLORS.warning }) }) }) : isLiveProcessing ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.CircularProgress, { size: 12, sx: { color: "hsl(var(--muted-foreground))" } }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 6, height: 6, borderRadius: "50%", bgcolor: "hsl(var(--muted-foreground) / 0.5)" } }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(StatusIcon, { status: effectiveStatus, resumeAtMs: scheduledResumeMs, authBlockedApp: isRowAuthBlocked ? rowAuthReq.appName : null }) }),
18565
19172
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isProcessing ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 22 } }) : toolApp?.icon ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: (toolApp.name || "").replace(/_/g, " "), arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Avatar, { src: toolApp.icon, sx: { width: 22, height: 22, bgcolor: "transparent" }, variant: "rounded" }) }) : item.category === "finalise" || details?.action === "finish" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: "Final answer", arrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.Check, { size: 18 }) }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { width: 22 } }) }),
18566
19173
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
18567
19174
  import_material26.Tooltip,
@@ -19080,6 +19687,7 @@ var AgentUI = ({
19080
19687
  composeSubmitInput: propComposeSubmitInput,
19081
19688
  contextParams,
19082
19689
  incidentId: propIncidentId,
19690
+ incidentContext: propIncidentContext,
19083
19691
  vulnerabilityId: propVulnerabilityId,
19084
19692
  workflowId: propWorkflowId
19085
19693
  }) => {
@@ -19094,6 +19702,10 @@ var AgentUI = ({
19094
19702
  return h;
19095
19703
  }, [apiKey, orgId]);
19096
19704
  const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
19705
+ const resolvedIncidentId = propIncidentId || (contextCategory === "incidents" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveIncidentId : void 0);
19706
+ const resolvedIncidentContext = propIncidentContext || (typeof window !== "undefined" ? window.__shuffleActiveIncidentContext : void 0);
19707
+ const resolvedVulnerabilityId = propVulnerabilityId || (contextCategory === "vulnerabilities" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveVulnerabilityId : void 0);
19708
+ const resolvedWorkflowId = propWorkflowId || (contextCategory === "workflows" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveWorkflowId : void 0);
19097
19709
  const isPhoneScreen = (0, import_material26.useMediaQuery)("(max-width:600px)", { noSsr: true });
19098
19710
  const isPhone = mobileView !== void 0 ? mobileView : isPhoneScreen;
19099
19711
  const [actionInput, setActionInput] = (0, import_react24.useState)(() => {
@@ -19174,17 +19786,37 @@ var AgentUI = ({
19174
19786
  if (!match || match.enabled === false) return;
19175
19787
  setSelectedPreset(match);
19176
19788
  if (defaultApps === void 0 && !apps) {
19789
+ const resolved = resolvePresetApps(match);
19177
19790
  const override = readPresetAppsOverride(match.id);
19178
- if (override) {
19179
- setChosenApps(override);
19180
- } else if (match.defaultApps && match.defaultApps.length > 0) {
19181
- setChosenApps(match.defaultApps.map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon })));
19791
+ if (override && override.length > 0) {
19792
+ const merged = [...override];
19793
+ for (const app2 of resolved) {
19794
+ const key = (app2.id || app2.name).toLowerCase();
19795
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
19796
+ merged.push(app2);
19797
+ }
19798
+ }
19799
+ setChosenApps(merged);
19800
+ } else {
19801
+ setChosenApps(resolved);
19182
19802
  }
19183
19803
  }
19184
19804
  seededPresetIdRef.current = match.id;
19185
19805
  } catch {
19186
19806
  }
19187
19807
  }, [presets, defaultInput, isEffectiveSupport, initialPresetId, defaultApps, apps]);
19808
+ (0, import_react24.useEffect)(() => {
19809
+ const handleToolsChanged = () => {
19810
+ const targetPreset = selectedPreset || AGENT_PRESETS.find((p) => p.id === "incident-response") || AGENT_PRESETS[0];
19811
+ if (targetPreset) {
19812
+ const next = resolvePresetApps(targetPreset);
19813
+ setChosenApps(next);
19814
+ writePresetAppsOverride(targetPreset.id, next);
19815
+ }
19816
+ };
19817
+ window.addEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
19818
+ return () => window.removeEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
19819
+ }, [selectedPreset]);
19188
19820
  (0, import_react24.useLayoutEffect)(() => {
19189
19821
  if (hidePresets) {
19190
19822
  setPresetsChipWidth(0);
@@ -19462,13 +20094,19 @@ var AgentUI = ({
19462
20094
  localStorage.setItem(LAST_PRESET_STORAGE_KEY, preset.id);
19463
20095
  } catch {
19464
20096
  }
20097
+ const resolved = resolvePresetApps(preset);
19465
20098
  const override = readPresetAppsOverride(preset.id);
19466
20099
  if (override && override.length > 0) {
19467
- setChosenApps(override);
19468
- } else if (preset.defaultApps && preset.defaultApps.length > 0) {
19469
- setChosenApps(preset.defaultApps.map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon })));
20100
+ const merged = [...override];
20101
+ for (const app2 of resolved) {
20102
+ const key = (app2.id || app2.name).toLowerCase();
20103
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
20104
+ merged.push(app2);
20105
+ }
20106
+ }
20107
+ setChosenApps(merged);
19470
20108
  } else {
19471
- setChosenApps([]);
20109
+ setChosenApps(resolved);
19472
20110
  }
19473
20111
  seededPresetIdRef.current = preset.id;
19474
20112
  if (onSelectPreset) {
@@ -19686,9 +20324,9 @@ var AgentUI = ({
19686
20324
  }, [availableApps]);
19687
20325
  const pendingAuthApps = (0, import_react24.useMemo)(() => {
19688
20326
  if (authAppsLoading) return [];
19689
- const decisions = agentData?.decisions || [];
19690
20327
  const seen = /* @__PURE__ */ new Set();
19691
20328
  const out = [];
20329
+ const decisions = agentData?.decisions || [];
19692
20330
  for (const d of decisions) {
19693
20331
  const req = extractAuthRequest(d);
19694
20332
  if (!req) continue;
@@ -19700,8 +20338,21 @@ var AgentUI = ({
19700
20338
  const icon = appsById[req.appName]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
19701
20339
  out.push({ appName: req.appName, appId, icon });
19702
20340
  }
20341
+ const hasAllowed = Array.isArray(agentData?.allowed_actions) && agentData.allowed_actions.length > 0;
20342
+ const activeAppList = hasAllowed ? executionApps : chosenApps;
20343
+ for (const app2 of activeAppList) {
20344
+ if (!app2?.name) continue;
20345
+ const slug = normalizeAgentAppName(app2.name);
20346
+ if (seen.has(slug)) continue;
20347
+ if (appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name, app2.id || null)) {
20348
+ seen.add(slug);
20349
+ const appId = app2.id || appsById[app2.name]?.id || appsById[slug]?.id || null;
20350
+ const icon = app2.icon || appsById[app2.name]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
20351
+ out.push({ appName: app2.name, appId, icon });
20352
+ }
20353
+ }
19703
20354
  return out;
19704
- }, [agentData, appsById, authAppsLoading, isAppAuthenticated]);
20355
+ }, [agentData, executionApps, chosenApps, appsById, authAppsLoading, isAppAuthenticated]);
19705
20356
  (0, import_react24.useEffect)(() => {
19706
20357
  if (apps) setChosenApps(apps);
19707
20358
  }, [apps]);
@@ -20316,9 +20967,6 @@ var AgentUI = ({
20316
20967
  return next;
20317
20968
  }, { replace: true });
20318
20969
  }
20319
- const resolvedIncidentId = propIncidentId || (contextCategory === "incidents" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveIncidentId : void 0);
20320
- const resolvedVulnerabilityId = propVulnerabilityId || (contextCategory === "vulnerabilities" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveVulnerabilityId : void 0);
20321
- const resolvedWorkflowId = propWorkflowId || (contextCategory === "workflows" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveWorkflowId : void 0);
20322
20970
  const result = await runAgent({
20323
20971
  input: composed.trim(),
20324
20972
  skipPolling: true,
@@ -20327,6 +20975,7 @@ var AgentUI = ({
20327
20975
  ...apiBaseUrl ? { apiBaseUrl } : {},
20328
20976
  ...orgId ? { orgId } : {},
20329
20977
  ...resolvedIncidentId ? { incidentId: resolvedIncidentId } : {},
20978
+ ...resolvedIncidentContext ? { incidentContext: resolvedIncidentContext } : {},
20330
20979
  ...resolvedVulnerabilityId ? { vulnerabilityId: resolvedVulnerabilityId } : {},
20331
20980
  ...resolvedWorkflowId ? { workflowId: resolvedWorkflowId } : {},
20332
20981
  // Send a single comma-separated `tool_name` in the format
@@ -20397,6 +21046,13 @@ var AgentUI = ({
20397
21046
  const auth = raw?.authorization;
20398
21047
  if (eid && auth) {
20399
21048
  activeExecutionIdRef.current = eid;
21049
+ if (typeof window !== "undefined") {
21050
+ window.dispatchEvent(
21051
+ new CustomEvent("shuffle:agent_execution_status", {
21052
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
21053
+ })
21054
+ );
21055
+ }
20400
21056
  if (contextStorageKey) {
20401
21057
  setPageContextChoice(contextStorageKey, {
20402
21058
  draftPrompt: "",
@@ -20984,17 +21640,30 @@ var AgentUI = ({
20984
21640
  if (status === "FINISHED" || status === "SUCCESS") {
20985
21641
  window.dispatchEvent(
20986
21642
  new CustomEvent("shuffle:agent_execution_status", {
20987
- detail: { executionId: eid, status: "completed" }
21643
+ detail: { executionId: eid, status: "completed", incidentId: resolvedIncidentId }
20988
21644
  })
20989
21645
  );
21646
+ if (resolvedIncidentId) {
21647
+ window.dispatchEvent(
21648
+ new CustomEvent("incident:refresh", {
21649
+ detail: { id: resolvedIncidentId, incidentId: resolvedIncidentId, executionId: eid }
21650
+ })
21651
+ );
21652
+ }
20990
21653
  } else if (["FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(status)) {
20991
21654
  window.dispatchEvent(
20992
21655
  new CustomEvent("shuffle:agent_execution_status", {
20993
- detail: { executionId: eid, status: "failed" }
21656
+ detail: { executionId: eid, status: "failed", incidentId: resolvedIncidentId }
21657
+ })
21658
+ );
21659
+ } else if (["RUNNING", "EXECUTING", "IN_PROGRESS", "WAITING"].includes(status)) {
21660
+ window.dispatchEvent(
21661
+ new CustomEvent("shuffle:agent_execution_status", {
21662
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
20994
21663
  })
20995
21664
  );
20996
21665
  }
20997
- }, [execution?.execution_id, execution?.status, agentData?.status]);
21666
+ }, [execution?.execution_id, execution?.status, agentData?.status, resolvedIncidentId]);
20998
21667
  (0, import_react24.useEffect)(() => {
20999
21668
  if (!finishDecisionId || agentRequestLoading) return;
21000
21669
  if (continuationFocusedForRef.current === finishDecisionId) return;
@@ -23192,7 +23861,47 @@ var AgentUI = ({
23192
23861
  children: formatAppDisplayName(app2.name || "")
23193
23862
  }
23194
23863
  ),
23195
- (needsAuth || isUnavailable) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.AlertTriangle, { size: 14, color: "hsl(var(--severity-medium))", style: { marginRight: 2 } }),
23864
+ needsAuth ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23865
+ import_material26.Box,
23866
+ {
23867
+ component: "span",
23868
+ sx: {
23869
+ fontSize: "0.65rem",
23870
+ fontWeight: 600,
23871
+ color: "hsl(var(--destructive))",
23872
+ bgcolor: "hsl(var(--destructive) / 0.12)",
23873
+ border: "1px solid hsl(var(--destructive) / 0.3)",
23874
+ borderRadius: 1,
23875
+ px: 0.6,
23876
+ py: 0.1,
23877
+ letterSpacing: "0.02em",
23878
+ textTransform: "uppercase",
23879
+ ml: 0.5,
23880
+ mr: 0.25
23881
+ },
23882
+ children: "Missing auth"
23883
+ }
23884
+ ) : isUnavailable ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23885
+ import_material26.Box,
23886
+ {
23887
+ component: "span",
23888
+ sx: {
23889
+ fontSize: "0.65rem",
23890
+ fontWeight: 600,
23891
+ color: "hsl(var(--severity-medium))",
23892
+ bgcolor: "hsl(var(--severity-medium) / 0.12)",
23893
+ border: "1px solid hsl(var(--severity-medium) / 0.3)",
23894
+ borderRadius: 1,
23895
+ px: 0.6,
23896
+ py: 0.1,
23897
+ letterSpacing: "0.02em",
23898
+ textTransform: "uppercase",
23899
+ ml: 0.5,
23900
+ mr: 0.25
23901
+ },
23902
+ children: "Unavailable"
23903
+ }
23904
+ ) : null,
23196
23905
  isRequired ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23197
23906
  import_lucide_react15.Lock,
23198
23907
  {
@@ -23394,43 +24103,83 @@ var AgentUI = ({
23394
24103
  return list;
23395
24104
  })().map((app2, i) => {
23396
24105
  const slug = normalizeAgentAppName(app2.name || "");
24106
+ const appNeedsAuth = !authAppsLoading && appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name || "", app2.id || null);
23397
24107
  const appIcon = app2.icon || availableApps.find((a) => normalizeAgentAppName(a.name || "") === slug)?.icon || resolvedToolApps[slug]?.icon;
23398
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Tooltip, { title: formatAppDisplayName(app2.name || ""), children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23399
- import_material26.Box,
24108
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
24109
+ import_material26.Tooltip,
23400
24110
  {
23401
- onClick: () => setAuthDrawerApp({ name: app2.name, id: app2.id || null }),
23402
- sx: {
23403
- display: "inline-flex",
23404
- alignItems: "center",
23405
- justifyContent: "center",
23406
- width: 24,
23407
- height: 24,
23408
- borderRadius: "6px",
23409
- overflow: "hidden",
23410
- bgcolor: "hsl(var(--muted))",
23411
- cursor: "pointer",
23412
- transition: "transform 0.15s ease, border-color 0.15s ease",
23413
- "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
23414
- },
24111
+ title: appNeedsAuth ? `${formatAppDisplayName(app2.name || "")} \u2014 Missing authentication (Click to connect)` : formatAppDisplayName(app2.name || ""),
23415
24112
  children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23416
- AppFallbackIcon,
24113
+ import_material26.Box,
23417
24114
  {
23418
- name: app2.name,
23419
- imageUrl: appIcon,
23420
- size: 24,
23421
- style: { borderRadius: 6, objectFit: "contain" }
24115
+ onClick: () => setAuthDrawerApp({ name: app2.name, id: app2.id || null }),
24116
+ sx: {
24117
+ display: "inline-flex",
24118
+ alignItems: "center",
24119
+ justifyContent: "center",
24120
+ width: 24,
24121
+ height: 24,
24122
+ borderRadius: "6px",
24123
+ overflow: "hidden",
24124
+ bgcolor: "hsl(var(--muted))",
24125
+ cursor: "pointer",
24126
+ transition: "transform 0.15s ease, border-color 0.15s ease",
24127
+ border: appNeedsAuth ? "2px solid hsl(var(--destructive)) !important" : "none",
24128
+ boxShadow: appNeedsAuth ? "0 0 0 1px hsl(var(--destructive) / 0.4)" : "none",
24129
+ "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
24130
+ },
24131
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
24132
+ AppFallbackIcon,
24133
+ {
24134
+ name: app2.name,
24135
+ imageUrl: appIcon,
24136
+ size: 24,
24137
+ style: { borderRadius: 6, objectFit: "contain" }
24138
+ }
24139
+ )
23422
24140
  }
23423
24141
  )
23424
- }
23425
- ) }, i);
24142
+ },
24143
+ i
24144
+ );
23426
24145
  }) }),
23427
24146
  /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Box, { sx: { flex: 1, minWidth: 0 }, children: [
23428
24147
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Typography, { sx: { fontSize: "0.85rem", color: "hsl(var(--foreground))", fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: extractCleanDisplayPrompt(agentData?.original_input) || actionInput || "Agent run" }),
23429
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Typography, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))" }, children: [
23430
- "Status: ",
23431
- execution?.status || agentData?.status || "\u2014",
23432
- " \xB7 ",
23433
- execution?.execution_id?.slice(0, 8) || ""
24148
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Typography, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))", display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap", mt: 0.25 }, children: [
24149
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { children: [
24150
+ "Status: ",
24151
+ execution?.status || agentData?.status || "\u2014",
24152
+ " \xB7 ",
24153
+ execution?.execution_id?.slice(0, 8) || ""
24154
+ ] }),
24155
+ pendingAuthApps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
24156
+ import_material26.Box,
24157
+ {
24158
+ component: "span",
24159
+ onClick: () => setAuthDrawerApp({ name: pendingAuthApps[0].appName, id: pendingAuthApps[0].appId }),
24160
+ sx: {
24161
+ display: "inline-flex",
24162
+ alignItems: "center",
24163
+ gap: 0.5,
24164
+ px: 0.75,
24165
+ py: 0.15,
24166
+ borderRadius: 1,
24167
+ bgcolor: "hsl(var(--destructive) / 0.12)",
24168
+ border: "1px solid hsl(var(--destructive) / 0.35)",
24169
+ color: "hsl(var(--destructive))",
24170
+ fontSize: "0.68rem",
24171
+ fontWeight: 600,
24172
+ cursor: "pointer",
24173
+ textTransform: "none",
24174
+ "&:hover": { bgcolor: "hsl(var(--destructive) / 0.2)" }
24175
+ },
24176
+ children: [
24177
+ "Missing Auth: ",
24178
+ pendingAuthApps.map((a) => formatAppDisplayName(a.appName)).join(", "),
24179
+ " \u2014 Connect"
24180
+ ]
24181
+ }
24182
+ )
23434
24183
  ] })
23435
24184
  ] }),
23436
24185
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AgentAttachmentsButton_default, { attachments: llmImageAttachments }),
@@ -23610,6 +24359,57 @@ var AgentUI = ({
23610
24359
  }
23611
24360
  }
23612
24361
  ),
24362
+ pendingAuthApps.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
24363
+ import_material26.Box,
24364
+ {
24365
+ sx: {
24366
+ mb: 2,
24367
+ p: 2,
24368
+ borderRadius: 2,
24369
+ border: "1px solid hsla(var(--severity-medium) / 0.35)",
24370
+ bgcolor: "hsla(var(--severity-medium) / 0.08)",
24371
+ display: "flex",
24372
+ alignItems: "center",
24373
+ justifyContent: "space-between",
24374
+ gap: 2,
24375
+ flexWrap: "wrap"
24376
+ },
24377
+ children: [
24378
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1, minWidth: 260 }, children: [
24379
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.Lock, { size: 22, color: "hsl(var(--severity-medium))" }),
24380
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Box, { sx: { flex: 1, minWidth: 0 }, children: [
24381
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Typography, { sx: { fontSize: "0.875rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: pendingAuthApps.length === 1 ? `${formatAppDisplayName(pendingAuthApps[0].appName)} requires authentication` : `${pendingAuthApps.map((a) => formatAppDisplayName(a.appName)).join(", ")} require authentication` }),
24382
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Typography, { sx: { fontSize: "0.78rem", color: "hsl(var(--muted-foreground))" }, children: pendingAuthApps.length === 1 ? `The agent cannot complete steps using ${formatAppDisplayName(pendingAuthApps[0].appName)} and may remain pending until connected.` : `The agent cannot complete steps using these tools and may remain pending until connected.` })
24383
+ ] })
24384
+ ] }),
24385
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: { display: "flex", gap: 1, flexWrap: "wrap" }, children: pendingAuthApps.map(({ appName, appId }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
24386
+ import_material26.Button,
24387
+ {
24388
+ variant: "outlined",
24389
+ size: "small",
24390
+ onClick: () => setAuthDrawerApp({ name: appName, id: appId }),
24391
+ sx: {
24392
+ borderColor: "hsla(var(--severity-medium) / 0.6)",
24393
+ color: "hsl(var(--foreground))",
24394
+ textTransform: "none",
24395
+ fontSize: "0.75rem",
24396
+ fontWeight: 600,
24397
+ height: 32,
24398
+ "&:hover": {
24399
+ bgcolor: "hsla(var(--severity-medium) / 0.15)",
24400
+ borderColor: "hsl(var(--severity-medium))"
24401
+ }
24402
+ },
24403
+ children: [
24404
+ "Authenticate ",
24405
+ formatAppDisplayName(appName)
24406
+ ]
24407
+ },
24408
+ appName
24409
+ )) })
24410
+ ]
24411
+ }
24412
+ ),
23613
24413
  viewMode === "simple" && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_material26.Box, { sx: {
23614
24414
  borderRadius: 2,
23615
24415
  border: "1px solid hsl(var(--border))",
@@ -23651,7 +24451,7 @@ var AgentUI = ({
23651
24451
  }
23652
24452
  const pendingAnswered = pendingQuestions.every((q) => questionAnswers[q.question]?.value);
23653
24453
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
23654
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
24454
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23655
24455
  RunFinishedSummary,
23656
24456
  {
23657
24457
  status,
@@ -23664,77 +24464,7 @@ var AgentUI = ({
23664
24464
  durationSec,
23665
24465
  showMeta: true,
23666
24466
  bottomContent: aiAuthSuggestionNode,
23667
- children: [
23668
- pendingAuthApps.map(({ appName, appId, icon }) => {
23669
- const pretty = appName.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
23670
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
23671
- import_material26.Box,
23672
- {
23673
- sx: {
23674
- display: "flex",
23675
- alignItems: "center",
23676
- gap: 1.5,
23677
- p: 1.5,
23678
- borderRadius: 1.5,
23679
- border: "1px solid hsla(var(--severity-medium) / 0.3)",
23680
- bgcolor: "hsla(var(--severity-medium) / 0.08)"
23681
- },
23682
- children: [
23683
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react15.Lock, { size: 22, color: "hsl(var(--severity-medium))" }),
23684
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Box, { sx: { flex: 1, minWidth: 0 }, children: [
23685
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Typography, { sx: { fontSize: "0.85rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: [
23686
- pretty,
23687
- " requires authentication"
23688
- ] }),
23689
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_material26.Typography, { sx: { fontSize: "0.75rem", color: "hsl(var(--muted-foreground))" }, children: [
23690
- "Connect your ",
23691
- pretty,
23692
- " account so the agent can complete this step, then rerun."
23693
- ] })
23694
- ] }),
23695
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
23696
- import_material26.Button,
23697
- {
23698
- variant: "outlined",
23699
- size: "small",
23700
- startIcon: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
23701
- import_material26.Avatar,
23702
- {
23703
- src: icon || void 0,
23704
- alt: "",
23705
- variant: "rounded",
23706
- sx: {
23707
- width: 18,
23708
- height: 18,
23709
- borderRadius: 0.5,
23710
- bgcolor: "hsl(var(--background) / 0.4)",
23711
- color: "hsl(var(--background))",
23712
- fontSize: "0.7rem",
23713
- fontWeight: 700,
23714
- "& img": { objectFit: "contain" }
23715
- },
23716
- children: pretty.charAt(0)
23717
- }
23718
- ),
23719
- onClick: () => setAuthDrawerApp({ name: appName, id: appId }),
23720
- sx: {
23721
- height: 36,
23722
- textTransform: "none",
23723
- fontWeight: 600
23724
- },
23725
- children: [
23726
- "Authenticate ",
23727
- pretty
23728
- ]
23729
- }
23730
- )
23731
- ]
23732
- },
23733
- `auth-${appName}`
23734
- );
23735
- }),
23736
- !isRunning && postRunDiscovery
23737
- ]
24467
+ children: !isRunning && postRunDiscovery
23738
24468
  }
23739
24469
  ),
23740
24470
  !finishAnswer && pendingAsk && pendingQuestions.length > 0 ? (() => {
@@ -28014,6 +28744,8 @@ var AskAiSidePanel = ({
28014
28744
  defaultInput,
28015
28745
  serverside,
28016
28746
  colorMode,
28747
+ incidentId: propIncidentId,
28748
+ incidentContext: propIncidentContext,
28017
28749
  sx
28018
28750
  }) => {
28019
28751
  const themeScope = useShuffleMcpTheme();
@@ -28136,11 +28868,15 @@ var AskAiSidePanel = ({
28136
28868
  }, [open, initialTab, onTabChange]);
28137
28869
  const [activeTaskId, setActiveTaskId] = (0, import_react34.useState)(null);
28138
28870
  const [activeExecutionId, setActiveExecutionId] = (0, import_react34.useState)(null);
28871
+ const [activeIncidentId, setActiveIncidentId] = (0, import_react34.useState)(null);
28872
+ const [activeIncidentContext, setActiveIncidentContext] = (0, import_react34.useState)(null);
28139
28873
  const [runResetKey, setRunResetKey] = (0, import_react34.useState)(0);
28140
28874
  (0, import_react34.useEffect)(() => {
28141
28875
  if (!open) {
28142
28876
  setActiveTaskId(null);
28143
28877
  setActiveExecutionId(null);
28878
+ setActiveIncidentId(null);
28879
+ setActiveIncidentContext(null);
28144
28880
  }
28145
28881
  }, [open]);
28146
28882
  (0, import_react34.useEffect)(() => {
@@ -28172,6 +28908,12 @@ var AskAiSidePanel = ({
28172
28908
  } else if (!detail?.tab) {
28173
28909
  setActiveTaskId(null);
28174
28910
  }
28911
+ if (detail?.incidentId !== void 0) {
28912
+ setActiveIncidentId(detail.incidentId || null);
28913
+ }
28914
+ if (detail?.incidentContext !== void 0) {
28915
+ setActiveIncidentContext(detail.incidentContext || null);
28916
+ }
28175
28917
  if (detail?.resetExecution) {
28176
28918
  setActiveExecutionId(null);
28177
28919
  setRunResetKey((k) => k + 1);
@@ -28805,6 +29547,8 @@ var AskAiSidePanel = ({
28805
29547
  onAppsChange: handleAppsChange,
28806
29548
  onSelectPreset: handleSelectPreset,
28807
29549
  onChooseLLM: () => handleTabChange("localLLM"),
29550
+ incidentId: activeIncidentId || propIncidentId || agentUIProps?.incidentId,
29551
+ incidentContext: activeIncidentContext || propIncidentContext || agentUIProps?.incidentContext,
28808
29552
  apiBaseUrl: globalUrl || agentUIProps?.apiBaseUrl,
28809
29553
  theme: effectiveTheme,
28810
29554
  sx: {