@shuffleio/shuffle-mcps 0.0.57 → 0.0.58

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,235 @@ 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 isSurfaceElement = (el) => {
8602
+ if (!(el instanceof HTMLElement)) return false;
8603
+ 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]"));
8604
+ };
8605
+ var isChildPopupElement = (el) => {
8606
+ if (!(el instanceof HTMLElement)) return false;
8607
+ 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");
8608
+ };
8609
+ var isTooltipElement = (el) => {
8610
+ if (!(el instanceof HTMLElement)) return false;
8611
+ return el.classList.contains("MuiTooltip-popper") || el.getAttribute("role") === "tooltip";
8612
+ };
8613
+ var isElementOpen = (el) => {
8614
+ if (el.getAttribute("aria-hidden") === "true") return false;
8615
+ if (el.getAttribute("data-state") === "closed") return false;
8616
+ if (el.classList.contains("MuiModal-hidden")) return false;
8617
+ const style = el.style;
8618
+ if (style.display === "none" || style.visibility === "hidden") return false;
8619
+ return true;
8620
+ };
8621
+ var observerInstance = null;
8622
+ var installGlobalOverlayAutoLayer = () => {
8623
+ if (typeof window === "undefined" || typeof document === "undefined") return;
8624
+ const store = getStore();
8625
+ if (store[AUTO_LAYER_KEY]) return;
8626
+ store[AUTO_LAYER_KEY] = true;
8627
+ const handleElementOpen = (el) => {
8628
+ if (isSurfaceElement(el)) {
8629
+ let layerId = el.dataset.shuffleLayerId;
8630
+ if (!layerId) {
8631
+ layerId = "dom_" + Math.random().toString(36).substring(2, 9);
8632
+ el.dataset.shuffleLayerId = layerId;
8633
+ }
8634
+ const targetZ = allocateSurfaceLayer(layerId, el);
8635
+ el.dataset.shuffleLayerZ = String(targetZ);
8636
+ el.style.setProperty("z-index", String(targetZ), "important");
8637
+ const dialogContent = el.querySelector('[role="dialog"], [role="alertdialog"]');
8638
+ if (dialogContent && dialogContent !== el) {
8639
+ dialogContent.style.setProperty("z-index", String(targetZ), "important");
8640
+ }
8641
+ return;
8642
+ }
8643
+ if (isChildPopupElement(el)) {
8644
+ const topZ = getTopSurfaceZIndex();
8645
+ const popupZ = topZ + POPUP_OFFSET;
8646
+ el.dataset.shuffleLayerZ = String(popupZ);
8647
+ el.style.setProperty("z-index", String(popupZ), "important");
8648
+ return;
8649
+ }
8650
+ if (isTooltipElement(el)) {
8651
+ const topZ = getTopSurfaceZIndex();
8652
+ const tooltipZ = topZ + TOOLTIP_OFFSET;
8653
+ el.dataset.shuffleLayerZ = String(tooltipZ);
8654
+ el.style.setProperty("z-index", String(tooltipZ), "important");
8655
+ return;
8656
+ }
8657
+ };
8658
+ const handleElementClose = (el) => {
8659
+ const layerId = el.dataset.shuffleLayerId;
8660
+ if (layerId) {
8661
+ releaseOverlayLayer(layerId);
8662
+ delete el.dataset.shuffleLayerId;
8663
+ delete el.dataset.shuffleLayerZ;
8664
+ } else {
8665
+ releaseOverlayLayer(el);
8666
+ }
8667
+ };
8668
+ const scanNode = (node) => {
8669
+ if (!(node instanceof HTMLElement)) return;
8670
+ if (isSurfaceElement(node) || isChildPopupElement(node) || isTooltipElement(node)) {
8671
+ if (isElementOpen(node)) {
8672
+ handleElementOpen(node);
8673
+ } else {
8674
+ handleElementClose(node);
8675
+ }
8676
+ }
8677
+ const children2 = node.children;
8678
+ for (let i = 0; i < children2.length; i++) {
8679
+ const child = children2[i];
8680
+ if (child instanceof HTMLElement) {
8681
+ if (isSurfaceElement(child) || isChildPopupElement(child) || isTooltipElement(child)) {
8682
+ if (isElementOpen(child)) {
8683
+ handleElementOpen(child);
8684
+ } else {
8685
+ handleElementClose(child);
8686
+ }
8687
+ }
8688
+ }
8689
+ }
8690
+ };
8691
+ observerInstance = new MutationObserver((mutations) => {
8692
+ for (const m of mutations) {
8693
+ if (m.type === "childList") {
8694
+ m.addedNodes.forEach(scanNode);
8695
+ m.removedNodes.forEach((node) => {
8696
+ if (node instanceof HTMLElement) {
8697
+ handleElementClose(node);
8698
+ }
8699
+ });
8700
+ } else if (m.type === "attributes") {
8701
+ const target = m.target;
8702
+ if (target instanceof HTMLElement) {
8703
+ scanNode(target);
8704
+ }
8705
+ }
8706
+ }
8707
+ });
8708
+ const body = document.body;
8709
+ if (body) {
8710
+ observerInstance.observe(body, {
8711
+ childList: true,
8712
+ subtree: true,
8713
+ attributes: true,
8714
+ attributeFilter: ["class", "style", "aria-hidden", "data-state"]
8715
+ });
8716
+ Array.from(body.children).forEach(scanNode);
8717
+ }
8718
+ document.addEventListener(
8719
+ "pointerdown",
8720
+ (e) => {
8721
+ const target = e.target;
8722
+ if (!target) return;
8723
+ const surface = target.closest(
8724
+ '.MuiDialog-root, .MuiDrawer-root, .MuiModal-root:not(.MuiPopover-root):not(.MuiMenu-root), [role="dialog"], [role="alertdialog"]'
8725
+ );
8726
+ if (!surface || !surface.dataset.shuffleLayerId) return;
8727
+ const currentZ = Number(surface.dataset.shuffleLayerZ || 0);
8728
+ const topZ = getTopSurfaceZIndex();
8729
+ if (currentZ > 0 && currentZ < topZ) {
8730
+ const newZ = bringSurfaceToFront(surface.dataset.shuffleLayerId);
8731
+ surface.dataset.shuffleLayerZ = String(newZ);
8732
+ surface.style.setProperty("z-index", String(newZ), "important");
8733
+ }
8734
+ },
8735
+ true
8736
+ );
8737
+ };
8738
+ if (typeof window !== "undefined") {
8739
+ installGlobalOverlayAutoLayer();
8740
+ }
8529
8741
 
8530
8742
  // views/AppDetailDrawer.tsx
8531
8743
  import { jsx as jsx17 } from "react/jsx-runtime";
@@ -8986,6 +9198,11 @@ var ShuffleMCP = React4.forwardRef(({
8986
9198
  const [isOpen, setIsOpen] = useState11(false);
8987
9199
  const [selectedIndex, setSelectedIndex] = useState11(-1);
8988
9200
  const [internalSelectedApps, setInternalSelectedApps] = useState11(selectedApps);
9201
+ useEffect9(() => {
9202
+ if (selectedApps) {
9203
+ setInternalSelectedApps(selectedApps);
9204
+ }
9205
+ }, [selectedApps]);
8989
9206
  const [authenticatedApps, setAuthenticatedApps] = useState11(externalAuthenticatedApps || []);
8990
9207
  const [authenticatedAppsLoading, setAuthenticatedAppsLoading] = useState11(!externalAuthenticatedApps);
8991
9208
  const [drawerApp, setDrawerApp] = useState11(null);
@@ -10181,6 +10398,7 @@ var AddAppDialog = ({
10181
10398
  maxLength = 1024,
10182
10399
  initialInput = ""
10183
10400
  }) => {
10401
+ const dialogZIndex = useOverlayLayer(open);
10184
10402
  const [input, setInput] = useState12(initialInput);
10185
10403
  const [stage, setStage] = useState12("idle");
10186
10404
  const [spec, setSpec] = useState12(null);
@@ -10347,6 +10565,12 @@ var AddAppDialog = ({
10347
10565
  onClose: () => onOpenChange(false),
10348
10566
  fullWidth: true,
10349
10567
  maxWidth: "sm",
10568
+ sx: {
10569
+ zIndex: dialogZIndex,
10570
+ "& .MuiBackdrop-root": {
10571
+ zIndex: dialogZIndex
10572
+ }
10573
+ },
10350
10574
  PaperProps: {
10351
10575
  sx: {
10352
10576
  maxWidth: 640,
@@ -10355,7 +10579,8 @@ var AddAppDialog = ({
10355
10579
  color: "hsl(var(--foreground))",
10356
10580
  border: "1px solid hsl(var(--border))",
10357
10581
  borderRadius: 2,
10358
- boxSizing: "border-box"
10582
+ boxSizing: "border-box",
10583
+ zIndex: dialogZIndex
10359
10584
  }
10360
10585
  },
10361
10586
  children: [
@@ -11403,6 +11628,8 @@ var AiAgentPromptsEditor = ({
11403
11628
  prompts,
11404
11629
  apps,
11405
11630
  readOnly = false,
11631
+ skillLabel,
11632
+ isBuiltInApp,
11406
11633
  onChangePrompt,
11407
11634
  onRemovePrompt,
11408
11635
  onAddPrompt,
@@ -11490,16 +11717,44 @@ var AiAgentPromptsEditor = ({
11490
11717
  ] }),
11491
11718
  /* @__PURE__ */ jsxs15(Box14, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
11492
11719
  /* @__PURE__ */ jsx22(
11493
- Typography12,
11720
+ Tooltip8,
11494
11721
  {
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"
11722
+ 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.",
11723
+ children: /* @__PURE__ */ jsxs15(Box14, { sx: { display: "inline-flex", alignItems: "center", gap: 0.75 }, children: [
11724
+ /* @__PURE__ */ jsx22(
11725
+ Typography12,
11726
+ {
11727
+ sx: {
11728
+ fontSize: "0.65rem",
11729
+ fontWeight: 600,
11730
+ color: "hsl(var(--muted-foreground))",
11731
+ textTransform: "uppercase",
11732
+ letterSpacing: "0.05em"
11733
+ },
11734
+ children: "Allowed apps"
11735
+ }
11736
+ ),
11737
+ skillLabel && /* @__PURE__ */ jsxs15(
11738
+ Typography12,
11739
+ {
11740
+ component: "span",
11741
+ sx: {
11742
+ fontSize: "0.62rem",
11743
+ fontWeight: 600,
11744
+ color: "hsl(var(--primary))",
11745
+ bgcolor: "hsl(var(--primary) / 0.1)",
11746
+ px: 0.6,
11747
+ py: 0.1,
11748
+ borderRadius: 0.75,
11749
+ letterSpacing: "0.02em"
11750
+ },
11751
+ children: [
11752
+ skillLabel,
11753
+ " permissions"
11754
+ ]
11755
+ }
11756
+ )
11757
+ ] })
11503
11758
  }
11504
11759
  ),
11505
11760
  /* @__PURE__ */ jsxs15(Box14, { sx: { display: "flex", alignItems: "center", gap: 0.5, flexWrap: "wrap", flex: 1 }, children: [
@@ -11508,8 +11763,9 @@ var AiAgentPromptsEditor = ({
11508
11763
  const meta = resolveAppMeta(appKey);
11509
11764
  const displayName2 = meta.name;
11510
11765
  const img = meta.image || `https://shuffler.io/images/apps/${displayName2}.png`;
11766
+ const isBuiltIn = isBuiltInApp ? isBuiltInApp(appKey) : false;
11511
11767
  const clickable = !readOnly && !!onRemoveApp;
11512
- const tip = clickable ? `Remove ${displayName2.replace(/_/g, " ")}` : displayName2.replace(/_/g, " ");
11768
+ const tip = isBuiltIn ? `${displayName2.replace(/_/g, " ")} (Default built-in app for ${skillLabel || "skill"})` : clickable ? `Remove ${displayName2.replace(/_/g, " ")} (Assigned permission)` : displayName2.replace(/_/g, " ");
11513
11769
  return /* @__PURE__ */ jsx22(Tooltip8, { title: tip, children: /* @__PURE__ */ jsx22(
11514
11770
  IconButton7,
11515
11771
  {
@@ -11519,12 +11775,12 @@ var AiAgentPromptsEditor = ({
11519
11775
  sx: {
11520
11776
  width: 26,
11521
11777
  height: 26,
11522
- border: "1px solid hsl(var(--severity-low) / 0.3)",
11523
- bgcolor: "hsl(var(--severity-low) / 0.1)",
11778
+ border: isBuiltIn ? "1px solid hsl(var(--primary) / 0.35)" : "1px solid hsl(var(--severity-low) / 0.3)",
11779
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)",
11524
11780
  borderRadius: 1,
11525
11781
  "&.Mui-disabled": {
11526
11782
  opacity: 1,
11527
- bgcolor: "hsl(var(--severity-low) / 0.1)"
11783
+ bgcolor: isBuiltIn ? "hsl(var(--primary) / 0.08)" : "hsl(var(--severity-low) / 0.1)"
11528
11784
  },
11529
11785
  "&:hover": clickable ? {
11530
11786
  bgcolor: "hsl(var(--destructive) / 0.15)",
@@ -11543,7 +11799,7 @@ var AiAgentPromptsEditor = ({
11543
11799
  }
11544
11800
  ) }, appKey);
11545
11801
  }),
11546
- !readOnly && onAddAppRequested && /* @__PURE__ */ jsx22(Tooltip8, { title: "Add allowed app", children: /* @__PURE__ */ jsx22(
11802
+ !readOnly && onAddAppRequested && /* @__PURE__ */ jsx22(Tooltip8, { title: skillLabel ? `Assign tools to ${skillLabel}` : "Add allowed app", children: /* @__PURE__ */ jsx22(
11547
11803
  IconButton7,
11548
11804
  {
11549
11805
  size: "small",
@@ -12325,7 +12581,7 @@ var AGENT_PRESETS = [
12325
12581
  icon: /* @__PURE__ */ jsx25(ShieldAlert, { size: 16 }),
12326
12582
  enabled: true,
12327
12583
  tag: "Beta",
12328
- defaultApps: [{ name: "shuffle_incidents" }, { name: "shuffle_datastore" }]
12584
+ defaultApps: [{ name: "shuffle_incidents" }]
12329
12585
  },
12330
12586
  {
12331
12587
  id: "host-monitor-control",
@@ -12786,6 +13042,150 @@ var AgentPresets = ({ variant = "default", onSelectPreset, selectedPreset, onRem
12786
13042
  };
12787
13043
  var AgentPresets_default = AgentPresets;
12788
13044
 
13045
+ // ../lib/agentTools.ts
13046
+ var STORAGE_KEY3 = "agent_tools_config";
13047
+ var AGENT_TOOLS_CHANGED_EVENT = "agent-tools-changed";
13048
+ var DEFAULT_AGENT = "default";
13049
+ var DEFAULT_ACTION_TYPE = "timeline_reply";
13050
+ var getActiveOrgId = () => {
13051
+ if (typeof window === "undefined") return null;
13052
+ try {
13053
+ const raw = localStorage.getItem("shuffle_user_info") || localStorage.getItem("userinfo") || localStorage.getItem("user_info");
13054
+ if (!raw) return null;
13055
+ const parsed = JSON.parse(raw);
13056
+ return parsed?.active_org?.id || parsed?.org_id || parsed?.active_org_id || Array.isArray(parsed?.orgs) && parsed.orgs[0]?.id || parsed?.id || null;
13057
+ } catch {
13058
+ return null;
13059
+ }
13060
+ };
13061
+ var getStorageKey = (orgId) => {
13062
+ const resolved = orgId || getActiveOrgId();
13063
+ return resolved ? `${STORAGE_KEY3}_${resolved}` : STORAGE_KEY3;
13064
+ };
13065
+ var coerceTool = (raw) => {
13066
+ if (typeof raw === "string") {
13067
+ const trimmed = raw.trim();
13068
+ if (!trimmed) return null;
13069
+ return { name: trimmed, id: trimmed };
13070
+ }
13071
+ if (raw && typeof raw === "object") {
13072
+ const obj = raw;
13073
+ const name = typeof obj.name === "string" ? obj.name.trim() : "";
13074
+ const id = typeof obj.id === "string" && obj.id.trim() ? obj.id.trim() : name;
13075
+ if (!name) return null;
13076
+ return { name, id };
13077
+ }
13078
+ return null;
13079
+ };
13080
+ var sanitize2 = (parsed) => {
13081
+ let target = parsed;
13082
+ if (target && typeof target === "object" && !Array.isArray(target)) {
13083
+ const obj = target;
13084
+ if (Array.isArray(obj.entries)) {
13085
+ target = obj.entries;
13086
+ }
13087
+ }
13088
+ if (!Array.isArray(target)) return [];
13089
+ return target.filter((e) => e && typeof e.agent === "string" && typeof e.actionType === "string" && Array.isArray(e.tools)).map((e) => ({
13090
+ agent: e.agent,
13091
+ actionType: e.actionType,
13092
+ tools: e.tools.map(coerceTool).filter((t) => !!t),
13093
+ updatedAt: typeof e.updatedAt === "number" ? e.updatedAt : void 0
13094
+ }));
13095
+ };
13096
+ var extractUpdatedAt = (parsed) => {
13097
+ if (parsed && typeof parsed === "object") {
13098
+ const obj = parsed;
13099
+ if (typeof obj.updatedAt === "number") return obj.updatedAt;
13100
+ }
13101
+ return 0;
13102
+ };
13103
+ var readCacheRecord = () => {
13104
+ if (typeof window === "undefined") return { entries: [], updatedAt: 0 };
13105
+ try {
13106
+ const key = getStorageKey();
13107
+ let raw = localStorage.getItem(key);
13108
+ let parsed = null;
13109
+ let entries = [];
13110
+ let updatedAt = 0;
13111
+ if (raw) {
13112
+ try {
13113
+ parsed = JSON.parse(raw);
13114
+ entries = sanitize2(parsed);
13115
+ updatedAt = extractUpdatedAt(parsed) || entries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0);
13116
+ } catch {
13117
+ }
13118
+ }
13119
+ if (entries.length === 0 || entries.every((e) => e.tools.length === 0)) {
13120
+ if (key !== STORAGE_KEY3) {
13121
+ const fallbackRaw = localStorage.getItem(STORAGE_KEY3);
13122
+ if (fallbackRaw) {
13123
+ try {
13124
+ const fallbackParsed = JSON.parse(fallbackRaw);
13125
+ const fallbackEntries = sanitize2(fallbackParsed);
13126
+ if (fallbackEntries.some((e) => e.tools.length > 0)) {
13127
+ entries = fallbackEntries;
13128
+ updatedAt = extractUpdatedAt(fallbackParsed) || fallbackEntries.reduce((max, e) => Math.max(max, e.updatedAt || 0), 0) || Date.now();
13129
+ writeCache(entries, updatedAt);
13130
+ }
13131
+ } catch {
13132
+ }
13133
+ }
13134
+ }
13135
+ }
13136
+ return { entries, updatedAt };
13137
+ } catch {
13138
+ return { entries: [], updatedAt: 0 };
13139
+ }
13140
+ };
13141
+ var readAll = () => readCacheRecord().entries;
13142
+ var writeCache = (entries, explicitUpdatedAt) => {
13143
+ if (typeof window === "undefined") return;
13144
+ try {
13145
+ const updatedAt = explicitUpdatedAt ?? Date.now();
13146
+ const payload = {
13147
+ version: 1,
13148
+ updatedAt,
13149
+ entries
13150
+ };
13151
+ const serialized = JSON.stringify(payload);
13152
+ const orgKey = getStorageKey();
13153
+ localStorage.setItem(orgKey, serialized);
13154
+ if (orgKey !== STORAGE_KEY3) {
13155
+ localStorage.setItem(STORAGE_KEY3, serialized);
13156
+ }
13157
+ window.dispatchEvent(
13158
+ new CustomEvent(AGENT_TOOLS_CHANGED_EVENT, { detail: { updatedAt, entries } })
13159
+ );
13160
+ } catch {
13161
+ }
13162
+ };
13163
+ var getAgentTools = (agent = DEFAULT_AGENT, actionType = DEFAULT_ACTION_TYPE) => {
13164
+ const all = readAll();
13165
+ const entry = all.find((e) => e.agent === agent && e.actionType === actionType);
13166
+ if (entry && entry.tools && entry.tools.length > 0) {
13167
+ return entry.tools;
13168
+ }
13169
+ if (agent === "incident-handler" || agent === "incident-response" || agent === DEFAULT_AGENT) {
13170
+ const found = all.find(
13171
+ (e) => (e.agent === "incident-handler" || e.agent === "incident-response" || e.agent === DEFAULT_AGENT) && e.actionType === actionType && e.tools && e.tools.length > 0
13172
+ );
13173
+ if (found?.tools && found.tools.length > 0) return found.tools;
13174
+ }
13175
+ return [];
13176
+ };
13177
+ var getToolsForSkill = (skillOrPresetId) => {
13178
+ const normalized = (skillOrPresetId || "").toLowerCase().trim();
13179
+ if (normalized === "incident-handler" || normalized === "incident-response" || normalized === "default") {
13180
+ const ih = getAgentTools("incident-handler");
13181
+ if (ih.length > 0) return ih;
13182
+ const ir = getAgentTools("incident-response");
13183
+ if (ir.length > 0) return ir;
13184
+ return getAgentTools(DEFAULT_AGENT);
13185
+ }
13186
+ return getAgentTools(normalized);
13187
+ };
13188
+
12789
13189
  // useAgentPromptPrefix.ts
12790
13190
  import { useCallback as useCallback9, useEffect as useEffect14, useRef as useRef10, useState as useState16 } from "react";
12791
13191
  var AGENT_PROMPT_PREFIX_CATEGORY = "agent-prompt-prefix";
@@ -13005,6 +13405,9 @@ var runAgent = async (request) => {
13005
13405
  if (request.incidentId) {
13006
13406
  input.incident_id = request.incidentId;
13007
13407
  }
13408
+ if (request.incidentContext) {
13409
+ input.incident_context = request.incidentContext;
13410
+ }
13008
13411
  if (request.vulnerabilityId) {
13009
13412
  input.vulnerability_id = request.vulnerabilityId;
13010
13413
  }
@@ -13283,16 +13686,143 @@ var getCachedGroupDocs = (groupId, folder) => {
13283
13686
  }));
13284
13687
  };
13285
13688
 
13689
+ // ../lib/incidentPromptContext.ts
13690
+ var GLOBAL_INCIDENT_KEY = "__shuffleActiveIncidentContext";
13691
+ var getGlobalScope = () => {
13692
+ if (typeof globalThis !== "undefined") return globalThis;
13693
+ if (typeof window !== "undefined") return window;
13694
+ if (typeof global !== "undefined") return global;
13695
+ return null;
13696
+ };
13697
+ var getActiveIncidentPromptContext = () => {
13698
+ const scope = getGlobalScope();
13699
+ if (!scope) return null;
13700
+ const info = scope[GLOBAL_INCIDENT_KEY];
13701
+ if (info && typeof info === "object") {
13702
+ return info;
13703
+ }
13704
+ return null;
13705
+ };
13706
+ var INCIDENT_PROMPT_DELIMITER_START = "=== INCIDENT CONTEXT ===";
13707
+ var INCIDENT_PROMPT_DELIMITER_END = "=== END INCIDENT CONTEXT ===";
13708
+ var formatObservableType = (type) => {
13709
+ if (!type) return "Indicator";
13710
+ const clean = type.toLowerCase().trim();
13711
+ switch (clean) {
13712
+ case "ip":
13713
+ case "ipv4":
13714
+ case "ip_address":
13715
+ return "IPv4";
13716
+ case "ipv6":
13717
+ return "IPv6";
13718
+ case "hash":
13719
+ case "sha256":
13720
+ case "file_hash":
13721
+ return "SHA256";
13722
+ case "md5":
13723
+ return "MD5";
13724
+ case "sha1":
13725
+ return "SHA1";
13726
+ case "hostname":
13727
+ case "host":
13728
+ case "endpoint":
13729
+ return "Hostname";
13730
+ case "domain":
13731
+ return "Domain";
13732
+ case "url":
13733
+ return "URL";
13734
+ case "user":
13735
+ case "username":
13736
+ case "account":
13737
+ return "User";
13738
+ case "email":
13739
+ return "Email";
13740
+ case "process":
13741
+ case "process_name":
13742
+ return "Process";
13743
+ case "file":
13744
+ case "filename":
13745
+ return "File";
13746
+ default:
13747
+ return type.charAt(0).toUpperCase() + type.slice(1);
13748
+ }
13749
+ };
13750
+ var isIncidentInjectedPrompt = (prompt) => {
13751
+ if (!prompt || typeof prompt !== "string") return false;
13752
+ return prompt.includes(INCIDENT_PROMPT_DELIMITER_START) || prompt.includes("OPERATIONAL DIRECTIVES:") || prompt.includes("INCIDENT OBSERVABLES / IOCs:");
13753
+ };
13754
+ var extractCleanIncidentPrompt = (prompt) => {
13755
+ if (!prompt || typeof prompt !== "string") return "";
13756
+ const trimmed = prompt.trim();
13757
+ const taskMatch = trimmed.match(/TASK TO EXECUTE:\s*\n\s*-\s*Task:\s*([^\n]+)/i);
13758
+ if (taskMatch && taskMatch[1]?.trim()) {
13759
+ return `Task: ${taskMatch[1].trim()}`;
13760
+ }
13761
+ const legacyMatch = trimmed.match(/\n\s*Task:\s*([^\n]+)/i);
13762
+ if (legacyMatch && legacyMatch[1]?.trim()) {
13763
+ return `Task: ${legacyMatch[1].trim()}`;
13764
+ }
13765
+ if (trimmed.includes(INCIDENT_PROMPT_DELIMITER_START)) {
13766
+ const before = trimmed.split(INCIDENT_PROMPT_DELIMITER_START)[0]?.trim();
13767
+ if (before) return before;
13768
+ }
13769
+ return trimmed;
13770
+ };
13771
+ var composeIncidentPromptInput = (rawInput, context) => {
13772
+ if (!rawInput || typeof rawInput !== "string") return "";
13773
+ const trimmed = rawInput.trim();
13774
+ if (isIncidentInjectedPrompt(trimmed)) {
13775
+ return trimmed;
13776
+ }
13777
+ const ctx = context || getActiveIncidentPromptContext();
13778
+ if (!ctx || !ctx.id) {
13779
+ return trimmed;
13780
+ }
13781
+ const incidentRef = ctx.id ? `#${ctx.id}` : "";
13782
+ const incidentTitle = ctx.title?.trim() || "Incident";
13783
+ const severity = ctx.severity || "Medium";
13784
+ const status = ctx.status || "In Progress";
13785
+ const description = ctx.description?.trim() || "No description provided.";
13786
+ const seenObservables = /* @__PURE__ */ new Set();
13787
+ const formattedObservables = [];
13788
+ if (Array.isArray(ctx.observables)) {
13789
+ for (const obs of ctx.observables) {
13790
+ if (!obs || obs.archived || !obs.value?.trim()) continue;
13791
+ const val = obs.value.trim();
13792
+ const typeLabel = formatObservableType(obs.type);
13793
+ const key = `${typeLabel.toLowerCase()}:${val.toLowerCase()}`;
13794
+ if (seenObservables.has(key)) continue;
13795
+ seenObservables.add(key);
13796
+ formattedObservables.push(`- ${typeLabel}: ${val}`);
13797
+ }
13798
+ }
13799
+ const observablesBlock = formattedObservables.length > 0 ? formattedObservables.slice(0, 50).join("\n") : "- None recorded yet";
13800
+ return `${trimmed}
13801
+
13802
+ ${INCIDENT_PROMPT_DELIMITER_START}
13803
+ INCIDENT CONTEXT:
13804
+ - Incident: ${incidentRef} ("${incidentTitle}")
13805
+ - Severity: ${severity} | Status: ${status}
13806
+ - Summary: ${description}
13807
+
13808
+ INCIDENT OBSERVABLES / IOCs:
13809
+ ${observablesBlock}
13810
+ ${INCIDENT_PROMPT_DELIMITER_END}
13811
+
13812
+ DIRECTIVES:
13813
+ - Relevant incident details and observables are provided above. Do not call "get_incident" unless raw external logs are required.`;
13814
+ };
13815
+
13286
13816
  // ../lib/docsPromptContext.ts
13287
13817
  var GLOBAL_DOC_KEY = "__shuffleActiveDocInfo";
13288
- var getGlobalScope = () => {
13818
+ var getGlobalScope2 = () => {
13289
13819
  if (typeof globalThis !== "undefined") return globalThis;
13290
13820
  if (typeof window !== "undefined") return window;
13291
13821
  if (typeof global !== "undefined") return global;
13292
13822
  return null;
13293
13823
  };
13294
13824
  var getActiveDocPromptContext = () => {
13295
- const scope = getGlobalScope();
13825
+ const scope = getGlobalScope2();
13296
13826
  if (!scope) return null;
13297
13827
  const info = scope[GLOBAL_DOC_KEY];
13298
13828
  if (info && typeof info === "object") {
@@ -13333,6 +13863,9 @@ var isDocInjectedPrompt = (prompt) => {
13333
13863
  var extractCleanDisplayPrompt = (prompt) => {
13334
13864
  if (!prompt || typeof prompt !== "string") return "";
13335
13865
  const trimmed = prompt.trim();
13866
+ if (isIncidentInjectedPrompt(trimmed)) {
13867
+ return extractCleanIncidentPrompt(trimmed);
13868
+ }
13336
13869
  if (!isDocInjectedPrompt(trimmed)) return trimmed;
13337
13870
  if (trimmed.includes(DOC_PROMPT_DELIMITER_END)) {
13338
13871
  const parts = trimmed.split(DOC_PROMPT_DELIMITER_END);
@@ -13372,7 +13905,7 @@ var composeDocPromptInput = (userQuestion, pathname, fallbackTitle, overrideDocI
13372
13905
  return trimmedQuestion;
13373
13906
  }
13374
13907
  const activeDoc = overrideDocInfo ?? getActiveDocPromptContext();
13375
- const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
13908
+ const rawTitle = (activeDoc?.title || fallbackTitle || getGlobalScope2()?.__shuffleActiveEntityTitle || "Shuffle documentation").trim();
13376
13909
  const title = normalizeDocPromptTitle(rawTitle);
13377
13910
  const groupLabel = activeDoc?.groupLabel;
13378
13911
  const groupId = activeDoc?.groupId;
@@ -16023,6 +16556,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16023
16556
  const cleanId = formatEntityDisplayId(params.id);
16024
16557
  return `Investigate incident ${cleanId} and recommend next steps: `;
16025
16558
  },
16559
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16026
16560
  placeholder: "Ask about this incident, triage observables, or correlate...",
16027
16561
  getStorageKey: (params) => `incident_${params.id}`,
16028
16562
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -16047,6 +16581,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16047
16581
  const cleanId = formatEntityDisplayId(params.id);
16048
16582
  return `Investigate incident ${cleanId} and recommend next steps: `;
16049
16583
  },
16584
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16050
16585
  placeholder: "Ask about this incident, triage observables, or correlate...",
16051
16586
  getStorageKey: (params) => `incident_${params.id}`,
16052
16587
  description: "Focused on the currently viewed incident with Shuffle Incidents MCP"
@@ -16069,6 +16604,7 @@ var DEFAULT_AGENT_CONTEXT_RULES = [
16069
16604
  const cleanId = formatEntityDisplayId(params.id);
16070
16605
  return `Investigate case ${cleanId} and recommend next steps: `;
16071
16606
  },
16607
+ composeInput: (raw) => composeIncidentPromptInput(raw),
16072
16608
  placeholder: "Review case evidence, correlate events, or recommend response actions...",
16073
16609
  getStorageKey: (params) => `case_${params.id}`,
16074
16610
  description: "Focused on the currently viewed case with Shuffle Incidents MCP"
@@ -16799,6 +17335,18 @@ var readPresetAppsOverride = (presetId) => {
16799
17335
  return null;
16800
17336
  }
16801
17337
  };
17338
+ var resolvePresetApps = (preset) => {
17339
+ const baseApps = (preset.defaultApps || []).map((app2) => ({ name: app2.name, id: app2.id, icon: app2.icon }));
17340
+ const assigned = getToolsForSkill(preset.id);
17341
+ const merged = [...baseApps];
17342
+ for (const t of assigned) {
17343
+ const key = (t.id || t.name).toLowerCase();
17344
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
17345
+ merged.push({ name: t.name, id: t.id, icon: t.icon || void 0 });
17346
+ }
17347
+ }
17348
+ return merged;
17349
+ };
16802
17350
  var writePresetAppsOverride = (presetId, apps) => {
16803
17351
  try {
16804
17352
  const raw = localStorage.getItem(PRESET_APPS_STORAGE_KEY);
@@ -17177,8 +17725,12 @@ var extractAuthRequest = (decision) => {
17177
17725
  } else if (raw && typeof raw === "object") {
17178
17726
  parsed = raw;
17179
17727
  }
17180
- const needsAuth = parsed && (parsed.action === "app_authentication" || parsed.app_authentication === true);
17181
- if (!needsAuth) return null;
17728
+ const candidateObjects = [
17729
+ parsed,
17730
+ decision?.result,
17731
+ decision?.run_details,
17732
+ decision
17733
+ ].filter(Boolean);
17182
17734
  let toolAppName;
17183
17735
  let appId = null;
17184
17736
  if (typeof decision?.tool === "string") {
@@ -17191,8 +17743,36 @@ var extractAuthRequest = (decision) => {
17191
17743
  toolAppName = t;
17192
17744
  }
17193
17745
  }
17194
- let appName = parsed.app || parsed.app_name || parsed.appname;
17195
- if (!appName) appName = toolAppName;
17746
+ let needsAuth = false;
17747
+ let candidateAppName;
17748
+ for (const obj of candidateObjects) {
17749
+ if (obj.action === "app_authentication" || obj.app_authentication === true || obj.action === "authenticate" || obj.needs_auth === true || obj.auth_required === true) {
17750
+ needsAuth = true;
17751
+ }
17752
+ const candidate = obj.app || obj.app_name || obj.appname;
17753
+ if (typeof candidate === "string" && candidate.trim()) {
17754
+ candidateAppName = candidate.trim();
17755
+ }
17756
+ }
17757
+ const textSources = [
17758
+ decision?.error,
17759
+ decision?.reason,
17760
+ decision?.status_message,
17761
+ decision?.message,
17762
+ decision?.run_details?.error,
17763
+ typeof raw === "string" ? raw : ""
17764
+ ];
17765
+ const combinedText = textSources.filter(Boolean).join(" ").toLowerCase();
17766
+ 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")) {
17767
+ needsAuth = true;
17768
+ }
17769
+ if (!needsAuth && (decision?.status === "WAITING" || decision?.status === "PENDING" || decision?.run_details?.status === "WAITING" || decision?.run_details?.status === "PENDING")) {
17770
+ if (toolAppName && appRequiresAuthentication(toolAppName)) {
17771
+ needsAuth = true;
17772
+ }
17773
+ }
17774
+ if (!needsAuth) return null;
17775
+ let appName = candidateAppName || toolAppName;
17196
17776
  if (!appName) {
17197
17777
  const f = (decision?.fields || []).find((x) => x?.key === "app" || x?.key === "app_name");
17198
17778
  if (f?.value) appName = f.value;
@@ -17207,12 +17787,17 @@ var STATUS_COLORS = {
17207
17787
  running: "hsl(var(--primary))"
17208
17788
  };
17209
17789
  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 || "";
17790
+ var resolveRunStatus = (execStatus, agentStatus) => {
17791
+ const e = (execStatus || "").toUpperCase();
17792
+ const a = (agentStatus || "").toUpperCase();
17793
+ if (e === "FINISHED" || a === "FINISHED") return "FINISHED";
17794
+ if (e === "FAILURE" || a === "FAILURE") return "FAILURE";
17795
+ if (e === "ABORTED" || a === "ABORTED") return "ABORTED";
17796
+ if (e === "CANCELLED" || a === "CANCELLED" || e === "CANCELED" || a === "CANCELED") return "CANCELLED";
17797
+ if (e === "WAITING" || a === "WAITING") return "WAITING";
17798
+ if (e === "PENDING" || a === "PENDING") return "PENDING";
17799
+ if (e === "RUNNING" || a === "RUNNING" || e === "EXECUTING" || a === "EXECUTING") return "RUNNING";
17800
+ return e || a || "FINISHED";
17216
17801
  };
17217
17802
  var buildToolName = (apps) => {
17218
17803
  if (!apps.length) return "API";
@@ -17236,7 +17821,11 @@ var DurationCountdown = ({ resumeAtMs }) => {
17236
17821
  const remaining = resumeAtMs - nowMs;
17237
17822
  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
17823
  };
17239
- var StatusIcon = ({ status, resumeAtMs }) => {
17824
+ var StatusIcon = ({
17825
+ status,
17826
+ resumeAtMs,
17827
+ authBlockedApp
17828
+ }) => {
17240
17829
  const s = (status || "").toUpperCase();
17241
17830
  const isScheduledWait = s === "WAITING" && !!resumeAtMs;
17242
17831
  const [nowMs, setNowMs] = useState20(() => Date.now());
@@ -17247,7 +17836,10 @@ var StatusIcon = ({ status, resumeAtMs }) => {
17247
17836
  }, [isScheduledWait]);
17248
17837
  let node;
17249
17838
  let label;
17250
- if (s === "RUNNING" || s === "EXECUTING" || s === "") {
17839
+ if (authBlockedApp) {
17840
+ node = /* @__PURE__ */ jsx31(LockIcon3, { size: 20, color: "hsl(var(--destructive))" });
17841
+ label = `Authentication required for ${formatAppDisplayName(authBlockedApp)} \u2014 step cannot proceed until connected`;
17842
+ } else if (s === "RUNNING" || s === "EXECUTING" || s === "") {
17251
17843
  node = /* @__PURE__ */ jsx31(CircularProgress5, { size: 18, sx: { color: STATUS_COLORS.running } });
17252
17844
  label = "Running";
17253
17845
  } else if (s === "WAITING") {
@@ -17446,8 +18038,10 @@ var TimelineRow = ({
17446
18038
  const s = (effectiveStatus || "").toUpperCase();
17447
18039
  return s === "WAITING" || s === "RUNNING" || s === "EXECUTING" || s === "";
17448
18040
  })();
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;
18041
+ const rowAuthReq = extractAuthRequest(details);
18042
+ const isRowAuthBlocked = !!rowAuthReq && !isAppAuthenticated?.(rowAuthReq.appName, rowAuthReq.appId) && (effectiveStatus === "WAITING" || effectiveStatus === "PENDING" || effectiveStatus === "FAILURE" || effectiveStatus === "ABORTED");
18043
+ const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : isFailed || isRowAuthBlocked ? STATUS_COLORS.error : "hsl(var(--muted-foreground) / 0.35)";
18044
+ 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
18045
  const isRerunTarget = !!rerunningDecisionId && item.type === "decision" && details?.run_details?.id === rerunningDecisionId;
17452
18046
  return /* @__PURE__ */ jsxs24(
17453
18047
  Box22,
@@ -17456,9 +18050,25 @@ var TimelineRow = ({
17456
18050
  sx: {
17457
18051
  borderTop: index === 0 ? "none" : "1px solid hsl(var(--border))",
17458
18052
  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,
18053
+ transition: "background-color 0.2s ease",
18054
+ "&:hover": {
18055
+ bgcolor: "hsl(var(--muted) / 0.4)"
18056
+ },
17461
18057
  position: "relative",
18058
+ "&::before": {
18059
+ content: '""',
18060
+ position: "absolute",
18061
+ left: 0,
18062
+ top: 0,
18063
+ bottom: 0,
18064
+ width: 3,
18065
+ bgcolor: barColor,
18066
+ transition: "background-color 0.15s ease"
18067
+ },
18068
+ "&:hover::before": {
18069
+ bgcolor: hoverBarColor
18070
+ },
18071
+ scrollMarginTop: 96,
17462
18072
  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
18073
  opacity: dimmedByRerun ? 0.35 : 1,
17464
18074
  pointerEvents: dimmedByRerun ? "none" : "auto"
@@ -17467,22 +18077,17 @@ var TimelineRow = ({
17467
18077
  /* @__PURE__ */ jsxs24(
17468
18078
  Box22,
17469
18079
  {
17470
- onClick: isProcessing ? void 0 : onToggle,
18080
+ onClick: onToggle,
17471
18081
  sx: {
17472
18082
  display: "flex",
17473
18083
  alignItems: "center",
17474
18084
  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
- }
18085
+ p: 1.5,
18086
+ cursor: "pointer",
18087
+ userSelect: "none"
17483
18088
  },
17484
18089
  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 }) }),
18090
+ /* @__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
18091
  /* @__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
18092
  /* @__PURE__ */ jsx31(
17488
18093
  Tooltip14,
@@ -18001,6 +18606,7 @@ var AgentUI = ({
18001
18606
  composeSubmitInput: propComposeSubmitInput,
18002
18607
  contextParams,
18003
18608
  incidentId: propIncidentId,
18609
+ incidentContext: propIncidentContext,
18004
18610
  vulnerabilityId: propVulnerabilityId,
18005
18611
  workflowId: propWorkflowId
18006
18612
  }) => {
@@ -18015,6 +18621,10 @@ var AgentUI = ({
18015
18621
  return h;
18016
18622
  }, [apiKey, orgId]);
18017
18623
  const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
18624
+ const resolvedIncidentId = propIncidentId || (contextCategory === "incidents" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveIncidentId : void 0);
18625
+ const resolvedIncidentContext = propIncidentContext || (typeof window !== "undefined" ? window.__shuffleActiveIncidentContext : void 0);
18626
+ const resolvedVulnerabilityId = propVulnerabilityId || (contextCategory === "vulnerabilities" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveVulnerabilityId : void 0);
18627
+ const resolvedWorkflowId = propWorkflowId || (contextCategory === "workflows" ? contextParams?.id : void 0) || (typeof window !== "undefined" ? window.__shuffleActiveWorkflowId : void 0);
18018
18628
  const isPhoneScreen = useMediaQuery("(max-width:600px)", { noSsr: true });
18019
18629
  const isPhone = mobileView !== void 0 ? mobileView : isPhoneScreen;
18020
18630
  const [actionInput, setActionInput] = useState20(() => {
@@ -18095,17 +18705,37 @@ var AgentUI = ({
18095
18705
  if (!match || match.enabled === false) return;
18096
18706
  setSelectedPreset(match);
18097
18707
  if (defaultApps === void 0 && !apps) {
18708
+ const resolved = resolvePresetApps(match);
18098
18709
  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 })));
18710
+ if (override && override.length > 0) {
18711
+ const merged = [...override];
18712
+ for (const app2 of resolved) {
18713
+ const key = (app2.id || app2.name).toLowerCase();
18714
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
18715
+ merged.push(app2);
18716
+ }
18717
+ }
18718
+ setChosenApps(merged);
18719
+ } else {
18720
+ setChosenApps(resolved);
18103
18721
  }
18104
18722
  }
18105
18723
  seededPresetIdRef.current = match.id;
18106
18724
  } catch {
18107
18725
  }
18108
18726
  }, [presets, defaultInput, isEffectiveSupport, initialPresetId, defaultApps, apps]);
18727
+ useEffect18(() => {
18728
+ const handleToolsChanged = () => {
18729
+ const targetPreset = selectedPreset || AGENT_PRESETS.find((p) => p.id === "incident-response") || AGENT_PRESETS[0];
18730
+ if (targetPreset) {
18731
+ const next = resolvePresetApps(targetPreset);
18732
+ setChosenApps(next);
18733
+ writePresetAppsOverride(targetPreset.id, next);
18734
+ }
18735
+ };
18736
+ window.addEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
18737
+ return () => window.removeEventListener(AGENT_TOOLS_CHANGED_EVENT, handleToolsChanged);
18738
+ }, [selectedPreset]);
18109
18739
  useLayoutEffect(() => {
18110
18740
  if (hidePresets) {
18111
18741
  setPresetsChipWidth(0);
@@ -18383,13 +19013,19 @@ var AgentUI = ({
18383
19013
  localStorage.setItem(LAST_PRESET_STORAGE_KEY, preset.id);
18384
19014
  } catch {
18385
19015
  }
19016
+ const resolved = resolvePresetApps(preset);
18386
19017
  const override = readPresetAppsOverride(preset.id);
18387
19018
  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 })));
19019
+ const merged = [...override];
19020
+ for (const app2 of resolved) {
19021
+ const key = (app2.id || app2.name).toLowerCase();
19022
+ if (!merged.some((m) => (m.id || m.name).toLowerCase() === key)) {
19023
+ merged.push(app2);
19024
+ }
19025
+ }
19026
+ setChosenApps(merged);
18391
19027
  } else {
18392
- setChosenApps([]);
19028
+ setChosenApps(resolved);
18393
19029
  }
18394
19030
  seededPresetIdRef.current = preset.id;
18395
19031
  if (onSelectPreset) {
@@ -18607,9 +19243,9 @@ var AgentUI = ({
18607
19243
  }, [availableApps]);
18608
19244
  const pendingAuthApps = useMemo10(() => {
18609
19245
  if (authAppsLoading) return [];
18610
- const decisions = agentData?.decisions || [];
18611
19246
  const seen = /* @__PURE__ */ new Set();
18612
19247
  const out = [];
19248
+ const decisions = agentData?.decisions || [];
18613
19249
  for (const d of decisions) {
18614
19250
  const req = extractAuthRequest(d);
18615
19251
  if (!req) continue;
@@ -18621,8 +19257,21 @@ var AgentUI = ({
18621
19257
  const icon = appsById[req.appName]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
18622
19258
  out.push({ appName: req.appName, appId, icon });
18623
19259
  }
19260
+ const hasAllowed = Array.isArray(agentData?.allowed_actions) && agentData.allowed_actions.length > 0;
19261
+ const activeAppList = hasAllowed ? executionApps : chosenApps;
19262
+ for (const app2 of activeAppList) {
19263
+ if (!app2?.name) continue;
19264
+ const slug = normalizeAgentAppName(app2.name);
19265
+ if (seen.has(slug)) continue;
19266
+ if (appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name, app2.id || null)) {
19267
+ seen.add(slug);
19268
+ const appId = app2.id || appsById[app2.name]?.id || appsById[slug]?.id || null;
19269
+ const icon = app2.icon || appsById[app2.name]?.icon || appsById[slug]?.icon || (appId ? appsById[appId]?.icon : "") || "";
19270
+ out.push({ appName: app2.name, appId, icon });
19271
+ }
19272
+ }
18624
19273
  return out;
18625
- }, [agentData, appsById, authAppsLoading, isAppAuthenticated]);
19274
+ }, [agentData, executionApps, chosenApps, appsById, authAppsLoading, isAppAuthenticated]);
18626
19275
  useEffect18(() => {
18627
19276
  if (apps) setChosenApps(apps);
18628
19277
  }, [apps]);
@@ -19237,9 +19886,6 @@ var AgentUI = ({
19237
19886
  return next;
19238
19887
  }, { replace: true });
19239
19888
  }
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
19889
  const result = await runAgent({
19244
19890
  input: composed.trim(),
19245
19891
  skipPolling: true,
@@ -19248,6 +19894,7 @@ var AgentUI = ({
19248
19894
  ...apiBaseUrl ? { apiBaseUrl } : {},
19249
19895
  ...orgId ? { orgId } : {},
19250
19896
  ...resolvedIncidentId ? { incidentId: resolvedIncidentId } : {},
19897
+ ...resolvedIncidentContext ? { incidentContext: resolvedIncidentContext } : {},
19251
19898
  ...resolvedVulnerabilityId ? { vulnerabilityId: resolvedVulnerabilityId } : {},
19252
19899
  ...resolvedWorkflowId ? { workflowId: resolvedWorkflowId } : {},
19253
19900
  // Send a single comma-separated `tool_name` in the format
@@ -19318,6 +19965,13 @@ var AgentUI = ({
19318
19965
  const auth = raw?.authorization;
19319
19966
  if (eid && auth) {
19320
19967
  activeExecutionIdRef.current = eid;
19968
+ if (typeof window !== "undefined") {
19969
+ window.dispatchEvent(
19970
+ new CustomEvent("shuffle:agent_execution_status", {
19971
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
19972
+ })
19973
+ );
19974
+ }
19321
19975
  if (contextStorageKey) {
19322
19976
  setPageContextChoice(contextStorageKey, {
19323
19977
  draftPrompt: "",
@@ -19905,17 +20559,30 @@ var AgentUI = ({
19905
20559
  if (status === "FINISHED" || status === "SUCCESS") {
19906
20560
  window.dispatchEvent(
19907
20561
  new CustomEvent("shuffle:agent_execution_status", {
19908
- detail: { executionId: eid, status: "completed" }
20562
+ detail: { executionId: eid, status: "completed", incidentId: resolvedIncidentId }
19909
20563
  })
19910
20564
  );
20565
+ if (resolvedIncidentId) {
20566
+ window.dispatchEvent(
20567
+ new CustomEvent("incident:refresh", {
20568
+ detail: { id: resolvedIncidentId, incidentId: resolvedIncidentId, executionId: eid }
20569
+ })
20570
+ );
20571
+ }
19911
20572
  } else if (["FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(status)) {
19912
20573
  window.dispatchEvent(
19913
20574
  new CustomEvent("shuffle:agent_execution_status", {
19914
- detail: { executionId: eid, status: "failed" }
20575
+ detail: { executionId: eid, status: "failed", incidentId: resolvedIncidentId }
20576
+ })
20577
+ );
20578
+ } else if (["RUNNING", "EXECUTING", "IN_PROGRESS", "WAITING"].includes(status)) {
20579
+ window.dispatchEvent(
20580
+ new CustomEvent("shuffle:agent_execution_status", {
20581
+ detail: { executionId: eid, status: "running", incidentId: resolvedIncidentId }
19915
20582
  })
19916
20583
  );
19917
20584
  }
19918
- }, [execution?.execution_id, execution?.status, agentData?.status]);
20585
+ }, [execution?.execution_id, execution?.status, agentData?.status, resolvedIncidentId]);
19919
20586
  useEffect18(() => {
19920
20587
  if (!finishDecisionId || agentRequestLoading) return;
19921
20588
  if (continuationFocusedForRef.current === finishDecisionId) return;
@@ -22113,7 +22780,47 @@ var AgentUI = ({
22113
22780
  children: formatAppDisplayName(app2.name || "")
22114
22781
  }
22115
22782
  ),
22116
- (needsAuth || isUnavailable) && /* @__PURE__ */ jsx31(WarningIcon, { size: 14, color: "hsl(var(--severity-medium))", style: { marginRight: 2 } }),
22783
+ needsAuth ? /* @__PURE__ */ jsx31(
22784
+ Box22,
22785
+ {
22786
+ component: "span",
22787
+ sx: {
22788
+ fontSize: "0.65rem",
22789
+ fontWeight: 600,
22790
+ color: "hsl(var(--destructive))",
22791
+ bgcolor: "hsl(var(--destructive) / 0.12)",
22792
+ border: "1px solid hsl(var(--destructive) / 0.3)",
22793
+ borderRadius: 1,
22794
+ px: 0.6,
22795
+ py: 0.1,
22796
+ letterSpacing: "0.02em",
22797
+ textTransform: "uppercase",
22798
+ ml: 0.5,
22799
+ mr: 0.25
22800
+ },
22801
+ children: "Missing auth"
22802
+ }
22803
+ ) : isUnavailable ? /* @__PURE__ */ jsx31(
22804
+ Box22,
22805
+ {
22806
+ component: "span",
22807
+ sx: {
22808
+ fontSize: "0.65rem",
22809
+ fontWeight: 600,
22810
+ color: "hsl(var(--severity-medium))",
22811
+ bgcolor: "hsl(var(--severity-medium) / 0.12)",
22812
+ border: "1px solid hsl(var(--severity-medium) / 0.3)",
22813
+ borderRadius: 1,
22814
+ px: 0.6,
22815
+ py: 0.1,
22816
+ letterSpacing: "0.02em",
22817
+ textTransform: "uppercase",
22818
+ ml: 0.5,
22819
+ mr: 0.25
22820
+ },
22821
+ children: "Unavailable"
22822
+ }
22823
+ ) : null,
22117
22824
  isRequired ? /* @__PURE__ */ jsx31(
22118
22825
  LockIcon3,
22119
22826
  {
@@ -22315,43 +23022,83 @@ var AgentUI = ({
22315
23022
  return list;
22316
23023
  })().map((app2, i) => {
22317
23024
  const slug = normalizeAgentAppName(app2.name || "");
23025
+ const appNeedsAuth = !authAppsLoading && appRequiresAuthentication(slug) && !isAppAuthenticated(app2.name || "", app2.id || null);
22318
23026
  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,
23027
+ return /* @__PURE__ */ jsx31(
23028
+ Tooltip14,
22321
23029
  {
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
- },
23030
+ title: appNeedsAuth ? `${formatAppDisplayName(app2.name || "")} \u2014 Missing authentication (Click to connect)` : formatAppDisplayName(app2.name || ""),
22336
23031
  children: /* @__PURE__ */ jsx31(
22337
- AppFallbackIcon,
23032
+ Box22,
22338
23033
  {
22339
- name: app2.name,
22340
- imageUrl: appIcon,
22341
- size: 24,
22342
- style: { borderRadius: 6, objectFit: "contain" }
23034
+ onClick: () => setAuthDrawerApp({ name: app2.name, id: app2.id || null }),
23035
+ sx: {
23036
+ display: "inline-flex",
23037
+ alignItems: "center",
23038
+ justifyContent: "center",
23039
+ width: 24,
23040
+ height: 24,
23041
+ borderRadius: "6px",
23042
+ overflow: "hidden",
23043
+ bgcolor: "hsl(var(--muted))",
23044
+ cursor: "pointer",
23045
+ transition: "transform 0.15s ease, border-color 0.15s ease",
23046
+ border: appNeedsAuth ? "2px solid hsl(var(--destructive)) !important" : "none",
23047
+ boxShadow: appNeedsAuth ? "0 0 0 1px hsl(var(--destructive) / 0.4)" : "none",
23048
+ "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
23049
+ },
23050
+ children: /* @__PURE__ */ jsx31(
23051
+ AppFallbackIcon,
23052
+ {
23053
+ name: app2.name,
23054
+ imageUrl: appIcon,
23055
+ size: 24,
23056
+ style: { borderRadius: 6, objectFit: "contain" }
23057
+ }
23058
+ )
22343
23059
  }
22344
23060
  )
22345
- }
22346
- ) }, i);
23061
+ },
23062
+ i
23063
+ );
22347
23064
  }) }),
22348
23065
  /* @__PURE__ */ jsxs24(Box22, { sx: { flex: 1, minWidth: 0 }, children: [
22349
23066
  /* @__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) || ""
23067
+ /* @__PURE__ */ jsxs24(Typography19, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))", display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap", mt: 0.25 }, children: [
23068
+ /* @__PURE__ */ jsxs24("span", { children: [
23069
+ "Status: ",
23070
+ execution?.status || agentData?.status || "\u2014",
23071
+ " \xB7 ",
23072
+ execution?.execution_id?.slice(0, 8) || ""
23073
+ ] }),
23074
+ pendingAuthApps.length > 0 && /* @__PURE__ */ jsxs24(
23075
+ Box22,
23076
+ {
23077
+ component: "span",
23078
+ onClick: () => setAuthDrawerApp({ name: pendingAuthApps[0].appName, id: pendingAuthApps[0].appId }),
23079
+ sx: {
23080
+ display: "inline-flex",
23081
+ alignItems: "center",
23082
+ gap: 0.5,
23083
+ px: 0.75,
23084
+ py: 0.15,
23085
+ borderRadius: 1,
23086
+ bgcolor: "hsl(var(--destructive) / 0.12)",
23087
+ border: "1px solid hsl(var(--destructive) / 0.35)",
23088
+ color: "hsl(var(--destructive))",
23089
+ fontSize: "0.68rem",
23090
+ fontWeight: 600,
23091
+ cursor: "pointer",
23092
+ textTransform: "none",
23093
+ "&:hover": { bgcolor: "hsl(var(--destructive) / 0.2)" }
23094
+ },
23095
+ children: [
23096
+ "Missing Auth: ",
23097
+ pendingAuthApps.map((a) => formatAppDisplayName(a.appName)).join(", "),
23098
+ " \u2014 Connect"
23099
+ ]
23100
+ }
23101
+ )
22355
23102
  ] })
22356
23103
  ] }),
22357
23104
  /* @__PURE__ */ jsx31(AgentAttachmentsButton_default, { attachments: llmImageAttachments }),
@@ -22531,6 +23278,57 @@ var AgentUI = ({
22531
23278
  }
22532
23279
  }
22533
23280
  ),
23281
+ pendingAuthApps.length > 0 && /* @__PURE__ */ jsxs24(
23282
+ Box22,
23283
+ {
23284
+ sx: {
23285
+ mb: 2,
23286
+ p: 2,
23287
+ borderRadius: 2,
23288
+ border: "1px solid hsla(var(--severity-medium) / 0.35)",
23289
+ bgcolor: "hsla(var(--severity-medium) / 0.08)",
23290
+ display: "flex",
23291
+ alignItems: "center",
23292
+ justifyContent: "space-between",
23293
+ gap: 2,
23294
+ flexWrap: "wrap"
23295
+ },
23296
+ children: [
23297
+ /* @__PURE__ */ jsxs24(Box22, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1, minWidth: 260 }, children: [
23298
+ /* @__PURE__ */ jsx31(LockIcon3, { size: 22, color: "hsl(var(--severity-medium))" }),
23299
+ /* @__PURE__ */ jsxs24(Box22, { sx: { flex: 1, minWidth: 0 }, children: [
23300
+ /* @__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` }),
23301
+ /* @__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.` })
23302
+ ] })
23303
+ ] }),
23304
+ /* @__PURE__ */ jsx31(Box22, { sx: { display: "flex", gap: 1, flexWrap: "wrap" }, children: pendingAuthApps.map(({ appName, appId }) => /* @__PURE__ */ jsxs24(
23305
+ Button13,
23306
+ {
23307
+ variant: "outlined",
23308
+ size: "small",
23309
+ onClick: () => setAuthDrawerApp({ name: appName, id: appId }),
23310
+ sx: {
23311
+ borderColor: "hsla(var(--severity-medium) / 0.6)",
23312
+ color: "hsl(var(--foreground))",
23313
+ textTransform: "none",
23314
+ fontSize: "0.75rem",
23315
+ fontWeight: 600,
23316
+ height: 32,
23317
+ "&:hover": {
23318
+ bgcolor: "hsla(var(--severity-medium) / 0.15)",
23319
+ borderColor: "hsl(var(--severity-medium))"
23320
+ }
23321
+ },
23322
+ children: [
23323
+ "Authenticate ",
23324
+ formatAppDisplayName(appName)
23325
+ ]
23326
+ },
23327
+ appName
23328
+ )) })
23329
+ ]
23330
+ }
23331
+ ),
22534
23332
  viewMode === "simple" && /* @__PURE__ */ jsx31(Box22, { sx: {
22535
23333
  borderRadius: 2,
22536
23334
  border: "1px solid hsl(var(--border))",
@@ -22572,7 +23370,7 @@ var AgentUI = ({
22572
23370
  }
22573
23371
  const pendingAnswered = pendingQuestions.every((q) => questionAnswers[q.question]?.value);
22574
23372
  return /* @__PURE__ */ jsxs24(Fragment12, { children: [
22575
- /* @__PURE__ */ jsxs24(
23373
+ /* @__PURE__ */ jsx31(
22576
23374
  RunFinishedSummary,
22577
23375
  {
22578
23376
  status,
@@ -22585,77 +23383,7 @@ var AgentUI = ({
22585
23383
  durationSec,
22586
23384
  showMeta: true,
22587
23385
  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
- ]
23386
+ children: !isRunning && postRunDiscovery
22659
23387
  }
22660
23388
  ),
22661
23389
  !finishAnswer && pendingAsk && pendingQuestions.length > 0 ? (() => {
@@ -27005,6 +27733,8 @@ var AskAiSidePanel = ({
27005
27733
  defaultInput,
27006
27734
  serverside,
27007
27735
  colorMode,
27736
+ incidentId: propIncidentId,
27737
+ incidentContext: propIncidentContext,
27008
27738
  sx
27009
27739
  }) => {
27010
27740
  const themeScope = useShuffleMcpTheme();
@@ -27127,11 +27857,15 @@ var AskAiSidePanel = ({
27127
27857
  }, [open, initialTab, onTabChange]);
27128
27858
  const [activeTaskId, setActiveTaskId] = useState29(null);
27129
27859
  const [activeExecutionId, setActiveExecutionId] = useState29(null);
27860
+ const [activeIncidentId, setActiveIncidentId] = useState29(null);
27861
+ const [activeIncidentContext, setActiveIncidentContext] = useState29(null);
27130
27862
  const [runResetKey, setRunResetKey] = useState29(0);
27131
27863
  useEffect26(() => {
27132
27864
  if (!open) {
27133
27865
  setActiveTaskId(null);
27134
27866
  setActiveExecutionId(null);
27867
+ setActiveIncidentId(null);
27868
+ setActiveIncidentContext(null);
27135
27869
  }
27136
27870
  }, [open]);
27137
27871
  useEffect26(() => {
@@ -27163,6 +27897,12 @@ var AskAiSidePanel = ({
27163
27897
  } else if (!detail?.tab) {
27164
27898
  setActiveTaskId(null);
27165
27899
  }
27900
+ if (detail?.incidentId !== void 0) {
27901
+ setActiveIncidentId(detail.incidentId || null);
27902
+ }
27903
+ if (detail?.incidentContext !== void 0) {
27904
+ setActiveIncidentContext(detail.incidentContext || null);
27905
+ }
27166
27906
  if (detail?.resetExecution) {
27167
27907
  setActiveExecutionId(null);
27168
27908
  setRunResetKey((k) => k + 1);
@@ -27796,6 +28536,8 @@ var AskAiSidePanel = ({
27796
28536
  onAppsChange: handleAppsChange,
27797
28537
  onSelectPreset: handleSelectPreset,
27798
28538
  onChooseLLM: () => handleTabChange("localLLM"),
28539
+ incidentId: activeIncidentId || propIncidentId || agentUIProps?.incidentId,
28540
+ incidentContext: activeIncidentContext || propIncidentContext || agentUIProps?.incidentContext,
27799
28541
  apiBaseUrl: globalUrl || agentUIProps?.apiBaseUrl,
27800
28542
  theme: effectiveTheme,
27801
28543
  sx: {