@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.mjs CHANGED
@@ -2411,6 +2411,7 @@ var deleteDatastoreItems = async (keys2, category) => {
2411
2411
  };
2412
2412
  var DATASTORE_CATEGORIES = {
2413
2413
  INCIDENTS: "shuffle-security_incidents",
2414
+ EVENTS: "shuffle-security_events",
2414
2415
  VULNERABILITIES: "shuffle-security_vulns",
2415
2416
  VULNS: "shuffle-security_vulns",
2416
2417
  ASSETS: "shuffle-security_assets",
@@ -3080,7 +3081,7 @@ var applyValidationStaleness = (data) => {
3080
3081
  });
3081
3082
  };
3082
3083
  var doFetch2 = async (crossOrgId) => {
3083
- if (!hasShuffleAuth()) return [];
3084
+ if (!hasShuffleAuth()) return { data: [], failed: false };
3084
3085
  const headers = {
3085
3086
  ...getAuthHeader(crossOrgId ?? void 0)
3086
3087
  };
@@ -3089,12 +3090,13 @@ var doFetch2 = async (crossOrgId) => {
3089
3090
  credentials: "include",
3090
3091
  headers
3091
3092
  });
3092
- if (!resp.ok) return [];
3093
+ if (!resp.ok) return { data: [], failed: true };
3093
3094
  const result = await resp.json();
3094
3095
  const data = result?.data || result;
3095
- return Array.isArray(data) ? applyValidationStaleness(data) : [];
3096
+ if (!Array.isArray(data)) return { data: [], failed: true };
3097
+ return { data: applyValidationStaleness(data), failed: false };
3096
3098
  } catch {
3097
- return [];
3099
+ return { data: [], failed: true };
3098
3100
  }
3099
3101
  };
3100
3102
  var fetchAuthenticatedApps = (crossOrgId) => {
@@ -3104,12 +3106,17 @@ var fetchAuthenticatedApps = (crossOrgId) => {
3104
3106
  return Promise.resolve(entry.data);
3105
3107
  }
3106
3108
  if (entry.promise) return entry.promise;
3107
- const promise = doFetch2(crossOrgId).then((data) => {
3108
- cache2.set(key, { data, fetchedAt: Date.now() });
3109
- return data;
3110
- }).catch((err) => {
3109
+ const promise = doFetch2(crossOrgId).then((outcome) => {
3110
+ if (outcome.failed) {
3111
+ const previous = cache2.get(key)?.data;
3112
+ cache2.delete(key);
3113
+ return previous || [];
3114
+ }
3115
+ cache2.set(key, { data: outcome.data, fetchedAt: Date.now() });
3116
+ return outcome.data;
3117
+ }).catch(() => {
3111
3118
  cache2.delete(key);
3112
- throw err;
3119
+ return [];
3113
3120
  });
3114
3121
  cache2.set(key, { ...entry, promise });
3115
3122
  return promise;
@@ -8502,30 +8509,237 @@ function AppDetailContent({
8502
8509
 
8503
8510
  // drawerLayer.ts
8504
8511
  import { useEffect as useEffect8, useState as useState10 } from "react";
8512
+ var STACK_KEY = "__shuffleOverlayStack";
8505
8513
  var COUNTER_KEY = "__shuffleDrawerLayerTop";
8506
- var DRAWER_LAYER_BASE = 10011;
8507
- var STEP = 10;
8508
- var getTop = (base3) => {
8509
- const store = globalThis;
8510
- const current = store[COUNTER_KEY];
8511
- return typeof current === "number" ? current : base3;
8512
- };
8513
- var useDrawerLayer = (open, base3 = DRAWER_LAYER_BASE) => {
8514
- const [zIndex, setZIndex] = useState10(base3);
8514
+ var AUTO_LAYER_KEY = "__shuffleOverlayAutoLayerInstalled";
8515
+ var OVERLAY_BASE = 10010;
8516
+ var DRAWER_LAYER_BASE = OVERLAY_BASE;
8517
+ var SURFACE_STEP = 20;
8518
+ var POPUP_OFFSET = 6;
8519
+ var TOOLTIP_OFFSET = 12;
8520
+ var getStore = () => globalThis;
8521
+ var getOverlayStack = () => {
8522
+ const store = getStore();
8523
+ if (!Array.isArray(store[STACK_KEY])) {
8524
+ store[STACK_KEY] = [];
8525
+ }
8526
+ return store[STACK_KEY];
8527
+ };
8528
+ var getTopSurfaceZIndex = (base3 = OVERLAY_BASE) => {
8529
+ const stack = getOverlayStack();
8530
+ const surfaces = stack.filter((r) => r.type === "surface");
8531
+ if (surfaces.length === 0) {
8532
+ const store = getStore();
8533
+ store[COUNTER_KEY] = base3;
8534
+ return base3;
8535
+ }
8536
+ let maxZ = base3;
8537
+ for (const s of surfaces) {
8538
+ if (s.zIndex > maxZ) {
8539
+ maxZ = s.zIndex;
8540
+ }
8541
+ }
8542
+ getStore()[COUNTER_KEY] = maxZ;
8543
+ return maxZ;
8544
+ };
8545
+ var syncGlobalCounter = (base3 = OVERLAY_BASE) => {
8546
+ getTopSurfaceZIndex(base3);
8547
+ };
8548
+ var allocateSurfaceLayer = (id, element2, base3 = OVERLAY_BASE) => {
8549
+ const stack = getOverlayStack();
8550
+ const existing = stack.find((r) => r.id === id || element2 && r.element === element2);
8551
+ if (existing) {
8552
+ return existing.zIndex;
8553
+ }
8554
+ const currentTop = getTopSurfaceZIndex(base3);
8555
+ const nextZ = currentTop + SURFACE_STEP;
8556
+ stack.push({ id, element: element2, zIndex: nextZ, type: "surface" });
8557
+ syncGlobalCounter(base3);
8558
+ return nextZ;
8559
+ };
8560
+ var releaseOverlayLayer = (idOrElement) => {
8561
+ const stack = getOverlayStack();
8562
+ const index = stack.findIndex(
8563
+ (r) => r.id === idOrElement || typeof idOrElement !== "string" && r.element === idOrElement
8564
+ );
8565
+ if (index !== -1) {
8566
+ stack.splice(index, 1);
8567
+ }
8568
+ syncGlobalCounter();
8569
+ };
8570
+ var bringSurfaceToFront = (idOrElement) => {
8571
+ const stack = getOverlayStack();
8572
+ const record = stack.find(
8573
+ (r) => r.id === idOrElement || typeof idOrElement !== "string" && r.element === idOrElement
8574
+ );
8575
+ if (!record || record.type !== "surface") {
8576
+ return typeof idOrElement === "string" ? allocateSurfaceLayer(idOrElement, null) : allocateSurfaceLayer("surface_" + Math.random().toString(36).substring(2, 9), idOrElement);
8577
+ }
8578
+ const currentTop = getTopSurfaceZIndex();
8579
+ if (record.zIndex >= currentTop) {
8580
+ return record.zIndex;
8581
+ }
8582
+ record.zIndex = currentTop + SURFACE_STEP;
8583
+ syncGlobalCounter();
8584
+ return record.zIndex;
8585
+ };
8586
+ var useOverlayLayer = (open, options) => {
8587
+ const base3 = options?.base ?? OVERLAY_BASE;
8588
+ const [zIndex, setZIndex] = useState10(() => open ? getTopSurfaceZIndex(base3) + SURFACE_STEP : base3);
8515
8589
  useEffect8(() => {
8516
8590
  if (!open) return;
8517
- const store = globalThis;
8518
- const next = Math.max(base3, getTop(base3) + STEP);
8519
- store[COUNTER_KEY] = next;
8520
- setZIndex(next);
8591
+ const id = "hook_" + Math.random().toString(36).substring(2, 9);
8592
+ const allocated = allocateSurfaceLayer(id, null, base3);
8593
+ setZIndex(allocated);
8521
8594
  return () => {
8522
- if (store[COUNTER_KEY] === next) {
8523
- store[COUNTER_KEY] = next - STEP;
8524
- }
8595
+ releaseOverlayLayer(id);
8525
8596
  };
8526
8597
  }, [open, base3]);
8527
8598
  return zIndex;
8528
8599
  };
8600
+ var useDrawerLayer = (open, base3 = DRAWER_LAYER_BASE) => useOverlayLayer(open, { base: base3 });
8601
+ 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;
8602
+ var isSurfaceElement = (el) => {
8603
+ if (!(el instanceof HTMLElement)) return false;
8604
+ 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]"));
8605
+ };
8606
+ var isChildPopupElement = (el) => {
8607
+ if (!(el instanceof HTMLElement)) return false;
8608
+ 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");
8609
+ };
8610
+ var isTooltipElement = (el) => {
8611
+ if (!(el instanceof HTMLElement)) return false;
8612
+ return el.classList.contains("MuiTooltip-popper") || el.getAttribute("role") === "tooltip";
8613
+ };
8614
+ var isElementOpen = (el) => {
8615
+ if (el.getAttribute("aria-hidden") === "true") return false;
8616
+ if (el.getAttribute("data-state") === "closed") return false;
8617
+ if (el.classList.contains("MuiModal-hidden")) return false;
8618
+ const style = el.style;
8619
+ if (style.display === "none" || style.visibility === "hidden") return false;
8620
+ return true;
8621
+ };
8622
+ var observerInstance = null;
8623
+ var installGlobalOverlayAutoLayer = () => {
8624
+ if (typeof window === "undefined" || typeof document === "undefined") return;
8625
+ const store = getStore();
8626
+ if (store[AUTO_LAYER_KEY]) return;
8627
+ store[AUTO_LAYER_KEY] = true;
8628
+ const handleElementOpen = (el) => {
8629
+ if (!isShuffleOwnedOverlay(el)) return;
8630
+ if (isSurfaceElement(el)) {
8631
+ let layerId = el.dataset.shuffleLayerId;
8632
+ if (!layerId) {
8633
+ layerId = "dom_" + Math.random().toString(36).substring(2, 9);
8634
+ el.dataset.shuffleLayerId = layerId;
8635
+ }
8636
+ const targetZ = allocateSurfaceLayer(layerId, el);
8637
+ el.dataset.shuffleLayerZ = String(targetZ);
8638
+ el.style.setProperty("z-index", String(targetZ), "important");
8639
+ const dialogContent = el.querySelector('[role="dialog"], [role="alertdialog"]');
8640
+ if (dialogContent && dialogContent !== el) {
8641
+ dialogContent.style.setProperty("z-index", String(targetZ), "important");
8642
+ }
8643
+ return;
8644
+ }
8645
+ if (isChildPopupElement(el)) {
8646
+ const topZ = getTopSurfaceZIndex();
8647
+ const popupZ = topZ + POPUP_OFFSET;
8648
+ el.dataset.shuffleLayerZ = String(popupZ);
8649
+ el.style.setProperty("z-index", String(popupZ), "important");
8650
+ return;
8651
+ }
8652
+ if (isTooltipElement(el)) {
8653
+ const topZ = getTopSurfaceZIndex();
8654
+ const tooltipZ = topZ + TOOLTIP_OFFSET;
8655
+ el.dataset.shuffleLayerZ = String(tooltipZ);
8656
+ el.style.setProperty("z-index", String(tooltipZ), "important");
8657
+ return;
8658
+ }
8659
+ };
8660
+ const handleElementClose = (el) => {
8661
+ const layerId = el.dataset.shuffleLayerId;
8662
+ if (layerId) {
8663
+ releaseOverlayLayer(layerId);
8664
+ delete el.dataset.shuffleLayerId;
8665
+ delete el.dataset.shuffleLayerZ;
8666
+ } else {
8667
+ releaseOverlayLayer(el);
8668
+ }
8669
+ };
8670
+ const scanNode = (node) => {
8671
+ if (!(node instanceof HTMLElement)) return;
8672
+ if (isSurfaceElement(node) || isChildPopupElement(node) || isTooltipElement(node)) {
8673
+ if (isElementOpen(node)) {
8674
+ handleElementOpen(node);
8675
+ } else {
8676
+ handleElementClose(node);
8677
+ }
8678
+ }
8679
+ const children2 = node.children;
8680
+ for (let i = 0; i < children2.length; i++) {
8681
+ const child = children2[i];
8682
+ if (child instanceof HTMLElement) {
8683
+ if (isSurfaceElement(child) || isChildPopupElement(child) || isTooltipElement(child)) {
8684
+ if (isElementOpen(child)) {
8685
+ handleElementOpen(child);
8686
+ } else {
8687
+ handleElementClose(child);
8688
+ }
8689
+ }
8690
+ }
8691
+ }
8692
+ };
8693
+ observerInstance = new MutationObserver((mutations) => {
8694
+ for (const m of mutations) {
8695
+ if (m.type === "childList") {
8696
+ m.addedNodes.forEach(scanNode);
8697
+ m.removedNodes.forEach((node) => {
8698
+ if (node instanceof HTMLElement) {
8699
+ handleElementClose(node);
8700
+ }
8701
+ });
8702
+ } else if (m.type === "attributes") {
8703
+ const target = m.target;
8704
+ if (target instanceof HTMLElement) {
8705
+ scanNode(target);
8706
+ }
8707
+ }
8708
+ }
8709
+ });
8710
+ const body = document.body;
8711
+ if (body) {
8712
+ observerInstance.observe(body, {
8713
+ childList: true,
8714
+ subtree: true,
8715
+ attributes: true,
8716
+ attributeFilter: ["class", "style", "aria-hidden", "data-state"]
8717
+ });
8718
+ Array.from(body.children).forEach(scanNode);
8719
+ }
8720
+ document.addEventListener(
8721
+ "pointerdown",
8722
+ (e) => {
8723
+ const target = e.target;
8724
+ if (!target) return;
8725
+ const surface = target.closest(
8726
+ '.MuiDialog-root, .MuiDrawer-root, .MuiModal-root:not(.MuiPopover-root):not(.MuiMenu-root), [role="dialog"], [role="alertdialog"]'
8727
+ );
8728
+ if (!surface || !surface.dataset.shuffleLayerId) return;
8729
+ const currentZ = Number(surface.dataset.shuffleLayerZ || 0);
8730
+ const topZ = getTopSurfaceZIndex();
8731
+ if (currentZ > 0 && currentZ < topZ) {
8732
+ const newZ = bringSurfaceToFront(surface.dataset.shuffleLayerId);
8733
+ surface.dataset.shuffleLayerZ = String(newZ);
8734
+ surface.style.setProperty("z-index", String(newZ), "important");
8735
+ }
8736
+ },
8737
+ true
8738
+ );
8739
+ };
8740
+ if (typeof window !== "undefined") {
8741
+ installGlobalOverlayAutoLayer();
8742
+ }
8529
8743
 
8530
8744
  // views/AppDetailDrawer.tsx
8531
8745
  import { jsx as jsx17 } from "react/jsx-runtime";
@@ -8986,6 +9200,11 @@ var ShuffleMCP = React4.forwardRef(({
8986
9200
  const [isOpen, setIsOpen] = useState11(false);
8987
9201
  const [selectedIndex, setSelectedIndex] = useState11(-1);
8988
9202
  const [internalSelectedApps, setInternalSelectedApps] = useState11(selectedApps);
9203
+ useEffect9(() => {
9204
+ if (selectedApps) {
9205
+ setInternalSelectedApps(selectedApps);
9206
+ }
9207
+ }, [selectedApps]);
8989
9208
  const [authenticatedApps, setAuthenticatedApps] = useState11(externalAuthenticatedApps || []);
8990
9209
  const [authenticatedAppsLoading, setAuthenticatedAppsLoading] = useState11(!externalAuthenticatedApps);
8991
9210
  const [drawerApp, setDrawerApp] = useState11(null);
@@ -10181,6 +10400,7 @@ var AddAppDialog = ({
10181
10400
  maxLength = 1024,
10182
10401
  initialInput = ""
10183
10402
  }) => {
10403
+ const dialogZIndex = useOverlayLayer(open);
10184
10404
  const [input, setInput] = useState12(initialInput);
10185
10405
  const [stage, setStage] = useState12("idle");
10186
10406
  const [spec, setSpec] = useState12(null);
@@ -10347,6 +10567,12 @@ var AddAppDialog = ({
10347
10567
  onClose: () => onOpenChange(false),
10348
10568
  fullWidth: true,
10349
10569
  maxWidth: "sm",
10570
+ sx: {
10571
+ zIndex: dialogZIndex,
10572
+ "& .MuiBackdrop-root": {
10573
+ zIndex: dialogZIndex
10574
+ }
10575
+ },
10350
10576
  PaperProps: {
10351
10577
  sx: {
10352
10578
  maxWidth: 640,
@@ -10355,7 +10581,8 @@ var AddAppDialog = ({
10355
10581
  color: "hsl(var(--foreground))",
10356
10582
  border: "1px solid hsl(var(--border))",
10357
10583
  borderRadius: 2,
10358
- boxSizing: "border-box"
10584
+ boxSizing: "border-box",
10585
+ zIndex: dialogZIndex
10359
10586
  }
10360
10587
  },
10361
10588
  children: [
@@ -11403,6 +11630,8 @@ var AiAgentPromptsEditor = ({
11403
11630
  prompts,
11404
11631
  apps,
11405
11632
  readOnly = false,
11633
+ skillLabel,
11634
+ isBuiltInApp,
11406
11635
  onChangePrompt,
11407
11636
  onRemovePrompt,
11408
11637
  onAddPrompt,
@@ -11490,16 +11719,44 @@ var AiAgentPromptsEditor = ({
11490
11719
  ] }),
11491
11720
  /* @__PURE__ */ jsxs15(Box14, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
11492
11721
  /* @__PURE__ */ jsx22(
11493
- Typography12,
11722
+ Tooltip8,
11494
11723
  {
11495
- sx: {
11496
- fontSize: "0.65rem",
11497
- fontWeight: 600,
11498
- color: "hsl(var(--muted-foreground))",
11499
- textTransform: "uppercase",
11500
- letterSpacing: "0.05em"
11501
- },
11502
- children: "Allowed apps"
11724
+ 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.",
11725
+ children: /* @__PURE__ */ jsxs15(Box14, { sx: { display: "inline-flex", alignItems: "center", gap: 0.75 }, children: [
11726
+ /* @__PURE__ */ jsx22(
11727
+ Typography12,
11728
+ {
11729
+ sx: {
11730
+ fontSize: "0.65rem",
11731
+ fontWeight: 600,
11732
+ color: "hsl(var(--muted-foreground))",
11733
+ textTransform: "uppercase",
11734
+ letterSpacing: "0.05em"
11735
+ },
11736
+ children: "Allowed apps"
11737
+ }
11738
+ ),
11739
+ skillLabel && /* @__PURE__ */ jsxs15(
11740
+ Typography12,
11741
+ {
11742
+ component: "span",
11743
+ sx: {
11744
+ fontSize: "0.62rem",
11745
+ fontWeight: 600,
11746
+ color: "hsl(var(--primary))",
11747
+ bgcolor: "hsl(var(--primary) / 0.1)",
11748
+ px: 0.6,
11749
+ py: 0.1,
11750
+ borderRadius: 0.75,
11751
+ letterSpacing: "0.02em"
11752
+ },
11753
+ children: [
11754
+ skillLabel,
11755
+ " permissions"
11756
+ ]
11757
+ }
11758
+ )
11759
+ ] })
11503
11760
  }
11504
11761
  ),
11505
11762
  /* @__PURE__ */ jsxs15(Box14, { sx: { display: "flex", alignItems: "center", gap: 0.5, flexWrap: "wrap", flex: 1 }, children: [
@@ -11508,8 +11765,9 @@ var AiAgentPromptsEditor = ({
11508
11765
  const meta = resolveAppMeta(appKey);
11509
11766
  const displayName2 = meta.name;
11510
11767
  const img = meta.image || `https://shuffler.io/images/apps/${displayName2}.png`;
11768
+ const isBuiltIn = isBuiltInApp ? isBuiltInApp(appKey) : false;
11511
11769
  const clickable = !readOnly && !!onRemoveApp;
11512
- const tip = clickable ? `Remove ${displayName2.replace(/_/g, " ")}` : displayName2.replace(/_/g, " ");
11770
+ const tip = isBuiltIn ? `${displayName2.replace(/_/g, " ")} (Default built-in app for ${skillLabel || "skill"})` : clickable ? `Remove ${displayName2.replace(/_/g, " ")} (Assigned permission)` : displayName2.replace(/_/g, " ");
11513
11771
  return /* @__PURE__ */ jsx22(Tooltip8, { title: tip, children: /* @__PURE__ */ jsx22(
11514
11772
  IconButton7,
11515
11773
  {
@@ -11519,12 +11777,12 @@ var AiAgentPromptsEditor = ({
11519
11777
  sx: {
11520
11778
  width: 26,
11521
11779
  height: 26,
11522
- border: "1px solid hsl(var(--severity-low) / 0.3)",
11523
- bgcolor: "hsl(var(--severity-low) / 0.1)",
11780
+ border: isBuiltIn ? "1px solid hsl(var(--primary) / 0.35)" : "1px solid hsl(var(--severity-low) / 0.3)",
11781
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)",
11524
11782
  borderRadius: 1,
11525
11783
  "&.Mui-disabled": {
11526
11784
  opacity: 1,
11527
- bgcolor: "hsl(var(--severity-low) / 0.1)"
11785
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)"
11528
11786
  },
11529
11787
  "&:hover": clickable ? {
11530
11788
  bgcolor: "hsl(var(--destructive) / 0.15)",
@@ -11543,7 +11801,7 @@ var AiAgentPromptsEditor = ({
11543
11801
  }
11544
11802
  ) }, appKey);
11545
11803
  }),
11546
- !readOnly && onAddAppRequested && /* @__PURE__ */ jsx22(Tooltip8, { title: "Add allowed app", children: /* @__PURE__ */ jsx22(
11804
+ !readOnly && onAddAppRequested && /* @__PURE__ */ jsx22(Tooltip8, { title: skillLabel ? `Assign tools to ${skillLabel}` : "Add allowed app", children: /* @__PURE__ */ jsx22(
11547
11805
  IconButton7,
11548
11806
  {
11549
11807
  size: "small",
@@ -12325,7 +12583,7 @@ var AGENT_PRESETS = [
12325
12583
  icon: /* @__PURE__ */ jsx25(ShieldAlert, { size: 16 }),
12326
12584
  enabled: true,
12327
12585
  tag: "Beta",
12328
- defaultApps: [{ name: "shuffle_incidents" }, { name: "shuffle_datastore" }]
12586
+ defaultApps: [{ name: "shuffle_incidents" }]
12329
12587
  },
12330
12588
  {
12331
12589
  id: "host-monitor-control",
@@ -12786,6 +13044,150 @@ var AgentPresets = ({ variant = "default", onSelectPreset, selectedPreset, onRem
12786
13044
  };
12787
13045
  var AgentPresets_default = AgentPresets;
12788
13046
 
13047
+ // ../lib/agentTools.ts
13048
+ var STORAGE_KEY3 = "agent_tools_config";
13049
+ var AGENT_TOOLS_CHANGED_EVENT = "agent-tools-changed";
13050
+ var DEFAULT_AGENT = "default";
13051
+ var DEFAULT_ACTION_TYPE = "timeline_reply";
13052
+ var getActiveOrgId = () => {
13053
+ if (typeof window === "undefined") return null;
13054
+ try {
13055
+ const raw = localStorage.getItem("shuffle_user_info") || localStorage.getItem("userinfo") || localStorage.getItem("user_info");
13056
+ if (!raw) return null;
13057
+ const parsed = JSON.parse(raw);
13058
+ return parsed?.active_org?.id || parsed?.org_id || parsed?.active_org_id || Array.isArray(parsed?.orgs) && parsed.orgs[0]?.id || parsed?.id || null;
13059
+ } catch {
13060
+ return null;
13061
+ }
13062
+ };
13063
+ var getStorageKey = (orgId) => {
13064
+ const resolved = orgId || getActiveOrgId();
13065
+ return resolved ? `${STORAGE_KEY3}_${resolved}` : STORAGE_KEY3;
13066
+ };
13067
+ var coerceTool = (raw) => {
13068
+ if (typeof raw === "string") {
13069
+ const trimmed = raw.trim();
13070
+ if (!trimmed) return null;
13071
+ return { name: trimmed, id: trimmed };
13072
+ }
13073
+ if (raw && typeof raw === "object") {
13074
+ const obj = raw;
13075
+ const name = typeof obj.name === "string" ? obj.name.trim() : "";
13076
+ const id = typeof obj.id === "string" && obj.id.trim() ? obj.id.trim() : name;
13077
+ if (!name) return null;
13078
+ return { name, id };
13079
+ }
13080
+ return null;
13081
+ };
13082
+ var sanitize2 = (parsed) => {
13083
+ let target = parsed;
13084
+ if (target && typeof target === "object" && !Array.isArray(target)) {
13085
+ const obj = target;
13086
+ if (Array.isArray(obj.entries)) {
13087
+ target = obj.entries;
13088
+ }
13089
+ }
13090
+ if (!Array.isArray(target)) return [];
13091
+ return target.filter((e) => e && typeof e.agent === "string" && typeof e.actionType === "string" && Array.isArray(e.tools)).map((e) => ({
13092
+ agent: e.agent,
13093
+ actionType: e.actionType,
13094
+ tools: e.tools.map(coerceTool).filter((t) => !!t),
13095
+ updatedAt: typeof e.updatedAt === "number" ? e.updatedAt : void 0
13096
+ }));
13097
+ };
13098
+ var extractUpdatedAt = (parsed) => {
13099
+ if (parsed && typeof parsed === "object") {
13100
+ const obj = parsed;
13101
+ if (typeof obj.updatedAt === "number") return obj.updatedAt;
13102
+ }
13103
+ return 0;
13104
+ };
13105
+ var readCacheRecord = () => {
13106
+ if (typeof window === "undefined") return { entries: [], updatedAt: 0 };
13107
+ try {
13108
+ const key = getStorageKey();
13109
+ let raw = localStorage.getItem(key);
13110
+ let parsed = null;
13111
+ let entries = [];
13112
+ let updatedAt = 0;
13113
+ if (raw) {
13114
+ try {
13115
+ parsed = JSON.parse(raw);
13116
+ entries = sanitize2(parsed);
13117
+ updatedAt = extractUpdatedAt(parsed) || entries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0);
13118
+ } catch {
13119
+ }
13120
+ }
13121
+ if (entries.length === 0 || entries.every((e) => e.tools.length === 0)) {
13122
+ if (key !== STORAGE_KEY3) {
13123
+ const fallbackRaw = localStorage.getItem(STORAGE_KEY3);
13124
+ if (fallbackRaw) {
13125
+ try {
13126
+ const fallbackParsed = JSON.parse(fallbackRaw);
13127
+ const fallbackEntries = sanitize2(fallbackParsed);
13128
+ if (fallbackEntries.some((e) => e.tools.length > 0)) {
13129
+ entries = fallbackEntries;
13130
+ updatedAt = extractUpdatedAt(fallbackParsed) || fallbackEntries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0) || Date.now();
13131
+ writeCache(entries, updatedAt);
13132
+ }
13133
+ } catch {
13134
+ }
13135
+ }
13136
+ }
13137
+ }
13138
+ return { entries, updatedAt };
13139
+ } catch {
13140
+ return { entries: [], updatedAt: 0 };
13141
+ }
13142
+ };
13143
+ var readAll = () => readCacheRecord().entries;
13144
+ var writeCache = (entries, explicitUpdatedAt) => {
13145
+ if (typeof window === "undefined") return;
13146
+ try {
13147
+ const updatedAt = explicitUpdatedAt ?? Date.now();
13148
+ const payload = {
13149
+ version: 1,
13150
+ updatedAt,
13151
+ entries
13152
+ };
13153
+ const serialized = JSON.stringify(payload);
13154
+ const orgKey = getStorageKey();
13155
+ localStorage.setItem(orgKey, serialized);
13156
+ if (orgKey !== STORAGE_KEY3) {
13157
+ localStorage.setItem(STORAGE_KEY3, serialized);
13158
+ }
13159
+ window.dispatchEvent(
13160
+ new CustomEvent(AGENT_TOOLS_CHANGED_EVENT, { detail: { updatedAt, entries } })
13161
+ );
13162
+ } catch {
13163
+ }
13164
+ };
13165
+ var getAgentTools = (agent = DEFAULT_AGENT, actionType = DEFAULT_ACTION_TYPE) => {
13166
+ const all = readAll();
13167
+ const entry = all.find((e) => e.agent === agent && e.actionType === actionType);
13168
+ if (entry && entry.tools && entry.tools.length > 0) {
13169
+ return entry.tools;
13170
+ }
13171
+ if (agent === "incident-handler" || agent === "incident-response" || agent === DEFAULT_AGENT) {
13172
+ const found = all.find(
13173
+ (e) => (e.agent === "incident-handler" || e.agent === "incident-response" || e.agent === DEFAULT_AGENT) && e.actionType === actionType && e.tools && e.tools.length > 0
13174
+ );
13175
+ if (found?.tools && found.tools.length > 0) return found.tools;
13176
+ }
13177
+ return [];
13178
+ };
13179
+ var getToolsForSkill = (skillOrPresetId) => {
13180
+ const normalized = (skillOrPresetId || "").toLowerCase().trim();
13181
+ if (normalized === "incident-handler" || normalized === "incident-response" || normalized === "default") {
13182
+ const ih = getAgentTools("incident-handler");
13183
+ if (ih.length > 0) return ih;
13184
+ const ir = getAgentTools("incident-response");
13185
+ if (ir.length > 0) return ir;
13186
+ return getAgentTools(DEFAULT_AGENT);
13187
+ }
13188
+ return getAgentTools(normalized);
13189
+ };
13190
+
12789
13191
  // useAgentPromptPrefix.ts
12790
13192
  import { useCallback as useCallback9, useEffect as useEffect14, useRef as useRef10, useState as useState16 } from "react";
12791
13193
  var AGENT_PROMPT_PREFIX_CATEGORY = "agent-prompt-prefix";
@@ -13005,6 +13407,9 @@ var runAgent = async (request) => {
13005
13407
  if (request.incidentId) {
13006
13408
  input.incident_id = request.incidentId;
13007
13409
  }
13410
+ if (request.incidentContext) {
13411
+ input.incident_context = request.incidentContext;
13412
+ }
13008
13413
  if (request.vulnerabilityId) {
13009
13414
  input.vulnerability_id = request.vulnerabilityId;
13010
13415
  }
@@ -13283,16 +13688,143 @@ var getCachedGroupDocs = (groupId, folder) => {
13283
13688
  }));
13284
13689
  };
13285
13690
 
13691
+ // ../lib/incidentPromptContext.ts
13692
+ var GLOBAL_INCIDENT_KEY = "__shuffleActiveIncidentContext";
13693
+ var getGlobalScope = () => {
13694
+ if (typeof globalThis !== "undefined") return globalThis;
13695
+ if (typeof window !== "undefined") return window;
13696
+ if (typeof global !== "undefined") return global;
13697
+ return null;
13698
+ };
13699
+ var getActiveIncidentPromptContext = () => {
13700
+ const scope = getGlobalScope();
13701
+ if (!scope) return null;
13702
+ const info = scope[GLOBAL_INCIDENT_KEY];
13703
+ if (info && typeof info === "object") {
13704
+ return info;
13705
+ }
13706
+ return null;
13707
+ };
13708
+ var INCIDENT_PROMPT_DELIMITER_START = "=== INCIDENT CONTEXT ===";
13709
+ var INCIDENT_PROMPT_DELIMITER_END = "=== END INCIDENT CONTEXT ===";
13710
+ var formatObservableType = (type) => {
13711
+ if (!type) return "Indicator";
13712
+ const clean = type.toLowerCase().trim();
13713
+ switch (clean) {
13714
+ case "ip":
13715
+ case "ipv4":
13716
+ case "ip_address":
13717
+ return "IPv4";
13718
+ case "ipv6":
13719
+ return "IPv6";
13720
+ case "hash":
13721
+ case "sha256":
13722
+ case "file_hash":
13723
+ return "SHA256";
13724
+ case "md5":
13725
+ return "MD5";
13726
+ case "sha1":
13727
+ return "SHA1";
13728
+ case "hostname":
13729
+ case "host":
13730
+ case "endpoint":
13731
+ return "Hostname";
13732
+ case "domain":
13733
+ return "Domain";
13734
+ case "url":
13735
+ return "URL";
13736
+ case "user":
13737
+ case "username":
13738
+ case "account":
13739
+ return "User";
13740
+ case "email":
13741
+ return "Email";
13742
+ case "process":
13743
+ case "process_name":
13744
+ return "Process";
13745
+ case "file":
13746
+ case "filename":
13747
+ return "File";
13748
+ default:
13749
+ return type.charAt(0).toUpperCase() + type.slice(1);
13750
+ }
13751
+ };
13752
+ var isIncidentInjectedPrompt = (prompt) => {
13753
+ if (!prompt || typeof prompt !== "string") return false;
13754
+ return prompt.includes(INCIDENT_PROMPT_DELIMITER_START) || prompt.includes("OPERATIONAL DIRECTIVES:") || prompt.includes("INCIDENT OBSERVABLES / IOCs:");
13755
+ };
13756
+ var extractCleanIncidentPrompt = (prompt) => {
13757
+ if (!prompt || typeof prompt !== "string") return "";
13758
+ const trimmed = prompt.trim();
13759
+ const taskMatch = trimmed.match(/TASK TO EXECUTE:\s*\n\s*-\s*Task:\s*([^\n]+)/i);
13760
+ if (taskMatch && taskMatch[1]?.trim()) {
13761
+ return `Task: ${taskMatch[1].trim()}`;
13762
+ }
13763
+ const legacyMatch = trimmed.match(/\n\s*Task:\s*([^\n]+)/i);
13764
+ if (legacyMatch && legacyMatch[1]?.trim()) {
13765
+ return `Task: ${legacyMatch[1].trim()}`;
13766
+ }
13767
+ if (trimmed.includes(INCIDENT_PROMPT_DELIMITER_START)) {
13768
+ const before = trimmed.split(INCIDENT_PROMPT_DELIMITER_START)[0]?.trim();
13769
+ if (before) return before;
13770
+ }
13771
+ return trimmed;
13772
+ };
13773
+ var composeIncidentPromptInput = (rawInput, context) => {
13774
+ if (!rawInput || typeof rawInput !== "string") return "";
13775
+ const trimmed = rawInput.trim();
13776
+ if (isIncidentInjectedPrompt(trimmed)) {
13777
+ return trimmed;
13778
+ }
13779
+ const ctx = context || getActiveIncidentPromptContext();
13780
+ if (!ctx || !ctx.id) {
13781
+ return trimmed;
13782
+ }
13783
+ const incidentRef = ctx.id ? `#${ctx.id}` : "";
13784
+ const incidentTitle = ctx.title?.trim() || "Incident";
13785
+ const severity = ctx.severity || "Medium";
13786
+ const status = ctx.status || "In Progress";
13787
+ const description = ctx.description?.trim() || "No description provided.";
13788
+ const seenObservables = /* @__PURE__ */ new Set();
13789
+ const formattedObservables = [];
13790
+ if (Array.isArray(ctx.observables)) {
13791
+ for (const obs of ctx.observables) {
13792
+ if (!obs || obs.archived || !obs.value?.trim()) continue;
13793
+ const val = obs.value.trim();
13794
+ const typeLabel = formatObservableType(obs.type);
13795
+ const key = `${typeLabel.toLowerCase()}:${val.toLowerCase()}`;
13796
+ if (seenObservables.has(key)) continue;
13797
+ seenObservables.add(key);
13798
+ formattedObservables.push(`- ${typeLabel}: ${val}`);
13799
+ }
13800
+ }
13801
+ const observablesBlock = formattedObservables.length > 0 ? formattedObservables.slice(0, 50).join("\n") : "- None recorded yet";
13802
+ return `${trimmed}
13803
+
13804
+ ${INCIDENT_PROMPT_DELIMITER_START}
13805
+ INCIDENT CONTEXT:
13806
+ - Incident: ${incidentRef} ("${incidentTitle}")
13807
+ - Severity: ${severity} | Status: ${status}
13808
+ - Summary: ${description}
13809
+
13810
+ INCIDENT OBSERVABLES / IOCs:
13811
+ ${observablesBlock}
13812
+ ${INCIDENT_PROMPT_DELIMITER_END}
13813
+
13814
+ DIRECTIVES:
13815
+ - Relevant incident details and observables are provided above. Do not call "get_incident" unless raw external logs are required.`;
13816
+ };
13817
+
13286
13818
  // ../lib/docsPromptContext.ts
13287
13819
  var GLOBAL_DOC_KEY = "__shuffleActiveDocInfo";
13288
- var getGlobalScope = () => {
13820
+ var getGlobalScope2 = () => {
13289
13821
  if (typeof globalThis !== "undefined") return globalThis;
13290
13822
  if (typeof window !== "undefined") return window;
13291
13823
  if (typeof global !== "undefined") return global;
13292
13824
  return null;
13293
13825
  };
13294
13826
  var getActiveDocPromptContext = () => {
13295
- const scope = getGlobalScope();
13827
+ const scope = getGlobalScope2();
13296
13828
  if (!scope) return null;
13297
13829
  const info = scope[GLOBAL_DOC_KEY];
13298
13830
  if (info && typeof info === "object") {
@@ -13333,6 +13865,9 @@ var isDocInjectedPrompt = (prompt) => {
13333
13865
  var extractCleanDisplayPrompt = (prompt) => {
13334
13866
  if (!prompt || typeof prompt !== "string") return "";
13335
13867
  const trimmed = prompt.trim();
13868
+ if (isIncidentInjectedPrompt(trimmed)) {
13869
+ return extractCleanIncidentPrompt(trimmed);
13870
+ }
13336
13871
  if (!isDocInjectedPrompt(trimmed)) return trimmed;
13337
13872
  if (trimmed.includes(DOC_PROMPT_DELIMITER_END)) {
13338
13873
  const parts = trimmed.split(DOC_PROMPT_DELIMITER_END);
@@ -13372,7 +13907,7 @@ var composeDocPromptInput = (userQuestion, pathname, fallbackTitle, overrideDocI
13372
13907
  return trimmedQuestion;
13373
13908
  }
13374
13909
  const activeDoc = overrideDocInfo ?? getActiveDocPromptContext();
13375
- const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
13910
+ const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope2()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
13376
13911
  const title = normalizeDocPromptTitle(rawTitle);
13377
13912
  const groupLabel = activeDoc?.groupLabel;
13378
13913
  const groupId = activeDoc?.groupId;
@@ -16023,6 +16558,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16023
16558
  const cleanId = formatEntityDisplayId(params.id);
16024
16559
  return `Investigate incident ${cleanId} and recommend next steps: `;
16025
16560
  },
16561
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16026
16562
  placeholder: "Ask about this incident, triage observables, or correlate...",
16027
16563
  getStorageKey: (params) => `incident_${params.id}`,
16028
16564
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -16047,6 +16583,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16047
16583
  const cleanId = formatEntityDisplayId(params.id);
16048
16584
  return `Investigate incident ${cleanId} and recommend next steps: `;
16049
16585
  },
16586
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16050
16587
  placeholder: "Ask about this incident, triage observables, or correlate...",
16051
16588
  getStorageKey: (params) => `incident_${params.id}`,
16052
16589
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -16069,6 +16606,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16069
16606
  const cleanId = formatEntityDisplayId(params.id);
16070
16607
  return `Investigate case ${cleanId} and recommend next steps: `;
16071
16608
  },
16609
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16072
16610
  placeholder: "Review case evidence, correlate events, or recommend response actions...",
16073
16611
  getStorageKey: (params) => `case_${params.id}`,
16074
16612
  description: "Focused on the currently viewed case with Shuffle Incidents MCP"
@@ -16799,6 +17337,18 @@ var readPresetAppsOverride = (presetId) => {
16799
17337
  return null;
16800
17338
  }
16801
17339
  };
17340
+ var resolvePresetApps = (preset) => {
17341
+ const baseApps = (preset.defaultApps || []).map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon }));
17342
+ const assigned = getToolsForSkill(preset.id);
17343
+ const merged = [...baseApps];
17344
+ for (const t of assigned) {
17345
+ const key = (t.id || t.name).toLowerCase();
17346
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
17347
+ merged.push({ name: t.name, id: t.id, icon: t.icon || void 0 });
17348
+ }
17349
+ }
17350
+ return merged;
17351
+ };
16802
17352
  var writePresetAppsOverride = (presetId, apps) => {
16803
17353
  try {
16804
17354
  const raw = localStorage.getItem(PRESET_APPS_STORAGE_KEY);
@@ -17177,8 +17727,12 @@ var extractAuthRequest = (decision) => {
17177
17727
  } else if (raw && typeof raw === "object") {
17178
17728
  parsed = raw;
17179
17729
  }
17180
- const needsAuth = parsed && (parsed.action === "app_authentication" || parsed.app_authentication === true);
17181
- if (!needsAuth) return null;
17730
+ const candidateObjects = [
17731
+ parsed,
17732
+ decision?.result,
17733
+ decision?.run_details,
17734
+ decision
17735
+ ].filter(Boolean);
17182
17736
  let toolAppName;
17183
17737
  let appId = null;
17184
17738
  if (typeof decision?.tool === "string") {
@@ -17191,8 +17745,36 @@ var extractAuthRequest = (decision) => {
17191
17745
  toolAppName = t;
17192
17746
  }
17193
17747
  }
17194
- let appName = parsed.app || parsed.app_name || parsed.appname;
17195
- if (!appName) appName = toolAppName;
17748
+ let needsAuth = false;
17749
+ let candidateAppName;
17750
+ for (const obj of candidateObjects) {
17751
+ if (obj.action === "app_authentication" || obj.app_authentication === true || obj.action === "authenticate" || obj.needs_auth === true || obj.auth_required === true) {
17752
+ needsAuth = true;
17753
+ }
17754
+ const candidate = obj.app || obj.app_name || obj.appname;
17755
+ if (typeof candidate === "string" && candidate.trim()) {
17756
+ candidateAppName = candidate.trim();
17757
+ }
17758
+ }
17759
+ const textSources = [
17760
+ decision?.error,
17761
+ decision?.reason,
17762
+ decision?.status_message,
17763
+ decision?.message,
17764
+ decision?.run_details?.error,
17765
+ typeof raw === "string" ? raw : ""
17766
+ ];
17767
+ const combinedText = textSources.filter(Boolean).join(" ").toLowerCase();
17768
+ 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")) {
17769
+ needsAuth = true;
17770
+ }
17771
+ if (!needsAuth && (decision?.status === "WAITING" || decision?.status === "PENDING" || decision?.run_details?.status === "WAITING" || decision?.run_details?.status === "PENDING")) {
17772
+ if (toolAppName && appRequiresAuthentication(toolAppName)) {
17773
+ needsAuth = true;
17774
+ }
17775
+ }
17776
+ if (!needsAuth) return null;
17777
+ let appName = candidateAppName || toolAppName;
17196
17778
  if (!appName) {
17197
17779
  const f = (decision?.fields || []).find((x) => x?.key === "app" || x?.key === "app_name");
17198
17780
  if (f?.value) appName = f.value;
@@ -17207,12 +17789,17 @@ var STATUS_COLORS = {
17207
17789
  running: "hsl(var(--primary))"
17208
17790
  };
17209
17791
  var TERMINAL_RUN_STATUSES = ["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"];
17210
- var resolveRunStatus = (executionStatus, agentStatus) => {
17211
- const exec = String(executionStatus || "").toUpperCase();
17212
- const agent = String(agentStatus || "").toUpperCase();
17213
- if (TERMINAL_RUN_STATUSES.includes(exec)) return exec;
17214
- if (TERMINAL_RUN_STATUSES.includes(agent)) return agent;
17215
- return exec || agent || "";
17792
+ var resolveRunStatus = (execStatus, agentStatus) => {
17793
+ const e = (execStatus || "").toUpperCase();
17794
+ const a = (agentStatus || "").toUpperCase();
17795
+ if (e === "FINISHED" || a === "FINISHED") return "FINISHED";
17796
+ if (e === "FAILURE" || a === "FAILURE") return "FAILURE";
17797
+ if (e === "ABORTED" || a === "ABORTED") return "ABORTED";
17798
+ if (e === "CANCELLED" || a === "CANCELLED" || e === "CANCELED" || a === "CANCELED") return "CANCELLED";
17799
+ if (e === "WAITING" || a === "WAITING") return "WAITING";
17800
+ if (e === "PENDING" || a === "PENDING") return "PENDING";
17801
+ if (e === "RUNNING" || a === "RUNNING" || e === "EXECUTING" || a === "EXECUTING") return "RUNNING";
17802
+ return e || a || "FINISHED";
17216
17803
  };
17217
17804
  var buildToolName = (apps) => {
17218
17805
  if (!apps.length) return "API";
@@ -17236,7 +17823,11 @@ var DurationCountdown = ({ resumeAtMs }) => {
17236
17823
  const remaining = resumeAtMs - nowMs;
17237
17824
  return /* @__PURE__ */ jsx31(Tooltip14, { title: `Scheduled to continue at ${new Date(resumeAtMs).toLocaleString()}`, arrow: true, children: /* @__PURE__ */ jsx31(Box22, { component: "span", sx: { whiteSpace: "nowrap", cursor: "default" }, children: remaining > 0 ? `in ${formatTimeLeft(remaining)}` : "due now" }) });
17238
17825
  };
17239
- var StatusIcon = ({ status, resumeAtMs }) => {
17826
+ var StatusIcon = ({
17827
+ status,
17828
+ resumeAtMs,
17829
+ authBlockedApp
17830
+ }) => {
17240
17831
  const s = (status || "").toUpperCase();
17241
17832
  const isScheduledWait = s === "WAITING" && !!resumeAtMs;
17242
17833
  const [nowMs, setNowMs] = useState20(() => Date.now());
@@ -17247,7 +17838,10 @@ var StatusIcon = ({ status, resumeAtMs }) => {
17247
17838
  }, [isScheduledWait]);
17248
17839
  let node;
17249
17840
  let label;
17250
- if (s === "RUNNING" || s === "EXECUTING" || s === "") {
17841
+ if (authBlockedApp) {
17842
+ node = /* @__PURE__ */ jsx31(LockIcon3, { size: 20, color: "hsl(var(--destructive))" });
17843
+ label = `Authentication required for ${formatAppDisplayName(authBlockedApp)} \u2014 step cannot proceed until connected`;
17844
+ } else if (s === "RUNNING" || s === "EXECUTING" || s === "") {
17251
17845
  node = /* @__PURE__ */ jsx31(CircularProgress5, { size: 18, sx: { color: STATUS_COLORS.running } });
17252
17846
  label = "Running";
17253
17847
  } else if (s === "WAITING") {
@@ -17446,8 +18040,10 @@ var TimelineRow = ({
17446
18040
  const s = (effectiveStatus || "").toUpperCase();
17447
18041
  return s === "WAITING" || s === "RUNNING" || s === "EXECUTING" || s === "";
17448
18042
  })();
17449
- const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : isFailed ? STATUS_COLORS.error : "hsl(var(--muted-foreground) / 0.35)";
17450
- const hoverBarColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : effectiveStatus === "FINISHED" || effectiveStatus === "IGNORED" ? STATUS_COLORS.finished : isFailed ? STATUS_COLORS.error : STATUS_COLORS.running;
18043
+ const rowAuthReq = extractAuthRequest(details);
18044
+ const isRowAuthBlocked = !!rowAuthReq && !isAppAuthenticated?.(rowAuthReq.appName, rowAuthReq.appId) && (effectiveStatus === "WAITING" || effectiveStatus === "PENDING" || effectiveStatus === "FAILURE" || effectiveStatus === "ABORTED");
18045
+ const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : isFailed || isRowAuthBlocked ? STATUS_COLORS.error : "hsl(var(--muted-foreground) / 0.35)";
18046
+ const hoverBarColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : effectiveStatus === "FINISHED" || effectiveStatus === "IGNORED" ? STATUS_COLORS.finished : isFailed || isRowAuthBlocked ? STATUS_COLORS.error : STATUS_COLORS.running;
17451
18047
  const isRerunTarget = !!rerunningDecisionId && item.type === "decision" && details?.run_details?.id === rerunningDecisionId;
17452
18048
  return /* @__PURE__ */ jsxs24(
17453
18049
  Box22,
@@ -17456,9 +18052,25 @@ var TimelineRow = ({
17456
18052
  sx: {
17457
18053
  borderTop: index === 0 ? "none" : "1px solid hsl(var(--border))",
17458
18054
  bgcolor: highlight ? "hsla(var(--severity-medium) / 0.12)" : isRerunTarget ? "hsla(var(--primary) / 0.08)" : open ? "hsl(var(--muted) / 0.3)" : "transparent",
17459
- transition: "background 0.6s ease, box-shadow 0.6s ease, opacity 0.2s ease",
17460
- scrollMarginTop: 96,
18055
+ transition: "background-color 0.2s ease",
18056
+ "&:hover": {
18057
+ bgcolor: "hsl(var(--muted) / 0.4)"
18058
+ },
17461
18059
  position: "relative",
18060
+ "&::before": {
18061
+ content: '""',
18062
+ position: "absolute",
18063
+ left: 0,
18064
+ top: 0,
18065
+ bottom: 0,
18066
+ width: 3,
18067
+ bgcolor: barColor,
18068
+ transition: "background-color 0.15s ease"
18069
+ },
18070
+ "&:hover::before": {
18071
+ bgcolor: hoverBarColor
18072
+ },
18073
+ scrollMarginTop: 96,
17462
18074
  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",
17463
18075
  opacity: dimmedByRerun ? 0.35 : 1,
17464
18076
  pointerEvents: dimmedByRerun ? "none" : "auto"
@@ -17467,22 +18079,17 @@ var TimelineRow = ({
17467
18079
  /* @__PURE__ */ jsxs24(
17468
18080
  Box22,
17469
18081
  {
17470
- onClick: isProcessing ? void 0 : onToggle,
18082
+ onClick: onToggle,
17471
18083
  sx: {
17472
18084
  display: "flex",
17473
18085
  alignItems: "center",
17474
18086
  gap: 1.5,
17475
- px: 2,
17476
- py: 1.25,
17477
- cursor: isProcessing ? "default" : "pointer",
17478
- "--timeline-bar-color": barColor,
17479
- "&:hover": isProcessing ? {} : {
17480
- bgcolor: "hsl(var(--muted) / 0.4)",
17481
- "--timeline-bar-color": hoverBarColor
17482
- }
18087
+ p: 1.5,
18088
+ cursor: "pointer",
18089
+ userSelect: "none"
17483
18090
  },
17484
18091
  children: [
17485
- /* @__PURE__ */ jsx31(Box22, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isRerunTarget ? /* @__PURE__ */ jsx31(CircularProgress5, { size: 14, sx: { color: "hsl(var(--primary))" } }) : isProcessing ? isLikelyTimedOut ? /* @__PURE__ */ jsx31(Tooltip14, { title: "No new activity for over a minute \u2014 this run has most likely timed out.", arrow: true, children: /* @__PURE__ */ jsx31(Box22, { sx: { display: "flex" }, children: /* @__PURE__ */ jsx31(WarningIcon, { size: 14, color: STATUS_COLORS.warning }) }) }) : isLiveProcessing ? /* @__PURE__ */ jsx31(CircularProgress5, { size: 12, sx: { color: "hsl(var(--muted-foreground))" } }) : /* @__PURE__ */ jsx31(Box22, { sx: { width: 6, height: 6, borderRadius: "50%", bgcolor: "hsl(var(--muted-foreground) / 0.5)" } }) : /* @__PURE__ */ jsx31(StatusIcon, { status: effectiveStatus, resumeAtMs: scheduledResumeMs }) }),
18092
+ /* @__PURE__ */ jsx31(Box22, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isRerunTarget ? /* @__PURE__ */ jsx31(CircularProgress5, { size: 14, sx: { color: "hsl(var(--primary))" } }) : isProcessing ? isLikelyTimedOut ? /* @__PURE__ */ jsx31(Tooltip14, { title: "No new activity for over a minute \u2014 this run has most likely timed out.", arrow: true, children: /* @__PURE__ */ jsx31(Box22, { sx: { display: "flex" }, children: /* @__PURE__ */ jsx31(WarningIcon, { size: 14, color: STATUS_COLORS.warning }) }) }) : isLiveProcessing ? /* @__PURE__ */ jsx31(CircularProgress5, { size: 12, sx: { color: "hsl(var(--muted-foreground))" } }) : /* @__PURE__ */ jsx31(Box22, { sx: { width: 6, height: 6, borderRadius: "50%", bgcolor: "hsl(var(--muted-foreground) / 0.5)" } }) : /* @__PURE__ */ jsx31(StatusIcon, { status: effectiveStatus, resumeAtMs: scheduledResumeMs, authBlockedApp: isRowAuthBlocked ? rowAuthReq.appName : null }) }),
17486
18093
  /* @__PURE__ */ jsx31(Box22, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isProcessing ? /* @__PURE__ */ jsx31(Box22, { sx: { width: 22 } }) : toolApp?.icon ? /* @__PURE__ */ jsx31(Tooltip14, { title: (toolApp.name || "").replace(/_/g, " "), arrow: true, children: /* @__PURE__ */ jsx31(Avatar6, { src: toolApp.icon, sx: { width: 22, height: 22, bgcolor: "transparent" }, variant: "rounded" }) }) : item.category === "finalise" || details?.action === "finish" ? /* @__PURE__ */ jsx31(Tooltip14, { title: "Final answer", arrow: true, children: /* @__PURE__ */ jsx31(CheckIcon3, { size: 18 }) }) : /* @__PURE__ */ jsx31(Box22, { sx: { width: 22 } }) }),
17487
18094
  /* @__PURE__ */ jsx31(
17488
18095
  Tooltip14,
@@ -18001,6 +18608,7 @@ var AgentUI = ({
18001
18608
  composeSubmitInput: propComposeSubmitInput,
18002
18609
  contextParams,
18003
18610
  incidentId: propIncidentId,
18611
+ incidentContext: propIncidentContext,
18004
18612
  vulnerabilityId: propVulnerabilityId,
18005
18613
  workflowId: propWorkflowId
18006
18614
  }) => {
@@ -18015,6 +18623,10 @@ var AgentUI = ({
18015
18623
  return h;
18016
18624
  }, [apiKey, orgId]);
18017
18625
  const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
18626
+ const resolvedIncidentId = propIncidentId || (contextCategory === "incidents" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveIncidentId : void 0);
18627
+ const resolvedIncidentContext = propIncidentContext || (typeof window !== "undefined" ? window.__shuffleActiveIncidentContext : void 0);
18628
+ const resolvedVulnerabilityId = propVulnerabilityId || (contextCategory === "vulnerabilities" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveVulnerabilityId : void 0);
18629
+ const resolvedWorkflowId = propWorkflowId || (contextCategory === "workflows" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveWorkflowId : void 0);
18018
18630
  const isPhoneScreen = useMediaQuery("(max-width:600px)", { noSsr: true });
18019
18631
  const isPhone = mobileView !== void 0 ? mobileView : isPhoneScreen;
18020
18632
  const [actionInput, setActionInput] = useState20(() => {
@@ -18095,17 +18707,37 @@ var AgentUI = ({
18095
18707
  if (!match || match.enabled === false) return;
18096
18708
  setSelectedPreset(match);
18097
18709
  if (defaultApps === void 0 && !apps) {
18710
+ const resolved = resolvePresetApps(match);
18098
18711
  const override = readPresetAppsOverride(match.id);
18099
- if (override) {
18100
- setChosenApps(override);
18101
- } else if (match.defaultApps && match.defaultApps.length > 0) {
18102
- setChosenApps(match.defaultApps.map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon })));
18712
+ if (override && override.length > 0) {
18713
+ const merged = [...override];
18714
+ for (const app2 of resolved) {
18715
+ const key = (app2.id || app2.name).toLowerCase();
18716
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
18717
+ merged.push(app2);
18718
+ }
18719
+ }
18720
+ setChosenApps(merged);
18721
+ } else {
18722
+ setChosenApps(resolved);
18103
18723
  }
18104
18724
  }
18105
18725
  seededPresetIdRef.current = match.id;
18106
18726
  } catch {
18107
18727
  }
18108
18728
  }, [presets, defaultInput, isEffectiveSupport, initialPresetId, defaultApps, apps]);
18729
+ useEffect18(() => {
18730
+ const handleToolsChanged = () => {
18731
+ const targetPreset = selectedPreset || AGENT_PRESETS.find((p) => p.id === "incident-response") || AGENT_PRESETS[0];
18732
+ if (targetPreset) {
18733
+ const next = resolvePresetApps(targetPreset);
18734
+ setChosenApps(next);
18735
+ writePresetAppsOverride(targetPreset.id, next);
18736
+ }
18737
+ };
18738
+ window.addEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
18739
+ return () => window.removeEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
18740
+ }, [selectedPreset]);
18109
18741
  useLayoutEffect(() => {
18110
18742
  if (hidePresets) {
18111
18743
  setPresetsChipWidth(0);
@@ -18383,13 +19015,19 @@ var AgentUI = ({
18383
19015
  localStorage.setItem(LAST_PRESET_STORAGE_KEY, preset.id);
18384
19016
  } catch {
18385
19017
  }
19018
+ const resolved = resolvePresetApps(preset);
18386
19019
  const override = readPresetAppsOverride(preset.id);
18387
19020
  if (override && override.length > 0) {
18388
- setChosenApps(override);
18389
- } else if (preset.defaultApps && preset.defaultApps.length > 0) {
18390
- setChosenApps(preset.defaultApps.map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon })));
19021
+ const merged = [...override];
19022
+ for (const app2 of resolved) {
19023
+ const key = (app2.id || app2.name).toLowerCase();
19024
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
19025
+ merged.push(app2);
19026
+ }
19027
+ }
19028
+ setChosenApps(merged);
18391
19029
  } else {
18392
- setChosenApps([]);
19030
+ setChosenApps(resolved);
18393
19031
  }
18394
19032
  seededPresetIdRef.current = preset.id;
18395
19033
  if (onSelectPreset) {
@@ -18607,9 +19245,9 @@ var AgentUI = ({
18607
19245
  }, [availableApps]);
18608
19246
  const pendingAuthApps = useMemo10(() => {
18609
19247
  if (authAppsLoading) return [];
18610
- const decisions = agentData?.decisions || [];
18611
19248
  const seen = /* @__PURE__ */ new Set();
18612
19249
  const out = [];
19250
+ const decisions = agentData?.decisions || [];
18613
19251
  for (const d of decisions) {
18614
19252
  const req = extractAuthRequest(d);
18615
19253
  if (!req) continue;
@@ -18621,8 +19259,21 @@ var AgentUI = ({
18621
19259
  const icon = appsById[req.appName]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
18622
19260
  out.push({ appName: req.appName, appId, icon });
18623
19261
  }
19262
+ const hasAllowed = Array.isArray(agentData?.allowed_actions) && agentData.allowed_actions.length > 0;
19263
+ const activeAppList = hasAllowed ? executionApps : chosenApps;
19264
+ for (const app2 of activeAppList) {
19265
+ if (!app2?.name) continue;
19266
+ const slug = normalizeAgentAppName(app2.name);
19267
+ if (seen.has(slug)) continue;
19268
+ if (appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name, app2.id || null)) {
19269
+ seen.add(slug);
19270
+ const appId = app2.id || appsById[app2.name]?.id || appsById[slug]?.id || null;
19271
+ const icon = app2.icon || appsById[app2.name]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
19272
+ out.push({ appName: app2.name, appId, icon });
19273
+ }
19274
+ }
18624
19275
  return out;
18625
- }, [agentData, appsById, authAppsLoading, isAppAuthenticated]);
19276
+ }, [agentData, executionApps, chosenApps, appsById, authAppsLoading, isAppAuthenticated]);
18626
19277
  useEffect18(() => {
18627
19278
  if (apps) setChosenApps(apps);
18628
19279
  }, [apps]);
@@ -19237,9 +19888,6 @@ var AgentUI = ({
19237
19888
  return next;
19238
19889
  }, { replace: true });
19239
19890
  }
19240
- const resolvedIncidentId = propIncidentId || (contextCategory === "incidents" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveIncidentId : void 0);
19241
- const resolvedVulnerabilityId = propVulnerabilityId || (contextCategory === "vulnerabilities" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveVulnerabilityId : void 0);
19242
- const resolvedWorkflowId = propWorkflowId || (contextCategory === "workflows" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveWorkflowId : void 0);
19243
19891
  const result = await runAgent({
19244
19892
  input: composed.trim(),
19245
19893
  skipPolling: true,
@@ -19248,6 +19896,7 @@ var AgentUI = ({
19248
19896
  ...apiBaseUrl ? { apiBaseUrl } : {},
19249
19897
  ...orgId ? { orgId } : {},
19250
19898
  ...resolvedIncidentId ? { incidentId: resolvedIncidentId } : {},
19899
+ ...resolvedIncidentContext ? { incidentContext: resolvedIncidentContext } : {},
19251
19900
  ...resolvedVulnerabilityId ? { vulnerabilityId: resolvedVulnerabilityId } : {},
19252
19901
  ...resolvedWorkflowId ? { workflowId: resolvedWorkflowId } : {},
19253
19902
  // Send a single comma-separated `tool_name` in the format
@@ -19318,6 +19967,13 @@ var AgentUI = ({
19318
19967
  const auth = raw?.authorization;
19319
19968
  if (eid && auth) {
19320
19969
  activeExecutionIdRef.current = eid;
19970
+ if (typeof window !== "undefined") {
19971
+ window.dispatchEvent(
19972
+ new CustomEvent("shuffle:agent_execution_status", {
19973
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
19974
+ })
19975
+ );
19976
+ }
19321
19977
  if (contextStorageKey) {
19322
19978
  setPageContextChoice(contextStorageKey, {
19323
19979
  draftPrompt: "",
@@ -19905,17 +20561,30 @@ var AgentUI = ({
19905
20561
  if (status === "FINISHED" || status === "SUCCESS") {
19906
20562
  window.dispatchEvent(
19907
20563
  new CustomEvent("shuffle:agent_execution_status", {
19908
- detail: { executionId: eid, status: "completed" }
20564
+ detail: { executionId: eid, status: "completed", incidentId: resolvedIncidentId }
19909
20565
  })
19910
20566
  );
20567
+ if (resolvedIncidentId) {
20568
+ window.dispatchEvent(
20569
+ new CustomEvent("incident:refresh", {
20570
+ detail: { id: resolvedIncidentId, incidentId: resolvedIncidentId, executionId: eid }
20571
+ })
20572
+ );
20573
+ }
19911
20574
  } else if (["FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(status)) {
19912
20575
  window.dispatchEvent(
19913
20576
  new CustomEvent("shuffle:agent_execution_status", {
19914
- detail: { executionId: eid, status: "failed" }
20577
+ detail: { executionId: eid, status: "failed", incidentId: resolvedIncidentId }
20578
+ })
20579
+ );
20580
+ } else if (["RUNNING", "EXECUTING", "IN_PROGRESS", "WAITING"].includes(status)) {
20581
+ window.dispatchEvent(
20582
+ new CustomEvent("shuffle:agent_execution_status", {
20583
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
19915
20584
  })
19916
20585
  );
19917
20586
  }
19918
- }, [execution?.execution_id, execution?.status, agentData?.status]);
20587
+ }, [execution?.execution_id, execution?.status, agentData?.status, resolvedIncidentId]);
19919
20588
  useEffect18(() => {
19920
20589
  if (!finishDecisionId || agentRequestLoading) return;
19921
20590
  if (continuationFocusedForRef.current === finishDecisionId) return;
@@ -22113,7 +22782,47 @@ var AgentUI = ({
22113
22782
  children: formatAppDisplayName(app2.name || "")
22114
22783
  }
22115
22784
  ),
22116
- (needsAuth || isUnavailable) && /* @__PURE__ */ jsx31(WarningIcon, { size: 14, color: "hsl(var(--severity-medium))", style: { marginRight: 2 } }),
22785
+ needsAuth ? /* @__PURE__ */ jsx31(
22786
+ Box22,
22787
+ {
22788
+ component: "span",
22789
+ sx: {
22790
+ fontSize: "0.65rem",
22791
+ fontWeight: 600,
22792
+ color: "hsl(var(--destructive))",
22793
+ bgcolor: "hsl(var(--destructive) / 0.12)",
22794
+ border: "1px solid hsl(var(--destructive) / 0.3)",
22795
+ borderRadius: 1,
22796
+ px: 0.6,
22797
+ py: 0.1,
22798
+ letterSpacing: "0.02em",
22799
+ textTransform: "uppercase",
22800
+ ml: 0.5,
22801
+ mr: 0.25
22802
+ },
22803
+ children: "Missing auth"
22804
+ }
22805
+ ) : isUnavailable ? /* @__PURE__ */ jsx31(
22806
+ Box22,
22807
+ {
22808
+ component: "span",
22809
+ sx: {
22810
+ fontSize: "0.65rem",
22811
+ fontWeight: 600,
22812
+ color: "hsl(var(--severity-medium))",
22813
+ bgcolor: "hsl(var(--severity-medium) / 0.12)",
22814
+ border: "1px solid hsl(var(--severity-medium) / 0.3)",
22815
+ borderRadius: 1,
22816
+ px: 0.6,
22817
+ py: 0.1,
22818
+ letterSpacing: "0.02em",
22819
+ textTransform: "uppercase",
22820
+ ml: 0.5,
22821
+ mr: 0.25
22822
+ },
22823
+ children: "Unavailable"
22824
+ }
22825
+ ) : null,
22117
22826
  isRequired ? /* @__PURE__ */ jsx31(
22118
22827
  LockIcon3,
22119
22828
  {
@@ -22315,43 +23024,83 @@ var AgentUI = ({
22315
23024
  return list;
22316
23025
  })().map((app2, i) => {
22317
23026
  const slug = normalizeAgentAppName(app2.name || "");
23027
+ const appNeedsAuth = !authAppsLoading && appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name || "", app2.id || null);
22318
23028
  const appIcon = app2.icon || availableApps.find((a) => normalizeAgentAppName(a.name || "") === slug)?.icon || resolvedToolApps[slug]?.icon;
22319
- return /* @__PURE__ */ jsx31(Tooltip14, { title: formatAppDisplayName(app2.name || ""), children: /* @__PURE__ */ jsx31(
22320
- Box22,
23029
+ return /* @__PURE__ */ jsx31(
23030
+ Tooltip14,
22321
23031
  {
22322
- onClick: () => setAuthDrawerApp({ name: app2.name, id: app2.id || null }),
22323
- sx: {
22324
- display: "inline-flex",
22325
- alignItems: "center",
22326
- justifyContent: "center",
22327
- width: 24,
22328
- height: 24,
22329
- borderRadius: "6px",
22330
- overflow: "hidden",
22331
- bgcolor: "hsl(var(--muted))",
22332
- cursor: "pointer",
22333
- transition: "transform 0.15s ease, border-color 0.15s ease",
22334
- "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
22335
- },
23032
+ title: appNeedsAuth ? `${formatAppDisplayName(app2.name || "")} \u2014 Missing authentication (Click to connect)` : formatAppDisplayName(app2.name || ""),
22336
23033
  children: /* @__PURE__ */ jsx31(
22337
- AppFallbackIcon,
23034
+ Box22,
22338
23035
  {
22339
- name: app2.name,
22340
- imageUrl: appIcon,
22341
- size: 24,
22342
- style: { borderRadius: 6, objectFit: "contain" }
23036
+ onClick: () => setAuthDrawerApp({ name: app2.name, id: app2.id || null }),
23037
+ sx: {
23038
+ display: "inline-flex",
23039
+ alignItems: "center",
23040
+ justifyContent: "center",
23041
+ width: 24,
23042
+ height: 24,
23043
+ borderRadius: "6px",
23044
+ overflow: "hidden",
23045
+ bgcolor: "hsl(var(--muted))",
23046
+ cursor: "pointer",
23047
+ transition: "transform 0.15s ease, border-color 0.15s ease",
23048
+ border: appNeedsAuth ? "2px solid hsl(var(--destructive)) !important" : "none",
23049
+ boxShadow: appNeedsAuth ? "0 0 0 1px hsl(var(--destructive) / 0.4)" : "none",
23050
+ "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
23051
+ },
23052
+ children: /* @__PURE__ */ jsx31(
23053
+ AppFallbackIcon,
23054
+ {
23055
+ name: app2.name,
23056
+ imageUrl: appIcon,
23057
+ size: 24,
23058
+ style: { borderRadius: 6, objectFit: "contain" }
23059
+ }
23060
+ )
22343
23061
  }
22344
23062
  )
22345
- }
22346
- ) }, i);
23063
+ },
23064
+ i
23065
+ );
22347
23066
  }) }),
22348
23067
  /* @__PURE__ */ jsxs24(Box22, { sx: { flex: 1, minWidth: 0 }, children: [
22349
23068
  /* @__PURE__ */ jsx31(Typography19, { sx: { fontSize: "0.85rem", color: "hsl(var(--foreground))", fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: extractCleanDisplayPrompt(agentData?.original_input) || actionInput || "Agent run" }),
22350
- /* @__PURE__ */ jsxs24(Typography19, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))" }, children: [
22351
- "Status: ",
22352
- execution?.status || agentData?.status || "\u2014",
22353
- " \xB7 ",
22354
- execution?.execution_id?.slice(0, 8) || ""
23069
+ /* @__PURE__ */ jsxs24(Typography19, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))", display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap", mt: 0.25 }, children: [
23070
+ /* @__PURE__ */ jsxs24("span", { children: [
23071
+ "Status: ",
23072
+ execution?.status || agentData?.status || "\u2014",
23073
+ " \xB7 ",
23074
+ execution?.execution_id?.slice(0, 8) || ""
23075
+ ] }),
23076
+ pendingAuthApps.length > 0 && /* @__PURE__ */ jsxs24(
23077
+ Box22,
23078
+ {
23079
+ component: "span",
23080
+ onClick: () => setAuthDrawerApp({ name: pendingAuthApps[0].appName, id: pendingAuthApps[0].appId }),
23081
+ sx: {
23082
+ display: "inline-flex",
23083
+ alignItems: "center",
23084
+ gap: 0.5,
23085
+ px: 0.75,
23086
+ py: 0.15,
23087
+ borderRadius: 1,
23088
+ bgcolor: "hsl(var(--destructive) / 0.12)",
23089
+ border: "1px solid hsl(var(--destructive) / 0.35)",
23090
+ color: "hsl(var(--destructive))",
23091
+ fontSize: "0.68rem",
23092
+ fontWeight: 600,
23093
+ cursor: "pointer",
23094
+ textTransform: "none",
23095
+ "&:hover": { bgcolor: "hsl(var(--destructive) / 0.2)" }
23096
+ },
23097
+ children: [
23098
+ "Missing Auth: ",
23099
+ pendingAuthApps.map((a) => formatAppDisplayName(a.appName)).join(", "),
23100
+ " \u2014 Connect"
23101
+ ]
23102
+ }
23103
+ )
22355
23104
  ] })
22356
23105
  ] }),
22357
23106
  /* @__PURE__ */ jsx31(AgentAttachmentsButton_default, { attachments: llmImageAttachments }),
@@ -22531,6 +23280,57 @@ var AgentUI = ({
22531
23280
  }
22532
23281
  }
22533
23282
  ),
23283
+ pendingAuthApps.length > 0 && /* @__PURE__ */ jsxs24(
23284
+ Box22,
23285
+ {
23286
+ sx: {
23287
+ mb: 2,
23288
+ p: 2,
23289
+ borderRadius: 2,
23290
+ border: "1px solid hsla(var(--severity-medium) / 0.35)",
23291
+ bgcolor: "hsla(var(--severity-medium) / 0.08)",
23292
+ display: "flex",
23293
+ alignItems: "center",
23294
+ justifyContent: "space-between",
23295
+ gap: 2,
23296
+ flexWrap: "wrap"
23297
+ },
23298
+ children: [
23299
+ /* @__PURE__ */ jsxs24(Box22, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1, minWidth: 260 }, children: [
23300
+ /* @__PURE__ */ jsx31(LockIcon3, { size: 22, color: "hsl(var(--severity-medium))" }),
23301
+ /* @__PURE__ */ jsxs24(Box22, { sx: { flex: 1, minWidth: 0 }, children: [
23302
+ /* @__PURE__ */ jsx31(Typography19, { 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` }),
23303
+ /* @__PURE__ */ jsx31(Typography19, { 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.` })
23304
+ ] })
23305
+ ] }),
23306
+ /* @__PURE__ */ jsx31(Box22, { sx: { display: "flex", gap: 1, flexWrap: "wrap" }, children: pendingAuthApps.map(({ appName, appId }) => /* @__PURE__ */ jsxs24(
23307
+ Button13,
23308
+ {
23309
+ variant: "outlined",
23310
+ size: "small",
23311
+ onClick: () => setAuthDrawerApp({ name: appName, id: appId }),
23312
+ sx: {
23313
+ borderColor: "hsla(var(--severity-medium) / 0.6)",
23314
+ color: "hsl(var(--foreground))",
23315
+ textTransform: "none",
23316
+ fontSize: "0.75rem",
23317
+ fontWeight: 600,
23318
+ height: 32,
23319
+ "&:hover": {
23320
+ bgcolor: "hsla(var(--severity-medium) / 0.15)",
23321
+ borderColor: "hsl(var(--severity-medium))"
23322
+ }
23323
+ },
23324
+ children: [
23325
+ "Authenticate ",
23326
+ formatAppDisplayName(appName)
23327
+ ]
23328
+ },
23329
+ appName
23330
+ )) })
23331
+ ]
23332
+ }
23333
+ ),
22534
23334
  viewMode === "simple" && /* @__PURE__ */ jsx31(Box22, { sx: {
22535
23335
  borderRadius: 2,
22536
23336
  border: "1px solid hsl(var(--border))",
@@ -22572,7 +23372,7 @@ var AgentUI = ({
22572
23372
  }
22573
23373
  const pendingAnswered = pendingQuestions.every((q) => questionAnswers[q.question]?.value);
22574
23374
  return /* @__PURE__ */ jsxs24(Fragment12, { children: [
22575
- /* @__PURE__ */ jsxs24(
23375
+ /* @__PURE__ */ jsx31(
22576
23376
  RunFinishedSummary,
22577
23377
  {
22578
23378
  status,
@@ -22585,77 +23385,7 @@ var AgentUI = ({
22585
23385
  durationSec,
22586
23386
  showMeta: true,
22587
23387
  bottomContent: aiAuthSuggestionNode,
22588
- children: [
22589
- pendingAuthApps.map(({ appName, appId, icon }) => {
22590
- const pretty = appName.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
22591
- return /* @__PURE__ */ jsxs24(
22592
- Box22,
22593
- {
22594
- sx: {
22595
- display: "flex",
22596
- alignItems: "center",
22597
- gap: 1.5,
22598
- p: 1.5,
22599
- borderRadius: 1.5,
22600
- border: "1px solid hsla(var(--severity-medium) / 0.3)",
22601
- bgcolor: "hsla(var(--severity-medium) / 0.08)"
22602
- },
22603
- children: [
22604
- /* @__PURE__ */ jsx31(LockIcon3, { size: 22, color: "hsl(var(--severity-medium))" }),
22605
- /* @__PURE__ */ jsxs24(Box22, { sx: { flex: 1, minWidth: 0 }, children: [
22606
- /* @__PURE__ */ jsxs24(Typography19, { sx: { fontSize: "0.85rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: [
22607
- pretty,
22608
- " requires authentication"
22609
- ] }),
22610
- /* @__PURE__ */ jsxs24(Typography19, { sx: { fontSize: "0.75rem", color: "hsl(var(--muted-foreground))" }, children: [
22611
- "Connect your ",
22612
- pretty,
22613
- " account so the agent can complete this step, then rerun."
22614
- ] })
22615
- ] }),
22616
- /* @__PURE__ */ jsxs24(
22617
- Button13,
22618
- {
22619
- variant: "outlined",
22620
- size: "small",
22621
- startIcon: /* @__PURE__ */ jsx31(
22622
- Avatar6,
22623
- {
22624
- src: icon || void 0,
22625
- alt: "",
22626
- variant: "rounded",
22627
- sx: {
22628
- width: 18,
22629
- height: 18,
22630
- borderRadius: 0.5,
22631
- bgcolor: "hsl(var(--background) / 0.4)",
22632
- color: "hsl(var(--background))",
22633
- fontSize: "0.7rem",
22634
- fontWeight: 700,
22635
- "& img": { objectFit: "contain" }
22636
- },
22637
- children: pretty.charAt(0)
22638
- }
22639
- ),
22640
- onClick: () => setAuthDrawerApp({ name: appName, id: appId }),
22641
- sx: {
22642
- height: 36,
22643
- textTransform: "none",
22644
- fontWeight: 600
22645
- },
22646
- children: [
22647
- "Authenticate ",
22648
- pretty
22649
- ]
22650
- }
22651
- )
22652
- ]
22653
- },
22654
- `auth-${appName}`
22655
- );
22656
- }),
22657
- !isRunning && postRunDiscovery
22658
- ]
23388
+ children: !isRunning && postRunDiscovery
22659
23389
  }
22660
23390
  ),
22661
23391
  !finishAnswer && pendingAsk && pendingQuestions.length > 0 ? (() => {
@@ -27005,6 +27735,8 @@ var AskAiSidePanel = ({
27005
27735
  defaultInput,
27006
27736
  serverside,
27007
27737
  colorMode,
27738
+ incidentId: propIncidentId,
27739
+ incidentContext: propIncidentContext,
27008
27740
  sx
27009
27741
  }) => {
27010
27742
  const themeScope = useShuffleMcpTheme();
@@ -27127,11 +27859,15 @@ var AskAiSidePanel = ({
27127
27859
  }, [open, initialTab, onTabChange]);
27128
27860
  const [activeTaskId, setActiveTaskId] = useState29(null);
27129
27861
  const [activeExecutionId, setActiveExecutionId] = useState29(null);
27862
+ const [activeIncidentId, setActiveIncidentId] = useState29(null);
27863
+ const [activeIncidentContext, setActiveIncidentContext] = useState29(null);
27130
27864
  const [runResetKey, setRunResetKey] = useState29(0);
27131
27865
  useEffect26(() => {
27132
27866
  if (!open) {
27133
27867
  setActiveTaskId(null);
27134
27868
  setActiveExecutionId(null);
27869
+ setActiveIncidentId(null);
27870
+ setActiveIncidentContext(null);
27135
27871
  }
27136
27872
  }, [open]);
27137
27873
  useEffect26(() => {
@@ -27163,6 +27899,12 @@ var AskAiSidePanel = ({
27163
27899
  } else if (!detail?.tab) {
27164
27900
  setActiveTaskId(null);
27165
27901
  }
27902
+ if (detail?.incidentId !== void 0) {
27903
+ setActiveIncidentId(detail.incidentId || null);
27904
+ }
27905
+ if (detail?.incidentContext !== void 0) {
27906
+ setActiveIncidentContext(detail.incidentContext || null);
27907
+ }
27166
27908
  if (detail?.resetExecution) {
27167
27909
  setActiveExecutionId(null);
27168
27910
  setRunResetKey((k) => k + 1);
@@ -27796,6 +28538,8 @@ var AskAiSidePanel = ({
27796
28538
  onAppsChange: handleAppsChange,
27797
28539
  onSelectPreset: handleSelectPreset,
27798
28540
  onChooseLLM: () => handleTabChange("localLLM"),
28541
+ incidentId: activeIncidentId || propIncidentId || agentUIProps?.incidentId,
28542
+ incidentContext: activeIncidentContext || propIncidentContext || agentUIProps?.incidentContext,
27799
28543
  apiBaseUrl: globalUrl || agentUIProps?.apiBaseUrl,
27800
28544
  theme: effectiveTheme,
27801
28545
  sx: {