@shuffleio/shuffle-mcps 0.0.36 → 0.0.38

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://security.shuffler.io/mcp/agent-icon.png" alt="Shuffle MCPs" width="96" />
3
+ <img src="https://shuffle.security/mcp/agent-icon.png" alt="Shuffle MCPs" width="96" />
4
4
 
5
5
  # Shuffle MCPs
6
6
 
@@ -26,11 +26,11 @@ Turn 3,000+ SaaS tools into MCP servers your agents can use. One search, one cli
26
26
  </tr>
27
27
  <tr>
28
28
  <td align="center" width="50%">
29
- <img src="https://security.shuffler.io/mcp/search-preview.png" alt="Search 3,000+ integrations" width="380" style="border-radius: 12px;" />
29
+ <img src="https://shuffle.security/mcp/search-preview.png" alt="Search 3,000+ integrations" width="380" style="border-radius: 12px;" />
30
30
  <br/><sub><b>3. Search any of 3,000+ tools</b></sub>
31
31
  </td>
32
32
  <td align="center" width="50%">
33
- <img src="https://security.shuffler.io/mcp/app-detail-preview.png" alt="Authenticate and use as MCP" width="380" style="border-radius: 12px;" />
33
+ <img src="https://shuffle.security/mcp/app-detail-preview.png" alt="Authenticate and use as MCP" width="380" style="border-radius: 12px;" />
34
34
  <br/><sub><b>4. Authenticate — your agent uses it instantly</b></sub>
35
35
  </td>
36
36
  </tr>
@@ -38,7 +38,7 @@ Turn 3,000+ SaaS tools into MCP servers your agents can use. One search, one cli
38
38
 
39
39
  &nbsp;
40
40
 
41
- > **See it live:** [security.shuffler.io/shuffle-mcp-demo](https://security.shuffler.io/shuffle-mcp-demo) — a fully working demo of every component in this package (inline search, search drawer, app detail drawer, auth, Try MCP, and Try individual actions). No login required.
41
+ > **See it live:** [shuffle.security/shuffle-mcp-demo](https://shuffle.security/shuffle-mcp-demo) — a fully working demo of every component in this package (inline search, search drawer, app detail drawer, auth, Try MCP, and Try individual actions). No login required.
42
42
 
43
43
  > **No SDK required.** Once a tool is authenticated in Shuffle, it is live as an MCP server immediately — call it from any agent over plain HTTP. This npm package is the optional UI layer for embedding the search-and-connect flow inside your own product.
44
44
 
@@ -99,13 +99,13 @@ The library exports six React components — use one or all of them. They share
99
99
 
100
100
  | Component | What it does | Live demo |
101
101
  |---|---|---|
102
- | [`<ShuffleMCP />`](#1-shufflemcp--inline-search) | Inline search box that merges Algolia's 3,000+ public app catalog with the current user's private apps | [/shuffle-mcp-demo §1](https://security.shuffler.io/shuffle-mcp-demo) |
103
- | [`<AppSearchDrawer />`](#2-appsearchdrawer--full-search-drawer) | Right-side drawer wrapping `<ShuffleMCP />` plus a "Your apps" status row. This is the exact "Add Ingestion Source" drawer used in production | [/shuffle-mcp-demo §2](https://security.shuffler.io/shuffle-mcp-demo) |
104
- | [`<AppDetailDrawer />`](#3-appdetaildrawer--single-app-config) | Right-side drawer for a single app: list/edit/test authentications and try the MCP `tools/call` endpoint inline | [/shuffle-mcp-demo §3](https://security.shuffler.io/shuffle-mcp-demo) |
105
- | [`<AgentUI />`](#4-agentui--start--debug-agents) | Standalone "What do you want to do?" hero prompt + live decision-by-decision debugger for `/api/v1/agent` runs. Drop-in replacement for the legacy Shuffle Core agent page | [/agents](https://security.shuffler.io/agents) |
106
- | [`<AgentRunDrawer />`](#5-agentrundrawer--run-agent-side-panel) | Right-side drawer that hosts `<AgentUI />` in compact mode plus optional caller-provided **Permissions** and **Local LLM** tabs (slot-driven, no host context required) | [/shuffle-mcp-demo §1b](https://security.shuffler.io/shuffle-mcp-demo) |
107
- | [`<AgentActivityList />`](#6-agentactivitylist--past-executions) | Searchable, status-filterable list of past `/api/v1/agent` runs. Pair with `<AgentExecutionDrawer />` to inspect any row in the canonical Simple/Detailed view | [/shuffle-mcp-demo §8](https://security.shuffler.io/shuffle-mcp-demo) |
108
- | [`<AgentExecutionDrawer />`](#7-agentexecutiondrawer--inspect-one-run) | Right-side drawer that pre-loads a single `AgentRun` into `<AgentUI />` (no `authorization` token required) for read-only inspection | [/agents](https://security.shuffler.io/agents) |
102
+ | [`<ShuffleMCP />`](#1-shufflemcp--inline-search) | Inline search box that merges Algolia's 3,000+ public app catalog with the current user's private apps | [/shuffle-mcp-demo §1](https://shuffle.security/shuffle-mcp-demo) |
103
+ | [`<AppSearchDrawer />`](#2-appsearchdrawer--full-search-drawer) | Right-side drawer wrapping `<ShuffleMCP />` plus a "Your apps" status row. This is the exact "Add Ingestion Source" drawer used in production | [/shuffle-mcp-demo §2](https://shuffle.security/shuffle-mcp-demo) |
104
+ | [`<AppDetailDrawer />`](#3-appdetaildrawer--single-app-config) | Right-side drawer for a single app: list/edit/test authentications and try the MCP `tools/call` endpoint inline | [/shuffle-mcp-demo §3](https://shuffle.security/shuffle-mcp-demo) |
105
+ | [`<AgentUI />`](#4-agentui--start--debug-agents) | Standalone "What do you want to do?" hero prompt + live decision-by-decision debugger for `/api/v1/agent` runs. Drop-in replacement for the legacy Shuffle Core agent page | [/agents](https://shuffle.security/agents) |
106
+ | [`<AgentRunDrawer />`](#5-agentrundrawer--run-agent-side-panel) | Right-side drawer that hosts `<AgentUI />` in compact mode plus optional caller-provided **Permissions** and **Local LLM** tabs (slot-driven, no host context required) | [/shuffle-mcp-demo §1b](https://shuffle.security/shuffle-mcp-demo) |
107
+ | [`<AgentActivityList />`](#6-agentactivitylist--past-executions) | Searchable, status-filterable list of past `/api/v1/agent` runs. Pair with `<AgentExecutionDrawer />` to inspect any row in the canonical Simple/Detailed view | [/shuffle-mcp-demo §8](https://shuffle.security/shuffle-mcp-demo) |
108
+ | [`<AgentExecutionDrawer />`](#7-agentexecutiondrawer--inspect-one-run) | Right-side drawer that pre-loads a single `AgentRun` into `<AgentUI />` (no `authorization` token required) for read-only inspection | [/agents](https://shuffle.security/agents) |
109
109
 
110
110
  ### 1. `<ShuffleMCP />` — inline search
111
111
 
@@ -252,7 +252,7 @@ Useful props:
252
252
  | `onRun` | `(info) => void` | Fires whenever a run finishes (success or failure) |
253
253
  | `className` / `sx` / `contentSx` | `string` / `SxProps` | Style overrides for the root container and inner content column |
254
254
 
255
- Reference page in production: [`src/pages/dashboard/AgentsPage.tsx`](../pages/dashboard/AgentsPage.tsx) (mounted at [`/agents`](https://security.shuffler.io/agents)).
255
+ Reference page in production: [`src/pages/dashboard/AgentsPage.tsx`](../pages/dashboard/AgentsPage.tsx) (mounted at [`/agents`](https://shuffle.security/agents)).
256
256
 
257
257
  ### 5. `<AgentRunDrawer />` — Run Agent side panel
258
258
 
@@ -2,7 +2,7 @@ import {
2
2
  fetchApps,
3
3
  fetchAppsViaApiConfig,
4
4
  invalidateAppsCache
5
- } from "./chunk-IABSYB2J.mjs";
5
+ } from "./chunk-DCHKGFML.mjs";
6
6
  export {
7
7
  fetchApps,
8
8
  fetchAppsViaApiConfig,
@@ -50,6 +50,30 @@ var keyFor = (input, init) => {
50
50
  return null;
51
51
  }
52
52
  };
53
+ var withStoredApiKey = (input, init) => {
54
+ if (typeof window === "undefined") return init;
55
+ let urlStr;
56
+ if (typeof input === "string") urlStr = input;
57
+ else if (input instanceof URL) urlStr = input.toString();
58
+ else if (input && typeof input.url === "string") urlStr = input.url;
59
+ else return init;
60
+ try {
61
+ const url = new URL(urlStr, window.location.href);
62
+ const isKnownShuffleOrigin = allowedOrigins.has(url.origin) || url.origin === window.location.origin || url.hostname === "shuffler.io" || url.hostname.endsWith(".shuffler.io") || url.hostname === "tunnel.schemaless.org";
63
+ if (!url.pathname.startsWith("/api/") || !isKnownShuffleOrigin) return init;
64
+ const apiKey = window.localStorage.getItem("shuffle_api_key");
65
+ if (!apiKey) return init;
66
+ const requestHeaders = typeof Request !== "undefined" && input instanceof Request ? input.headers : void 0;
67
+ const headers = new Headers(requestHeaders);
68
+ if (init?.headers) {
69
+ new Headers(init.headers).forEach((value, name) => headers.set(name, value));
70
+ }
71
+ if (!headers.has("Authorization")) headers.set("Authorization", `Bearer ${apiKey}`);
72
+ return { ...init, headers };
73
+ } catch {
74
+ return init;
75
+ }
76
+ };
53
77
  var synthetic503 = (key, retryInMs) => new Response(
54
78
  JSON.stringify({
55
79
  error: "circuit_breaker_open",
@@ -75,8 +99,9 @@ var installFetchBreaker = () => {
75
99
  installed = true;
76
100
  const original = window.fetch.bind(window);
77
101
  window.fetch = (async (input, init) => {
78
- const key = keyFor(input, init);
79
- if (!key) return original(input, init);
102
+ const authenticatedInit = withStoredApiKey(input, init);
103
+ const key = keyFor(input, authenticatedInit);
104
+ if (!key) return original(input, authenticatedInit);
80
105
  const entry = getEntry(key);
81
106
  const now = Date.now();
82
107
  let isProbe = false;
@@ -110,7 +135,7 @@ var installFetchBreaker = () => {
110
135
  };
111
136
  let response;
112
137
  try {
113
- response = await original(input, init);
138
+ response = await original(input, authenticatedInit);
114
139
  } catch (err) {
115
140
  const ts = Date.now();
116
141
  entry.failures.push(ts);
@@ -150,11 +175,65 @@ var installFetchBreaker = () => {
150
175
  });
151
176
  };
152
177
 
178
+ // ../lib/platform.ts
179
+ var getPlatform = () => {
180
+ if (typeof window === "undefined") return "web";
181
+ const cap = window.Capacitor;
182
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
183
+ const platform = typeof cap.getPlatform === "function" ? cap.getPlatform() : "";
184
+ if (platform === "ios") return "ios";
185
+ if (platform === "android") return "android";
186
+ }
187
+ const ua = window.navigator?.userAgent || "";
188
+ if (/iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) {
189
+ return "ios";
190
+ }
191
+ if (/android/i.test(ua)) {
192
+ return "android";
193
+ }
194
+ return "web";
195
+ };
196
+ var isCapacitorNative = () => {
197
+ if (typeof window === "undefined") return false;
198
+ const cap = window.Capacitor;
199
+ return Boolean(cap?.isNativePlatform && cap.isNativePlatform());
200
+ };
201
+ var isIosWebView = () => {
202
+ if (typeof window === "undefined") return false;
203
+ const cap = window.Capacitor;
204
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
205
+ return typeof cap.getPlatform === "function" ? cap.getPlatform() === "ios" : true;
206
+ }
207
+ const ua = window.navigator?.userAgent || "";
208
+ const isIosDevice = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
209
+ const isStandalonePwa = window.navigator.standalone === true || typeof window.matchMedia === "function" && window.matchMedia("(display-mode: standalone)").matches;
210
+ const isEmbeddedWebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(ua);
211
+ return isIosDevice && (isStandalonePwa || isEmbeddedWebview);
212
+ };
213
+ var isAndroidWebView = () => {
214
+ if (typeof window === "undefined") return false;
215
+ const cap = window.Capacitor;
216
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
217
+ return typeof cap.getPlatform === "function" ? cap.getPlatform() === "android" : false;
218
+ }
219
+ const ua = window.navigator?.userAgent || "";
220
+ const isAndroidDevice = /android/i.test(ua);
221
+ const isStandalone = typeof window.matchMedia === "function" && window.matchMedia("(display-mode: standalone)").matches;
222
+ const isWebview = /;\s*wv|Version\/[\d.]+/i.test(ua) && isAndroidDevice;
223
+ return isAndroidDevice && (isStandalone || isWebview);
224
+ };
225
+ if (typeof window !== "undefined") {
226
+ window.isCapacitorNative = isCapacitorNative;
227
+ window.isIosWebView = isIosWebView;
228
+ window.isAndroidWebView = isAndroidWebView;
229
+ window.getPlatform = getPlatform;
230
+ }
231
+
153
232
  // api.ts
154
233
  installFetchBreaker();
155
234
  var DEV_BACKEND = "https://tunnel.schemaless.org";
156
235
  var PROD_BACKEND = "https://shuffler.io";
157
- var CLOUD_DOMAINS = ["security.shuffler.io", "shutdown.no"];
236
+ var CLOUD_DOMAINS = ["shuffle.security", "www.shuffle.security", "security.shuffler.io", "shutdown.no", "www.shutdown.no"];
158
237
  var getEnvVar = (key) => {
159
238
  try {
160
239
  const meta = new Function("try { return import.meta } catch { return undefined }")();
@@ -169,6 +248,7 @@ var isDevEnvironment = () => {
169
248
  return hostname.includes("lovableproject.com") || hostname.includes("id-preview--") || hostname.endsWith(".lovable.app") || hostname.endsWith(".lovable.dev");
170
249
  };
171
250
  var isCloudDomain = () => {
251
+ if (isCapacitorNative()) return true;
172
252
  const hostname = typeof window !== "undefined" ? window.location.hostname : "";
173
253
  return CLOUD_DOMAINS.includes(hostname);
174
254
  };
@@ -180,6 +260,7 @@ var getDefaultBaseUrl = () => {
180
260
  return envUrl;
181
261
  }
182
262
  if (isDevEnvironment()) return DEV_BACKEND;
263
+ if (isCapacitorNative()) return PROD_BACKEND;
183
264
  if (isCloudDomain()) return PROD_BACKEND;
184
265
  if (typeof window !== "undefined") {
185
266
  return window.location.origin;
@@ -200,8 +281,17 @@ var readCachedRegion = () => {
200
281
  };
201
282
  var cached = readCachedRegion();
202
283
  var _regionUrl = cached.url;
284
+ var readCachedCustomHost = () => {
285
+ if (typeof window === "undefined") return null;
286
+ try {
287
+ const raw = localStorage.getItem("shuffle_custom_host_url");
288
+ return raw ? raw.trim().replace(/\/+$/, "") : null;
289
+ } catch {
290
+ return null;
291
+ }
292
+ };
203
293
  var _trackedOrgId = cached.orgId;
204
- var _hostBaseUrl = null;
294
+ var _hostBaseUrl = readCachedCustomHost();
205
295
  var REGION_EVENT = "shuffle:region-url";
206
296
  var _lastBroadcastUrl = cached.url;
207
297
  var persistRegion = (url, orgId) => {
@@ -350,6 +440,14 @@ var getAuthHeader = (overrideOrgId) => {
350
440
  }
351
441
  return headers;
352
442
  };
443
+ var hasShuffleAuth = () => {
444
+ try {
445
+ if (API_CONFIG.apiKey) return true;
446
+ return !!(localStorage.getItem("session_token") || localStorage.getItem("shuffle_user_info"));
447
+ } catch {
448
+ return false;
449
+ }
450
+ };
353
451
 
354
452
  // appsCache.ts
355
453
  var TTL_MS = 3e4;
@@ -406,6 +504,7 @@ var fetchAppsViaApiConfig = () => {
406
504
  export {
407
505
  registerProtectedOrigin,
408
506
  installFetchBreaker,
507
+ isCapacitorNative,
409
508
  isCloudDomain,
410
509
  isCloud,
411
510
  isOnprem,
@@ -419,6 +518,7 @@ export {
419
518
  getApiUrl,
420
519
  shuffleFetch,
421
520
  getAuthHeader,
521
+ hasShuffleAuth,
422
522
  fetchApps,
423
523
  invalidateAppsCache,
424
524
  fetchAppsViaApiConfig
package/dist/index.d.mts CHANGED
@@ -359,6 +359,11 @@ interface AgentPreset {
359
359
  id?: string;
360
360
  icon?: string;
361
361
  }>;
362
+ /**
363
+ * Tools this skill cannot run without. They are always selected and cannot
364
+ * be removed from the Tools chip row while the skill is active.
365
+ */
366
+ requiredApps?: string[];
362
367
  }
363
368
  declare const AGENT_PRESETS: AgentPreset[];
364
369
  interface AgentPresetsProps {
@@ -374,8 +379,10 @@ interface AgentPresetsProps {
374
379
  presets?: AgentPreset[];
375
380
  /** Ref forwarded to the trigger button so the host can measure its width. */
376
381
  chipRef?: React.Ref<HTMLButtonElement>;
382
+ /** Authoritative support flag from the host's getinfo payload. */
383
+ isSupport?: boolean;
377
384
  }
378
- declare const AgentPresets: ({ variant, onSelectPreset, selectedPreset, onRemoveSelected, presets, chipRef }: AgentPresetsProps) => React$1.JSX.Element;
385
+ declare const AgentPresets: ({ variant, onSelectPreset, selectedPreset, onRemoveSelected, presets, chipRef, isSupport }: AgentPresetsProps) => React$1.JSX.Element;
379
386
 
380
387
  /**
381
388
  * AgentUI — Standalone "start + debug agents" surface.
@@ -416,6 +423,20 @@ interface AgentUIProps {
416
423
  * token to be set on `API_CONFIG`).
417
424
  */
418
425
  autoLoadApps?: boolean;
426
+ /** Authoritative support flag from `/api/v1/getinfo`. */
427
+ isSupport?: boolean;
428
+ /**
429
+ * Optional per-skill readiness CTAs. Keyed by skill (preset) id. When the
430
+ * matching skill is selected and the host reports it has no real content
431
+ * yet, AgentUI renders a small call-to-action under the prompt.
432
+ */
433
+ presetCtas?: Record<string, {
434
+ /** When false, nothing is rendered (content exists / still loading). */
435
+ show?: boolean;
436
+ message: string;
437
+ actionLabel: string;
438
+ onAction?: () => void;
439
+ }>;
419
440
  /** Hero title above the prompt. */
420
441
  title?: string;
421
442
  /** Optional subtitle/description shown under the title. */
@@ -773,6 +794,8 @@ interface AgentActivityResponse {
773
794
  interface AgentActivityParams {
774
795
  cursor?: string;
775
796
  limit?: number;
797
+ /** Optional page size sent as the `?top` query parameter. */
798
+ top?: number;
776
799
  status?: string;
777
800
  startTime?: string;
778
801
  endTime?: string;
@@ -854,6 +877,8 @@ interface AgentActivityListProps extends ShuffleHostProps {
854
877
  showStatusChips?: boolean;
855
878
  /** Page size. Default: 50. */
856
879
  limit?: number;
880
+ /** Optional page size sent as the `?top` query parameter. */
881
+ top?: number;
857
882
  /** Empty-state heading. */
858
883
  emptyTitle?: string;
859
884
  /** Empty-state subtitle. */
@@ -940,6 +965,8 @@ interface AgentsViewProps extends ShuffleHostProps {
940
965
  appsStorageKey?: string;
941
966
  /** Usecase-backed agent types shown in the activity list filter dropdown. */
942
967
  usecaseFilters?: AgentUsecaseFilter[];
968
+ /** Per-skill readiness CTAs forwarded to the embedded AgentUI. */
969
+ presetCtas?: AgentUIProps['presetCtas'];
943
970
  }
944
971
 
945
972
  interface AgentLocalModel {
@@ -1495,6 +1522,8 @@ declare const DATASTORE_CATEGORIES: {
1495
1522
  readonly INCIDENTS: "shuffle-security_incidents";
1496
1523
  readonly VULNERABILITIES: "shuffle-security_vulnerabilities";
1497
1524
  readonly ASSETS: "shuffle-security_assets";
1525
+ readonly PACKAGES: "shuffle-security_packages";
1526
+ readonly SOFTWARE: "shuffle-security_software";
1498
1527
  readonly TEMPLATES: "shuffle-security_templates";
1499
1528
  readonly CONFIGURATION: "shuffle-security_configuration";
1500
1529
  readonly IOCS: "shuffle-security_ioc-config";
package/dist/index.d.ts CHANGED
@@ -359,6 +359,11 @@ interface AgentPreset {
359
359
  id?: string;
360
360
  icon?: string;
361
361
  }>;
362
+ /**
363
+ * Tools this skill cannot run without. They are always selected and cannot
364
+ * be removed from the Tools chip row while the skill is active.
365
+ */
366
+ requiredApps?: string[];
362
367
  }
363
368
  declare const AGENT_PRESETS: AgentPreset[];
364
369
  interface AgentPresetsProps {
@@ -374,8 +379,10 @@ interface AgentPresetsProps {
374
379
  presets?: AgentPreset[];
375
380
  /** Ref forwarded to the trigger button so the host can measure its width. */
376
381
  chipRef?: React.Ref<HTMLButtonElement>;
382
+ /** Authoritative support flag from the host's getinfo payload. */
383
+ isSupport?: boolean;
377
384
  }
378
- declare const AgentPresets: ({ variant, onSelectPreset, selectedPreset, onRemoveSelected, presets, chipRef }: AgentPresetsProps) => React$1.JSX.Element;
385
+ declare const AgentPresets: ({ variant, onSelectPreset, selectedPreset, onRemoveSelected, presets, chipRef, isSupport }: AgentPresetsProps) => React$1.JSX.Element;
379
386
 
380
387
  /**
381
388
  * AgentUI — Standalone "start + debug agents" surface.
@@ -416,6 +423,20 @@ interface AgentUIProps {
416
423
  * token to be set on `API_CONFIG`).
417
424
  */
418
425
  autoLoadApps?: boolean;
426
+ /** Authoritative support flag from `/api/v1/getinfo`. */
427
+ isSupport?: boolean;
428
+ /**
429
+ * Optional per-skill readiness CTAs. Keyed by skill (preset) id. When the
430
+ * matching skill is selected and the host reports it has no real content
431
+ * yet, AgentUI renders a small call-to-action under the prompt.
432
+ */
433
+ presetCtas?: Record<string, {
434
+ /** When false, nothing is rendered (content exists / still loading). */
435
+ show?: boolean;
436
+ message: string;
437
+ actionLabel: string;
438
+ onAction?: () => void;
439
+ }>;
419
440
  /** Hero title above the prompt. */
420
441
  title?: string;
421
442
  /** Optional subtitle/description shown under the title. */
@@ -773,6 +794,8 @@ interface AgentActivityResponse {
773
794
  interface AgentActivityParams {
774
795
  cursor?: string;
775
796
  limit?: number;
797
+ /** Optional page size sent as the `?top` query parameter. */
798
+ top?: number;
776
799
  status?: string;
777
800
  startTime?: string;
778
801
  endTime?: string;
@@ -854,6 +877,8 @@ interface AgentActivityListProps extends ShuffleHostProps {
854
877
  showStatusChips?: boolean;
855
878
  /** Page size. Default: 50. */
856
879
  limit?: number;
880
+ /** Optional page size sent as the `?top` query parameter. */
881
+ top?: number;
857
882
  /** Empty-state heading. */
858
883
  emptyTitle?: string;
859
884
  /** Empty-state subtitle. */
@@ -940,6 +965,8 @@ interface AgentsViewProps extends ShuffleHostProps {
940
965
  appsStorageKey?: string;
941
966
  /** Usecase-backed agent types shown in the activity list filter dropdown. */
942
967
  usecaseFilters?: AgentUsecaseFilter[];
968
+ /** Per-skill readiness CTAs forwarded to the embedded AgentUI. */
969
+ presetCtas?: AgentUIProps['presetCtas'];
943
970
  }
944
971
 
945
972
  interface AgentLocalModel {
@@ -1495,6 +1522,8 @@ declare const DATASTORE_CATEGORIES: {
1495
1522
  readonly INCIDENTS: "shuffle-security_incidents";
1496
1523
  readonly VULNERABILITIES: "shuffle-security_vulnerabilities";
1497
1524
  readonly ASSETS: "shuffle-security_assets";
1525
+ readonly PACKAGES: "shuffle-security_packages";
1526
+ readonly SOFTWARE: "shuffle-security_software";
1498
1527
  readonly TEMPLATES: "shuffle-security_templates";
1499
1528
  readonly CONFIGURATION: "shuffle-security_configuration";
1500
1529
  readonly IOCS: "shuffle-security_ioc-config";