@trops/dash-core 0.1.505 → 0.1.507

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.
@@ -3,7 +3,7 @@
3
3
  var require$$0$1 = require('electron');
4
4
  var require$$1$1 = require('path');
5
5
  var require$$0$2 = require('fs');
6
- var require$$8$1 = require('objects-to-csv');
6
+ var require$$9$1 = require('objects-to-csv');
7
7
  var require$$1$2 = require('readline');
8
8
  var require$$2 = require('xtreamer');
9
9
  var require$$3$1 = require('xml2js');
@@ -11,7 +11,7 @@ var require$$4 = require('JSONStream');
11
11
  var require$$5 = require('stream');
12
12
  var require$$6 = require('csv-parser');
13
13
  var require$$0$3 = require('quickjs-emscripten');
14
- var require$$10 = require('https');
14
+ var require$$11 = require('https');
15
15
  var require$$0$5 = require('@modelcontextprotocol/sdk/client/index.js');
16
16
  var require$$1$3 = require('@modelcontextprotocol/sdk/client/stdio.js');
17
17
  var require$$0$4 = require('pkce-challenge');
@@ -25,16 +25,15 @@ var require$$1$4 = require('croner');
25
25
  var require$$2$3 = require('algoliasearch');
26
26
  var require$$3$3 = require('node:path');
27
27
  var require$$0$7 = require('openai');
28
- require('live-plugin-manager');
29
28
  var require$$0$a = require('@anthropic-ai/sdk');
30
29
  var require$$3$4 = require('crypto');
31
- var require$$8$2 = require('zod');
30
+ var require$$8$1 = require('zod');
32
31
  var require$$0$8 = require('http');
33
32
  var require$$1$5 = require('http2');
34
33
  var require$$2$4 = require('node-forge');
35
34
  var require$$0$9 = require('css');
36
35
  var require$$1$6 = require('node-vibrant/node');
37
- var require$$0$b = require('ws');
36
+ var require$$3$5 = require('ws');
38
37
 
39
38
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
40
39
 
@@ -1643,7 +1642,7 @@ var themeController_1 = themeController$5;
1643
1642
  */
1644
1643
 
1645
1644
  const path$j = require$$1$1;
1646
- const fs$e = require$$0$2;
1645
+ const fs$f = require$$0$2;
1647
1646
  const { app: app$c } = require$$0$1;
1648
1647
 
1649
1648
  const APP_NAME = "Dashboard";
@@ -1692,8 +1691,8 @@ function readDataDirectoryFromSettings() {
1692
1691
  APP_NAME,
1693
1692
  "settings.json",
1694
1693
  );
1695
- if (!fs$e.existsSync(settingsPath)) return undefined;
1696
- const raw = fs$e.readFileSync(settingsPath, "utf8");
1694
+ if (!fs$f.existsSync(settingsPath)) return undefined;
1695
+ const raw = fs$f.readFileSync(settingsPath, "utf8");
1697
1696
  const settings = JSON.parse(raw);
1698
1697
  const dir = settings && settings.dataDirectory;
1699
1698
  if (typeof dir === "string" && dir) return dir;
@@ -1726,10 +1725,10 @@ function safePath$3(requested, allowedRoots) {
1726
1725
  // parent chain can't trick us.
1727
1726
  let real = resolved;
1728
1727
  try {
1729
- real = fs$e.realpathSync(resolved);
1728
+ real = fs$f.realpathSync(resolved);
1730
1729
  } catch (_e) {
1731
1730
  try {
1732
- const parent = fs$e.realpathSync(path$j.dirname(resolved));
1731
+ const parent = fs$f.realpathSync(path$j.dirname(resolved));
1733
1732
  real = path$j.join(parent, path$j.basename(resolved));
1734
1733
  } catch (_e2) {
1735
1734
  // Parent doesn't exist either. Use the resolved-but-not-
@@ -1742,7 +1741,7 @@ function safePath$3(requested, allowedRoots) {
1742
1741
  for (const root of allowedRoots) {
1743
1742
  let realRoot = root;
1744
1743
  try {
1745
- if (fs$e.existsSync(root)) realRoot = fs$e.realpathSync(root);
1744
+ if (fs$f.existsSync(root)) realRoot = fs$f.realpathSync(root);
1746
1745
  } catch (_e) {
1747
1746
  // root doesn't exist or isn't reachable — keep as-is for
1748
1747
  // the comparison below
@@ -1810,7 +1809,7 @@ var safePath_1 = {
1810
1809
  * clearCache() → void // test-only
1811
1810
  */
1812
1811
 
1813
- const fs$d = require$$0$2;
1812
+ const fs$e = require$$0$2;
1814
1813
  const path$i = require$$1$1;
1815
1814
  const { app: app$b } = require$$0$1;
1816
1815
 
@@ -1826,9 +1825,9 @@ function grantsFilePath() {
1826
1825
 
1827
1826
  function loadFromDisk() {
1828
1827
  const p = grantsFilePath();
1829
- if (!fs$d.existsSync(p)) return {};
1828
+ if (!fs$e.existsSync(p)) return {};
1830
1829
  try {
1831
- const raw = fs$d.readFileSync(p, "utf8");
1830
+ const raw = fs$e.readFileSync(p, "utf8");
1832
1831
  const parsed = JSON.parse(raw);
1833
1832
  if (!parsed || typeof parsed !== "object") return {};
1834
1833
  return parsed;
@@ -1848,9 +1847,9 @@ function writeToDisk(data) {
1848
1847
  const tmp = p + ".tmp";
1849
1848
  // Ensure parent dir exists (userData should already, but be defensive
1850
1849
  // for first-launch / freshly-cleared profile cases).
1851
- fs$d.mkdirSync(path$i.dirname(p), { recursive: true });
1852
- fs$d.writeFileSync(tmp, JSON.stringify(data, null, 2), "utf8");
1853
- fs$d.renameSync(tmp, p);
1850
+ fs$e.mkdirSync(path$i.dirname(p), { recursive: true });
1851
+ fs$e.writeFileSync(tmp, JSON.stringify(data, null, 2), "utf8");
1852
+ fs$e.renameSync(tmp, p);
1854
1853
  }
1855
1854
 
1856
1855
  // Recognized origins for a persisted grant.
@@ -1935,6 +1934,12 @@ function sanitizePerms(perms) {
1935
1934
  ? raw.writePaths.filter((p) => typeof p === "string")
1936
1935
  : [],
1937
1936
  };
1937
+ } else if (name === "network") {
1938
+ domains.network = {
1939
+ hosts: Array.isArray(raw.hosts)
1940
+ ? raw.hosts.filter((h) => typeof h === "string")
1941
+ : [],
1942
+ };
1938
1943
  }
1939
1944
  // Future domains plug in here. Unknown domain names are dropped.
1940
1945
  }
@@ -1952,13 +1957,13 @@ function sanitizePerms(perms) {
1952
1957
  return out;
1953
1958
  }
1954
1959
 
1955
- function getGrant$3(widgetId) {
1960
+ function getGrant$4(widgetId) {
1956
1961
  if (typeof widgetId !== "string" || !widgetId) return null;
1957
1962
  const all = ensureCache();
1958
1963
  return all[widgetId] || null;
1959
1964
  }
1960
1965
 
1961
- function setGrant$3(widgetId, perms) {
1966
+ function setGrant$4(widgetId, perms) {
1962
1967
  if (typeof widgetId !== "string" || !widgetId) return false;
1963
1968
  const sanitized = sanitizePerms(perms);
1964
1969
  if (!sanitized) return false;
@@ -2039,8 +2044,8 @@ function clearCache$1() {
2039
2044
  }
2040
2045
 
2041
2046
  var grantedPermissions = {
2042
- getGrant: getGrant$3,
2043
- setGrant: setGrant$3,
2047
+ getGrant: getGrant$4,
2048
+ setGrant: setGrant$4,
2044
2049
  revokeGrant: revokeGrant$1,
2045
2050
  revokeServer: revokeServer$1,
2046
2051
  listAllGrants: listAllGrants$1,
@@ -2159,7 +2164,7 @@ function validateRequest(req) {
2159
2164
  *
2160
2165
  * `scope` informs the caller how to write the resulting grant.
2161
2166
  */
2162
- function requestApproval$2(req, opts = {}) {
2167
+ function requestApproval$3(req, opts = {}) {
2163
2168
  const validation = validateRequest(req);
2164
2169
  if (validation) {
2165
2170
  return Promise.reject(new Error(validation));
@@ -2251,7 +2256,7 @@ function setupJitConsentHandlers() {
2251
2256
  }
2252
2257
 
2253
2258
  var jitConsent$1 = {
2254
- requestApproval: requestApproval$2,
2259
+ requestApproval: requestApproval$3,
2255
2260
  setupJitConsentHandlers,
2256
2261
  _handleResponse,
2257
2262
  _resetForTest,
@@ -2295,8 +2300,8 @@ var jitConsent$1 = {
2295
2300
  * read-only entry) stay synchronous.
2296
2301
  */
2297
2302
 
2298
- const { getGrant: getGrant$2, setGrant: setGrant$2 } = grantedPermissions;
2299
- const { requestApproval: requestApproval$1 } = jitConsent$1;
2303
+ const { getGrant: getGrant$3, setGrant: setGrant$3 } = grantedPermissions;
2304
+ const { requestApproval: requestApproval$2 } = jitConsent$1;
2300
2305
 
2301
2306
  // Action names treated as writes. Anything not in this set is a read.
2302
2307
  // Conservative — when in doubt, classify as a read so write-protected
@@ -2315,7 +2320,7 @@ function isFsWriteAction(action) {
2315
2320
  return WRITE_ACTIONS.has(action);
2316
2321
  }
2317
2322
 
2318
- function _isNoGrantDenial$1(reason) {
2323
+ function _isNoGrantDenial$2(reason) {
2319
2324
  return (
2320
2325
  typeof reason === "string" && /no fs permissions granted/i.test(reason)
2321
2326
  );
@@ -2352,7 +2357,7 @@ function gateFsCall$1({ widgetId, action, args }) {
2352
2357
  };
2353
2358
  }
2354
2359
 
2355
- const grant = getGrant$2(widgetId);
2360
+ const grant = getGrant$3(widgetId);
2356
2361
  const fsPerms = grant && grant.domains && grant.domains.fs;
2357
2362
  if (!fsPerms) {
2358
2363
  return {
@@ -2453,11 +2458,11 @@ async function gateFsCallWithJit$1(req, opts = {}) {
2453
2458
  const initial = gateFsCall$1(req);
2454
2459
  if (initial.allow) return initial;
2455
2460
  if (!opts.enableJit) return initial;
2456
- if (!_isNoGrantDenial$1(initial.reason)) return initial;
2461
+ if (!_isNoGrantDenial$2(initial.reason)) return initial;
2457
2462
 
2458
2463
  let decision;
2459
2464
  try {
2460
- decision = await requestApproval$1(
2465
+ decision = await requestApproval$2(
2461
2466
  {
2462
2467
  widgetId: req.widgetId,
2463
2468
  domain: "fs",
@@ -2506,9 +2511,9 @@ async function gateFsCallWithJit$1(req, opts = {}) {
2506
2511
  addition.grantOrigin = "live";
2507
2512
 
2508
2513
  try {
2509
- const current = getGrant$2(req.widgetId);
2514
+ const current = getGrant$3(req.widgetId);
2510
2515
  const merged = _mergeFsGrant(current, addition);
2511
- setGrant$2(req.widgetId, merged);
2516
+ setGrant$3(req.widgetId, merged);
2512
2517
  } catch (e) {
2513
2518
  return {
2514
2519
  allow: false,
@@ -2528,6 +2533,232 @@ var fsGate = {
2528
2533
  WRITE_ACTIONS,
2529
2534
  };
2530
2535
 
2536
+ /**
2537
+ * networkGate.js
2538
+ *
2539
+ * Per-widget gate for outbound-network IPC actions (Phase 3 of JIT
2540
+ * consent). Same shape as `fsGate.js` but for hostname-based scoping.
2541
+ *
2542
+ * Channels currently gated by this:
2543
+ * - readDataFromURL (dataController) — fetch a URL into a file
2544
+ * - wsConnect (webSocketController) — open a WebSocket
2545
+ *
2546
+ * Channels NOT gated:
2547
+ * - WS_SEND/DISCONNECT/STATUS/GET_ALL — operate on already-authorized
2548
+ * connections, intentionally shared across widgets via the
2549
+ * `consumers: Set<webContentsId>` design.
2550
+ * - THEME_EXTRACT_FROM_URL — admin-only callers (Settings panels);
2551
+ * no widget caller exists in the codebase.
2552
+ *
2553
+ * Grant shape (under `grant.domains.network`):
2554
+ * {
2555
+ * hosts: ["api.example.com", "*", ...]
2556
+ * }
2557
+ *
2558
+ * Hostname matching:
2559
+ * - Exact match (case-insensitive)
2560
+ * - "*" wildcard in the grant matches any host (escape hatch;
2561
+ * surfaced in the JIT modal as "no host scope — risky")
2562
+ * - Subdomain wildcards ("*.example.com") are NOT supported in this
2563
+ * slice — deferred to a follow-up.
2564
+ *
2565
+ * URL parsing uses the WHATWG URL constructor. Malformed URLs deny
2566
+ * synchronously and do NOT escalate to JIT (a JIT prompt would let a
2567
+ * widget probe URL parser quirks, which we'd rather not).
2568
+ *
2569
+ * JIT escalation: when the runtime calls `gateNetworkCallWithJit` and
2570
+ * the gate denies for "no network permissions granted", a
2571
+ * permission-required IPC fires and the user's response is merged
2572
+ * into the persisted grant. Other denial reasons (host not in
2573
+ * allowlist, malformed url, missing url) stay synchronous.
2574
+ */
2575
+
2576
+ const { getGrant: getGrant$2, setGrant: setGrant$2 } = grantedPermissions;
2577
+ const { requestApproval: requestApproval$1 } = jitConsent$1;
2578
+
2579
+ function _isNoGrantDenial$1(reason) {
2580
+ return (
2581
+ typeof reason === "string" && /no network permissions granted/i.test(reason)
2582
+ );
2583
+ }
2584
+
2585
+ function _hostMatches(host, allowedList) {
2586
+ if (!Array.isArray(allowedList) || allowedList.length === 0) return false;
2587
+ if (allowedList.includes("*")) return true;
2588
+ const lower = host.toLowerCase();
2589
+ return allowedList.some(
2590
+ (h) => typeof h === "string" && h.toLowerCase() === lower,
2591
+ );
2592
+ }
2593
+
2594
+ function _parseHost(url) {
2595
+ try {
2596
+ return new URL(url).hostname;
2597
+ } catch {
2598
+ return null;
2599
+ }
2600
+ }
2601
+
2602
+ /**
2603
+ * Synchronous gate evaluation.
2604
+ * @returns {{ allow: true } | { allow: false, reason: string }}
2605
+ */
2606
+ function gateNetworkCall$2({ widgetId, action, args }) {
2607
+ if (!widgetId) {
2608
+ return {
2609
+ allow: false,
2610
+ reason: "no widgetId supplied; cannot determine network permissions",
2611
+ };
2612
+ }
2613
+
2614
+ const url = args && typeof args === "object" ? args.url : null;
2615
+ if (typeof url !== "string" || !url) {
2616
+ return {
2617
+ allow: false,
2618
+ reason:
2619
+ "network gate: action '" +
2620
+ action +
2621
+ "' requires args.url (got: " +
2622
+ JSON.stringify(url) +
2623
+ ")",
2624
+ };
2625
+ }
2626
+
2627
+ const host = _parseHost(url);
2628
+ if (!host) {
2629
+ return {
2630
+ allow: false,
2631
+ reason: "network gate: malformed url '" + url + "'",
2632
+ };
2633
+ }
2634
+
2635
+ const grant = getGrant$2(widgetId);
2636
+ const netPerms = grant && grant.domains && grant.domains.network;
2637
+ if (!netPerms) {
2638
+ return {
2639
+ allow: false,
2640
+ reason:
2641
+ "widget '" +
2642
+ widgetId +
2643
+ "' has no network permissions granted; user must approve at runtime or in Settings → Privacy & Security",
2644
+ };
2645
+ }
2646
+
2647
+ if (_hostMatches(host, netPerms.hosts)) {
2648
+ return { allow: true };
2649
+ }
2650
+ return {
2651
+ allow: false,
2652
+ reason:
2653
+ "network gate: host '" +
2654
+ host +
2655
+ "' rejected — not in allowed hosts for widget '" +
2656
+ widgetId +
2657
+ "'",
2658
+ };
2659
+ }
2660
+
2661
+ /**
2662
+ * Merge an approved JIT decision's grant into the widget's existing
2663
+ * grant under domains.network. Mirrors fsGate._mergeFsGrant.
2664
+ */
2665
+ function _mergeNetworkGrant(current, addition) {
2666
+ const out = {
2667
+ grantOrigin: addition.grantOrigin || current?.grantOrigin || null,
2668
+ servers: { ...(current?.servers || {}) },
2669
+ domains: { ...(current?.domains || {}) },
2670
+ };
2671
+ const additionNet = addition?.domains?.network;
2672
+ if (additionNet) {
2673
+ const existingNet = out.domains.network || { hosts: [] };
2674
+ out.domains.network = {
2675
+ hosts: [
2676
+ ...new Set([
2677
+ ...(existingNet.hosts || []),
2678
+ ...(Array.isArray(additionNet.hosts) ? additionNet.hosts : []),
2679
+ ]),
2680
+ ],
2681
+ };
2682
+ }
2683
+ return out;
2684
+ }
2685
+
2686
+ /**
2687
+ * Async gate that escalates "no network grant" denials to a JIT
2688
+ * consent prompt when `opts.enableJit` is true. On approval, merges
2689
+ * the decision's grant blob into the persisted grant and re-evaluates.
2690
+ */
2691
+ async function gateNetworkCallWithJit$2(req, opts = {}) {
2692
+ const initial = gateNetworkCall$2(req);
2693
+ if (initial.allow) return initial;
2694
+ if (!opts.enableJit) return initial;
2695
+ if (!_isNoGrantDenial$1(initial.reason)) return initial;
2696
+
2697
+ let decision;
2698
+ try {
2699
+ decision = await requestApproval$1(
2700
+ {
2701
+ widgetId: req.widgetId,
2702
+ domain: "network",
2703
+ action: req.action,
2704
+ args: req.args || {},
2705
+ },
2706
+ { timeoutMs: opts.timeoutMs },
2707
+ );
2708
+ } catch (e) {
2709
+ return {
2710
+ allow: false,
2711
+ reason:
2712
+ "JIT consent " +
2713
+ (e && e.message ? e.message : "failed") +
2714
+ "; original denial: " +
2715
+ initial.reason,
2716
+ };
2717
+ }
2718
+
2719
+ if (!decision || decision.approve !== true) {
2720
+ return {
2721
+ allow: false,
2722
+ reason:
2723
+ "user declined JIT consent for widget '" +
2724
+ req.widgetId +
2725
+ "' calling network '" +
2726
+ req.action +
2727
+ "'",
2728
+ };
2729
+ }
2730
+
2731
+ const host = _parseHost(req.args?.url) || "*";
2732
+ const addition =
2733
+ decision.granted && typeof decision.granted === "object"
2734
+ ? decision.granted
2735
+ : {
2736
+ grantOrigin: "live",
2737
+ domains: { network: { hosts: [host] } },
2738
+ };
2739
+ addition.grantOrigin = "live";
2740
+
2741
+ try {
2742
+ const current = getGrant$2(req.widgetId);
2743
+ const merged = _mergeNetworkGrant(current, addition);
2744
+ setGrant$2(req.widgetId, merged);
2745
+ } catch (e) {
2746
+ return {
2747
+ allow: false,
2748
+ reason:
2749
+ "JIT consent: failed to persist network grant: " +
2750
+ (e && e.message ? e.message : String(e)),
2751
+ };
2752
+ }
2753
+
2754
+ return gateNetworkCall$2(req);
2755
+ }
2756
+
2757
+ var networkGate = {
2758
+ gateNetworkCall: gateNetworkCall$2,
2759
+ gateNetworkCallWithJit: gateNetworkCallWithJit$2,
2760
+ };
2761
+
2531
2762
  /**
2532
2763
  * securityFlags.js
2533
2764
  *
@@ -2549,15 +2780,15 @@ var fsGate = {
2549
2780
  * settings.json IO.
2550
2781
  */
2551
2782
 
2552
- function readEnforceFlag$2(settings) {
2783
+ function readEnforceFlag$3(settings) {
2553
2784
  return settings?.security?.enforceWidgetMcpPermissions !== false;
2554
2785
  }
2555
2786
 
2556
- function readJitFlag$2(settings) {
2787
+ function readJitFlag$3(settings) {
2557
2788
  return settings?.security?.enableJitConsent !== false;
2558
2789
  }
2559
2790
 
2560
- var securityFlags = { readEnforceFlag: readEnforceFlag$2, readJitFlag: readJitFlag$2 };
2791
+ var securityFlags = { readEnforceFlag: readEnforceFlag$3, readJitFlag: readJitFlag$3 };
2561
2792
 
2562
2793
  /**
2563
2794
  * safeJsExecutor.js
@@ -3259,27 +3490,31 @@ function requireTransform () {
3259
3490
  }
3260
3491
 
3261
3492
  const { app: app$a } = require$$0$1;
3262
- var fs$c = require$$0$2;
3493
+ var fs$d = require$$0$2;
3263
3494
  const path$h = require$$1$1;
3264
3495
  const events$5 = events$8;
3265
3496
  const { getFileContents: getFileContents$5, writeToFile: writeToFile$2 } = file;
3266
3497
  const { safePath: safePath$2, getAllowedRoots: getAllowedRoots$1 } = safePath_1;
3267
3498
  const { gateFsCall, gateFsCallWithJit } = fsGate;
3268
- const { readEnforceFlag: readEnforceFlag$1, readJitFlag: readJitFlag$1 } = securityFlags;
3499
+ const {
3500
+ gateNetworkCall: gateNetworkCall$1,
3501
+ gateNetworkCallWithJit: gateNetworkCallWithJit$1,
3502
+ } = networkGate;
3503
+ const { readEnforceFlag: readEnforceFlag$2, readJitFlag: readJitFlag$2 } = securityFlags;
3269
3504
 
3270
3505
  // Reads the enforcement + JIT flags from settings.json. Mirrors the
3271
3506
  // helper in mcpController. The flag is shared across MCP and fs domains
3272
3507
  // — see Phase 2 plan for rationale (the cosmetic rename to a
3273
3508
  // domain-neutral name is a separate slice).
3274
- function _loadFlags() {
3509
+ function _loadFlags$1() {
3275
3510
  try {
3276
3511
  const settingsPath = path$h.join(
3277
3512
  app$a.getPath("userData"),
3278
3513
  appName$5,
3279
3514
  "settings.json",
3280
3515
  );
3281
- if (!fs$c.existsSync(settingsPath)) return null;
3282
- return JSON.parse(fs$c.readFileSync(settingsPath, "utf8"));
3516
+ if (!fs$d.existsSync(settingsPath)) return null;
3517
+ return JSON.parse(fs$d.readFileSync(settingsPath, "utf8"));
3283
3518
  } catch (_e) {
3284
3519
  return null;
3285
3520
  }
@@ -3293,10 +3528,10 @@ function _loadFlags() {
3293
3528
  * @returns {Promise<boolean>}
3294
3529
  */
3295
3530
  async function _runFsGate(win, action, widgetId, args, errorEvent) {
3296
- const settings = _loadFlags();
3297
- if (!readEnforceFlag$1(settings)) return true; // gate disabled
3531
+ const settings = _loadFlags$1();
3532
+ if (!readEnforceFlag$2(settings)) return true; // gate disabled
3298
3533
  if (!widgetId) return true; // legacy callers without widgetId — see plan
3299
- const gate = readJitFlag$1(settings)
3534
+ const gate = readJitFlag$2(settings)
3300
3535
  ? await gateFsCallWithJit({ widgetId, action, args }, { enableJit: true })
3301
3536
  : gateFsCall({ widgetId, action, args });
3302
3537
  if (gate.allow) return true;
@@ -3309,10 +3544,34 @@ async function _runFsGate(win, action, widgetId, args, errorEvent) {
3309
3544
  return false;
3310
3545
  }
3311
3546
 
3547
+ /**
3548
+ * Phase 3 network gate. Same shape as _runFsGate but for outbound
3549
+ * URLs. Mirrors fs's "disabled / no widgetId / sync vs async" branching.
3550
+ */
3551
+ async function _runNetworkGate$1(win, action, widgetId, args, errorEvent) {
3552
+ const settings = _loadFlags$1();
3553
+ if (!readEnforceFlag$2(settings)) return true;
3554
+ if (!widgetId) return true;
3555
+ const gate = readJitFlag$2(settings)
3556
+ ? await gateNetworkCallWithJit$1(
3557
+ { widgetId, action, args },
3558
+ { enableJit: true },
3559
+ )
3560
+ : gateNetworkCall$1({ widgetId, action, args });
3561
+ if (gate.allow) return true;
3562
+ if (win && errorEvent) {
3563
+ win.webContents.send(errorEvent, {
3564
+ success: false,
3565
+ message: "network permission gate: " + gate.reason,
3566
+ });
3567
+ }
3568
+ return false;
3569
+ }
3570
+
3312
3571
  // Convert Json to Csv
3313
- const ObjectsToCsv = require$$8$1;
3572
+ const ObjectsToCsv = require$$9$1;
3314
3573
  const Transform = requireTransform();
3315
- const https$3 = require$$10;
3574
+ const https$3 = require$$11;
3316
3575
  const appName$5 = "Dashboard";
3317
3576
 
3318
3577
  const dataController$1 = {
@@ -3468,7 +3727,18 @@ const dataController$1 = {
3468
3727
  }
3469
3728
  },
3470
3729
 
3471
- readDataFromURL: (win, url, toFilepath) => {
3730
+ readDataFromURL: async (win, url, toFilepath, widgetId = null) => {
3731
+ // Phase 3 network gate. Runs before HTTPS-protocol + safePath
3732
+ // checks so JIT can prompt the user without leaking URL parser
3733
+ // edge cases through error timing.
3734
+ const gateOk = await _runNetworkGate$1(
3735
+ win,
3736
+ "readDataFromURL",
3737
+ widgetId,
3738
+ { url },
3739
+ events$5.READ_DATA_URL_ERROR,
3740
+ );
3741
+ if (!gateOk) return;
3472
3742
  try {
3473
3743
  // Validate URL is https protocol only
3474
3744
  let parsedUrl;
@@ -3488,7 +3758,7 @@ const dataController$1 = {
3488
3758
  // intent, plus realpath/symlink protection.
3489
3759
  const resolvedFilepath = safePath$2(toFilepath, getAllowedRoots$1("data"));
3490
3760
 
3491
- const writeStream = fs$c.createWriteStream(resolvedFilepath);
3761
+ const writeStream = fs$d.createWriteStream(resolvedFilepath);
3492
3762
 
3493
3763
  https$3
3494
3764
  .get(url, (resp) => {
@@ -3855,7 +4125,7 @@ var dataController_1 = dataController$1;
3855
4125
 
3856
4126
  const { app: app$9 } = require$$0$1;
3857
4127
  const path$g = require$$1$1;
3858
- const fs$b = require$$0$2;
4128
+ const fs$c = require$$0$2;
3859
4129
  const { getFileContents: getFileContents$4, writeToFile: writeToFile$1 } = file;
3860
4130
 
3861
4131
  const configFilename$3 = "settings.json";
@@ -3863,15 +4133,15 @@ const appName$4 = "Dashboard";
3863
4133
 
3864
4134
  // Helper function to recursively copy directory
3865
4135
  function copyDirectory(source, destination) {
3866
- if (!fs$b.existsSync(destination)) {
3867
- fs$b.mkdirSync(destination, { recursive: true });
4136
+ if (!fs$c.existsSync(destination)) {
4137
+ fs$c.mkdirSync(destination, { recursive: true });
3868
4138
  }
3869
4139
 
3870
- const files = fs$b.readdirSync(source);
4140
+ const files = fs$c.readdirSync(source);
3871
4141
  for (const file of files) {
3872
4142
  const srcPath = path$g.join(source, file);
3873
4143
  const destPath = path$g.join(destination, file);
3874
- const stat = fs$b.lstatSync(srcPath);
4144
+ const stat = fs$c.lstatSync(srcPath);
3875
4145
 
3876
4146
  // Skip symlinks to prevent following links to sensitive files
3877
4147
  if (stat.isSymbolicLink()) {
@@ -3882,7 +4152,7 @@ function copyDirectory(source, destination) {
3882
4152
  if (stat.isDirectory()) {
3883
4153
  copyDirectory(srcPath, destPath);
3884
4154
  } else {
3885
- fs$b.copyFileSync(srcPath, destPath);
4155
+ fs$c.copyFileSync(srcPath, destPath);
3886
4156
  }
3887
4157
  }
3888
4158
  }
@@ -4000,11 +4270,11 @@ const settingsController$4 = {
4000
4270
  setDataDirectory: (win, newPath) => {
4001
4271
  try {
4002
4272
  // Validate the path exists and is a directory
4003
- if (!fs$b.existsSync(newPath)) {
4004
- fs$b.mkdirSync(newPath, { recursive: true });
4273
+ if (!fs$c.existsSync(newPath)) {
4274
+ fs$c.mkdirSync(newPath, { recursive: true });
4005
4275
  }
4006
4276
 
4007
- const stats = fs$b.statSync(newPath);
4277
+ const stats = fs$c.statSync(newPath);
4008
4278
  if (!stats.isDirectory()) {
4009
4279
  throw new Error("Path is not a directory");
4010
4280
  }
@@ -4081,12 +4351,12 @@ const settingsController$4 = {
4081
4351
  }
4082
4352
 
4083
4353
  // Validate paths
4084
- if (!fs$b.existsSync(resolvedOldPath)) {
4354
+ if (!fs$c.existsSync(resolvedOldPath)) {
4085
4355
  throw new Error("Source directory does not exist");
4086
4356
  }
4087
4357
 
4088
- if (!fs$b.existsSync(resolvedNewPath)) {
4089
- fs$b.mkdirSync(resolvedNewPath, { recursive: true });
4358
+ if (!fs$c.existsSync(resolvedNewPath)) {
4359
+ fs$c.mkdirSync(resolvedNewPath, { recursive: true });
4090
4360
  }
4091
4361
 
4092
4362
  // Copy files
@@ -22440,13 +22710,13 @@ const {
22440
22710
  StreamableHTTPClientTransport,
22441
22711
  } = streamableHttp$1;
22442
22712
  const path$e = require$$1$1;
22443
- const fs$a = require$$0$2;
22713
+ const fs$b = require$$0$2;
22444
22714
  const os$2 = require$$2$1;
22445
22715
  const responseCache$2 = responseCache_1;
22446
22716
  const { gateToolCall, gateToolCallWithJit } = permissionGate;
22447
22717
  const { serverKey, parseServerKey } = mcpServerKey;
22448
22718
  const { applyPathScopeToCredentials } = mcpScopeResolver;
22449
- const { readEnforceFlag, readJitFlag } = securityFlags;
22719
+ const { readEnforceFlag: readEnforceFlag$1, readJitFlag: readJitFlag$1 } = securityFlags;
22450
22720
  const { app: app$7 } = require$$0$1;
22451
22721
 
22452
22722
  /**
@@ -22461,8 +22731,8 @@ function loadSettingsForFlags() {
22461
22731
  "Dashboard",
22462
22732
  "settings.json",
22463
22733
  );
22464
- if (!fs$a.existsSync(settingsPath)) return null;
22465
- const raw = fs$a.readFileSync(settingsPath, "utf8");
22734
+ if (!fs$b.existsSync(settingsPath)) return null;
22735
+ const raw = fs$b.readFileSync(settingsPath, "utf8");
22466
22736
  return JSON.parse(raw);
22467
22737
  } catch (_e) {
22468
22738
  return null;
@@ -22475,13 +22745,13 @@ function loadSettingsForFlags() {
22475
22745
  // confirm-on-disable dialog. See electron/utils/securityFlags.js for
22476
22746
  // the pinned default semantics.
22477
22747
  function isWidgetPermissionEnforcementEnabled() {
22478
- return readEnforceFlag(loadSettingsForFlags());
22748
+ return readEnforceFlag$1(loadSettingsForFlags());
22479
22749
  }
22480
22750
 
22481
22751
  // JIT consent flag. **Default ON.** Same semantics as the enforcement
22482
22752
  // flag — explicit false to opt out, otherwise on.
22483
22753
  function isJitConsentEnabled() {
22484
- return readJitFlag(loadSettingsForFlags());
22754
+ return readJitFlag$1(loadSettingsForFlags());
22485
22755
  }
22486
22756
 
22487
22757
  /**
@@ -22629,7 +22899,7 @@ function getShellPath$1() {
22629
22899
  fallbackDirs.push(`${home}/.nodenv/shims`);
22630
22900
  try {
22631
22901
  const nvmDir = `${home}/.nvm/versions/node`;
22632
- const versions = fs$a.readdirSync(nvmDir).sort();
22902
+ const versions = fs$b.readdirSync(nvmDir).sort();
22633
22903
  if (versions.length > 0) {
22634
22904
  // Find the highest compatible version (v18/v20/v22)
22635
22905
  for (let i = versions.length - 1; i >= 0; i--) {
@@ -22765,15 +23035,15 @@ async function refreshGoogleOAuthToken(tokenRefresh) {
22765
23035
  const credPath = tokenRefresh.credentialsPath.replace(/^~/, home);
22766
23036
  const keysPath = tokenRefresh.oauthKeysPath.replace(/^~/, home);
22767
23037
 
22768
- if (!fs$a.existsSync(credPath) || !fs$a.existsSync(keysPath)) {
23038
+ if (!fs$b.existsSync(credPath) || !fs$b.existsSync(keysPath)) {
22769
23039
  console.log(
22770
23040
  "[mcpController] Token refresh skipped: credential files not found",
22771
23041
  );
22772
23042
  return;
22773
23043
  }
22774
23044
 
22775
- const credentials = JSON.parse(fs$a.readFileSync(credPath, "utf8"));
22776
- const keysFile = JSON.parse(fs$a.readFileSync(keysPath, "utf8"));
23045
+ const credentials = JSON.parse(fs$b.readFileSync(credPath, "utf8"));
23046
+ const keysFile = JSON.parse(fs$b.readFileSync(keysPath, "utf8"));
22777
23047
  const keyData = keysFile.installed || keysFile.web;
22778
23048
 
22779
23049
  if (
@@ -22798,7 +23068,7 @@ async function refreshGoogleOAuthToken(tokenRefresh) {
22798
23068
 
22799
23069
  console.log("[mcpController] Refreshing Google OAuth token...");
22800
23070
 
22801
- const https = require$$10;
23071
+ const https = require$$11;
22802
23072
  const postData = [
22803
23073
  `client_id=${encodeURIComponent(keyData.client_id)}`,
22804
23074
  `client_secret=${encodeURIComponent(keyData.client_secret)}`,
@@ -22842,7 +23112,7 @@ async function refreshGoogleOAuthToken(tokenRefresh) {
22842
23112
  credentials.refresh_token = body.refresh_token;
22843
23113
  }
22844
23114
 
22845
- fs$a.writeFileSync(credPath, JSON.stringify(credentials, null, 2));
23115
+ fs$b.writeFileSync(credPath, JSON.stringify(credentials, null, 2));
22846
23116
  console.log("[mcpController] Google OAuth token refreshed successfully");
22847
23117
  }
22848
23118
 
@@ -23487,13 +23757,13 @@ const mcpController$3 = {
23487
23757
  "mcpServerCatalog.json",
23488
23758
  );
23489
23759
 
23490
- if (!fs$a.existsSync(catalogPath)) {
23760
+ if (!fs$b.existsSync(catalogPath)) {
23491
23761
  return {
23492
23762
  catalog: [],
23493
23763
  };
23494
23764
  }
23495
23765
 
23496
- const catalogData = fs$a.readFileSync(catalogPath, "utf8");
23766
+ const catalogData = fs$b.readFileSync(catalogPath, "utf8");
23497
23767
  const catalog = JSON.parse(catalogData);
23498
23768
 
23499
23769
  return {
@@ -23528,11 +23798,11 @@ const mcpController$3 = {
23528
23798
  "knownExternalMcpServers.json",
23529
23799
  );
23530
23800
 
23531
- if (!fs$a.existsSync(catalogPath)) {
23801
+ if (!fs$b.existsSync(catalogPath)) {
23532
23802
  return { success: true, servers: [] };
23533
23803
  }
23534
23804
 
23535
- const catalogData = fs$a.readFileSync(catalogPath, "utf8");
23805
+ const catalogData = fs$b.readFileSync(catalogPath, "utf8");
23536
23806
  const catalog = JSON.parse(catalogData);
23537
23807
 
23538
23808
  return {
@@ -23597,8 +23867,8 @@ const mcpController$3 = {
23597
23867
  const destPath = to.replace(/^~/, os$2.homedir());
23598
23868
  const destDir = require$$1$1.dirname(destPath);
23599
23869
  try {
23600
- fs$a.mkdirSync(destDir, { recursive: true });
23601
- fs$a.copyFileSync(sourcePath, destPath);
23870
+ fs$b.mkdirSync(destDir, { recursive: true });
23871
+ fs$b.copyFileSync(sourcePath, destPath);
23602
23872
  } catch (err) {
23603
23873
  return {
23604
23874
  error: true,
@@ -24182,7 +24452,7 @@ function commonjsRequire(path) {
24182
24452
  * Runs in the Electron main process at widget install time.
24183
24453
  */
24184
24454
 
24185
- const fs$9 = require$$0$2;
24455
+ const fs$a = require$$0$2;
24186
24456
  const path$d = require$$1$1;
24187
24457
 
24188
24458
  /**
@@ -24236,7 +24506,7 @@ function getEsbuildDiagnostics() {
24236
24506
  ? path$d.join(archDir, "esbuild.exe")
24237
24507
  : path$d.join(archDir, "bin", "esbuild");
24238
24508
  diagnostics.nativeBinaryPath = candidate;
24239
- diagnostics.nativeBinaryExists = fs$9.existsSync(candidate);
24509
+ diagnostics.nativeBinaryExists = fs$a.existsSync(candidate);
24240
24510
  } catch (err) {
24241
24511
  diagnostics.archResolveError = err.message;
24242
24512
  }
@@ -24283,25 +24553,25 @@ async function healthCheck() {
24283
24553
  */
24284
24554
  function findWidgetsDir$2(widgetPath) {
24285
24555
  const direct = path$d.join(widgetPath, "widgets");
24286
- if (fs$9.existsSync(direct)) {
24556
+ if (fs$a.existsSync(direct)) {
24287
24557
  return direct;
24288
24558
  }
24289
24559
 
24290
24560
  // Check configs/widgets/ (packageZip.js nests .dash.js files here)
24291
24561
  const configsWidgets = path$d.join(widgetPath, "configs", "widgets");
24292
- if (fs$9.existsSync(configsWidgets)) {
24562
+ if (fs$a.existsSync(configsWidgets)) {
24293
24563
  return configsWidgets;
24294
24564
  }
24295
24565
 
24296
24566
  // Check configs/ directory (used by packageZip.js for distributed widgets)
24297
24567
  const configs = path$d.join(widgetPath, "configs");
24298
- if (fs$9.existsSync(configs)) {
24568
+ if (fs$a.existsSync(configs)) {
24299
24569
  return configs;
24300
24570
  }
24301
24571
 
24302
24572
  // Check one level deeper for nested ZIP extraction
24303
24573
  try {
24304
- const entries = fs$9.readdirSync(widgetPath, { withFileTypes: true });
24574
+ const entries = fs$a.readdirSync(widgetPath, { withFileTypes: true });
24305
24575
  const subdirs = entries.filter(
24306
24576
  (e) =>
24307
24577
  e.isDirectory() &&
@@ -24312,7 +24582,7 @@ function findWidgetsDir$2(widgetPath) {
24312
24582
 
24313
24583
  for (const subdir of subdirs) {
24314
24584
  const nested = path$d.join(widgetPath, subdir.name, "widgets");
24315
- if (fs$9.existsSync(nested)) {
24585
+ if (fs$a.existsSync(nested)) {
24316
24586
  console.log(`[WidgetCompiler] Found nested widgets/ at ${nested}`);
24317
24587
  return nested;
24318
24588
  }
@@ -24346,7 +24616,7 @@ async function compileWidget$1(widgetPath) {
24346
24616
  }
24347
24617
 
24348
24618
  // Discover .dash.js config files
24349
- const files = fs$9.readdirSync(widgetsDir);
24619
+ const files = fs$a.readdirSync(widgetsDir);
24350
24620
  const dashFiles = files.filter((f) => f.endsWith(".dash.js"));
24351
24621
 
24352
24622
  if (dashFiles.length === 0) {
@@ -24368,7 +24638,7 @@ async function compileWidget$1(widgetPath) {
24368
24638
  const componentName = dashFile.replace(".dash.js", "");
24369
24639
  const componentFile = `${componentName}.js`;
24370
24640
  const componentFilePath = path$d.join(widgetsDir, componentFile);
24371
- const hasComponent = fs$9.existsSync(componentFilePath);
24641
+ const hasComponent = fs$a.existsSync(componentFilePath);
24372
24642
 
24373
24643
  // Import the config (always)
24374
24644
  imports.push(
@@ -24406,11 +24676,11 @@ async function compileWidget$1(widgetPath) {
24406
24676
 
24407
24677
  try {
24408
24678
  // Ensure dist/ directory exists
24409
- if (!fs$9.existsSync(distDir)) {
24410
- fs$9.mkdirSync(distDir, { recursive: true });
24679
+ if (!fs$a.existsSync(distDir)) {
24680
+ fs$a.mkdirSync(distDir, { recursive: true });
24411
24681
  }
24412
24682
 
24413
- fs$9.writeFileSync(entryPath, entryContent, "utf8");
24683
+ fs$a.writeFileSync(entryPath, entryContent, "utf8");
24414
24684
 
24415
24685
  console.log(
24416
24686
  `[WidgetCompiler] Compiling ${dashFiles.length} component(s) from ${widgetPath}`,
@@ -24466,8 +24736,8 @@ async function compileWidget$1(widgetPath) {
24466
24736
  } finally {
24467
24737
  // Clean up temporary entry file
24468
24738
  try {
24469
- if (fs$9.existsSync(entryPath)) {
24470
- fs$9.unlinkSync(entryPath);
24739
+ if (fs$a.existsSync(entryPath)) {
24740
+ fs$a.unlinkSync(entryPath);
24471
24741
  }
24472
24742
  } catch (cleanupError) {
24473
24743
  // Non-fatal
@@ -24499,7 +24769,7 @@ var widgetCompiler$1 = {
24499
24769
  * Integrates with ComponentManager for automatic registration
24500
24770
  */
24501
24771
 
24502
- const fs$8 = require$$0$2;
24772
+ const fs$9 = require$$0$2;
24503
24773
  const path$c = require$$1$1;
24504
24774
  const vm = require$$2$2;
24505
24775
  const { findWidgetsDir: findWidgetsDir$1 } = widgetCompiler$1;
@@ -24592,10 +24862,10 @@ class DynamicWidgetLoader {
24592
24862
  const componentPath = path$c.join(widgetsDir, `${componentName}.js`);
24593
24863
  const configPath = path$c.join(widgetsDir, `${componentName}.dash.js`);
24594
24864
 
24595
- if (!fs$8.existsSync(componentPath)) {
24865
+ if (!fs$9.existsSync(componentPath)) {
24596
24866
  throw new Error(`Component file not found: ${componentPath}`);
24597
24867
  }
24598
- if (!fs$8.existsSync(configPath)) {
24868
+ if (!fs$9.existsSync(configPath)) {
24599
24869
  throw new Error(`Config file not found: ${configPath}`);
24600
24870
  }
24601
24871
 
@@ -24646,7 +24916,7 @@ class DynamicWidgetLoader {
24646
24916
  */
24647
24917
  async loadConfigFile(configPath) {
24648
24918
  try {
24649
- const source = fs$8.readFileSync(configPath, "utf8");
24919
+ const source = fs$9.readFileSync(configPath, "utf8");
24650
24920
 
24651
24921
  let exportMatch = source.match(/export\s+default\s+({[\s\S]*});?\s*$/);
24652
24922
 
@@ -24714,7 +24984,7 @@ class DynamicWidgetLoader {
24714
24984
  return [];
24715
24985
  }
24716
24986
 
24717
- const files = fs$8.readdirSync(widgetsDir);
24987
+ const files = fs$9.readdirSync(widgetsDir);
24718
24988
  const widgets = new Set();
24719
24989
 
24720
24990
  files.forEach((file) => {
@@ -24790,7 +25060,7 @@ var dynamicWidgetLoaderExports = dynamicWidgetLoader$3.exports;
24790
25060
  * Test-only. Drops the in-process cache so tests can re-read.
24791
25061
  */
24792
25062
 
24793
- const fs$7 = require$$0$2;
25063
+ const fs$8 = require$$0$2;
24794
25064
  const path$b = require$$1$1;
24795
25065
  const os$1 = require$$2$1;
24796
25066
  const { app: app$6 } = require$$0$1;
@@ -24865,12 +25135,12 @@ function resolveWidgetPackagePath(widgetId) {
24865
25135
  function getWidgetMcpPermissions$1(widgetId) {
24866
25136
  if (_cache.has(widgetId)) return _cache.get(widgetId);
24867
25137
  const pkgPath = resolveWidgetPackagePath(widgetId);
24868
- if (!pkgPath || !fs$7.existsSync(pkgPath)) {
25138
+ if (!pkgPath || !fs$8.existsSync(pkgPath)) {
24869
25139
  _cache.set(widgetId, null);
24870
25140
  return null;
24871
25141
  }
24872
25142
  try {
24873
- const raw = fs$7.readFileSync(pkgPath, "utf8");
25143
+ const raw = fs$8.readFileSync(pkgPath, "utf8");
24874
25144
  const pkg = JSON.parse(raw);
24875
25145
  const perms = parseManifestPermissions(pkg);
24876
25146
  _cache.set(widgetId, perms);
@@ -24919,7 +25189,7 @@ var widgetPermissions = {
24919
25189
  * (Slices 1-3) is the actual boundary.
24920
25190
  */
24921
25191
 
24922
- const fs$6 = require$$0$2;
25192
+ const fs$7 = require$$0$2;
24923
25193
  const path$a = require$$1$1;
24924
25194
 
24925
25195
  const SOURCE_EXTENSIONS = new Set([
@@ -24973,7 +25243,7 @@ function readSourceFiles(dir) {
24973
25243
  function walk(current, relBase) {
24974
25244
  let entries;
24975
25245
  try {
24976
- entries = fs$6.readdirSync(current, { withFileTypes: true });
25246
+ entries = fs$7.readdirSync(current, { withFileTypes: true });
24977
25247
  } catch {
24978
25248
  return;
24979
25249
  }
@@ -24990,7 +25260,7 @@ function readSourceFiles(dir) {
24990
25260
  try {
24991
25261
  result.push({
24992
25262
  relPath: rel,
24993
- source: fs$6.readFileSync(abs, "utf8"),
25263
+ source: fs$7.readFileSync(abs, "utf8"),
24994
25264
  });
24995
25265
  } catch {
24996
25266
  // unreadable — skip
@@ -27147,7 +27417,7 @@ var widgetRegistryExports = widgetRegistry$1.exports;
27147
27417
  */
27148
27418
 
27149
27419
  const path$9 = require$$1$1;
27150
- const fs$5 = require$$0$2;
27420
+ const fs$6 = require$$0$2;
27151
27421
  const os = require$$2$1;
27152
27422
  const { toPackageId } = packageId;
27153
27423
  const { getStoredToken: getStoredToken$3 } = registryAuthController$2;
@@ -27223,12 +27493,12 @@ async function fetchRegistryIndex(forceRefresh = false) {
27223
27493
  if (isDev()) {
27224
27494
  // In dev mode, try local test file first
27225
27495
  const testPath = getTestRegistryPath();
27226
- if (fs$5.existsSync(testPath)) {
27496
+ if (fs$6.existsSync(testPath)) {
27227
27497
  console.log(
27228
27498
  "[RegistryController] Loading test registry from:",
27229
27499
  testPath,
27230
27500
  );
27231
- const raw = fs$5.readFileSync(testPath, "utf8");
27501
+ const raw = fs$6.readFileSync(testPath, "utf8");
27232
27502
  indexData = JSON.parse(raw);
27233
27503
  } else {
27234
27504
  // Fall back to API (supports DASH_REGISTRY_URL as full-URL override)
@@ -27655,8 +27925,8 @@ async function fetchPackageSource(packageName, componentName = null) {
27655
27925
  let configCode = "";
27656
27926
  let widgetName = null;
27657
27927
 
27658
- if (fs$5.existsSync(widgetsDir)) {
27659
- const files = fs$5.readdirSync(widgetsDir);
27928
+ if (fs$6.existsSync(widgetsDir)) {
27929
+ const files = fs$6.readdirSync(widgetsDir);
27660
27930
  const dashFiles = files.filter((f) => f.endsWith(".dash.js"));
27661
27931
  const componentFiles = files.filter(
27662
27932
  (f) => f.endsWith(".js") && !f.endsWith(".dash.js") && f !== "index.js",
@@ -27678,7 +27948,7 @@ async function fetchPackageSource(packageName, componentName = null) {
27678
27948
  if (!configFile) configFile = dashFiles[0];
27679
27949
 
27680
27950
  if (configFile) {
27681
- configCode = fs$5.readFileSync(path$9.join(widgetsDir, configFile), "utf8");
27951
+ configCode = fs$6.readFileSync(path$9.join(widgetsDir, configFile), "utf8");
27682
27952
  widgetName = configFile.replace(/\.dash\.js$/, "");
27683
27953
  }
27684
27954
 
@@ -27692,7 +27962,7 @@ async function fetchPackageSource(packageName, componentName = null) {
27692
27962
  if (!componentFile) componentFile = componentFiles[0];
27693
27963
 
27694
27964
  if (componentFile) {
27695
- componentCode = fs$5.readFileSync(
27965
+ componentCode = fs$6.readFileSync(
27696
27966
  path$9.join(widgetsDir, componentFile),
27697
27967
  "utf8",
27698
27968
  );
@@ -27702,15 +27972,15 @@ async function fetchPackageSource(packageName, componentName = null) {
27702
27972
 
27703
27973
  let bundleSource = null;
27704
27974
  const bundlePath = path$9.join(tempDir, "dist", "index.cjs.js");
27705
- if (fs$5.existsSync(bundlePath)) {
27706
- bundleSource = fs$5.readFileSync(bundlePath, "utf8");
27975
+ if (fs$6.existsSync(bundlePath)) {
27976
+ bundleSource = fs$6.readFileSync(bundlePath, "utf8");
27707
27977
  }
27708
27978
 
27709
27979
  let dashMeta = {};
27710
27980
  const dashPath = path$9.join(tempDir, "dash.json");
27711
- if (fs$5.existsSync(dashPath)) {
27981
+ if (fs$6.existsSync(dashPath)) {
27712
27982
  try {
27713
- dashMeta = JSON.parse(fs$5.readFileSync(dashPath, "utf8"));
27983
+ dashMeta = JSON.parse(fs$6.readFileSync(dashPath, "utf8"));
27714
27984
  } catch {
27715
27985
  // Ignore — metadata is optional for preview
27716
27986
  }
@@ -27729,7 +27999,7 @@ async function fetchPackageSource(packageName, componentName = null) {
27729
27999
  };
27730
28000
  } finally {
27731
28001
  try {
27732
- fs$5.rmSync(tempDir, { recursive: true, force: true });
28002
+ fs$6.rmSync(tempDir, { recursive: true, force: true });
27733
28003
  } catch (err) {
27734
28004
  console.warn(
27735
28005
  `[RegistryController] Failed to clean up preview temp dir ${tempDir}:`,
@@ -27749,7 +28019,7 @@ var registryController$3 = {
27749
28019
  fetchPackageSource,
27750
28020
  };
27751
28021
 
27752
- var fs$4 = require$$0$2;
28022
+ var fs$5 = require$$0$2;
27753
28023
  var JSONStream = require$$4;
27754
28024
  const algoliasearch$1 = require$$2$3;
27755
28025
  const path$8 = require$$3$3;
@@ -27790,7 +28060,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
27790
28060
  var batchNumber = 1;
27791
28061
 
27792
28062
  // create the readStream to parse the large file (json)
27793
- var readStream = fs$4.createReadStream(filepath).pipe(parser);
28063
+ var readStream = fs$5.createReadStream(filepath).pipe(parser);
27794
28064
 
27795
28065
  var batch = [];
27796
28066
 
@@ -27804,7 +28074,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
27804
28074
  // lets write to the batch file
27805
28075
  if (countForBatch === batchSize) {
27806
28076
  // write to the batch file
27807
- var writeStream = fs$4.createWriteStream(
28077
+ var writeStream = fs$5.createWriteStream(
27808
28078
  batchFilepath + "/batch_" + batchNumber + ".json",
27809
28079
  );
27810
28080
  writeStream.write(JSON.stringify(batch));
@@ -27855,11 +28125,11 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
27855
28125
  return new Promise((resolve, reject) => {
27856
28126
  try {
27857
28127
  checkDirectory(directoryPath);
27858
- fs$4.readdir(directoryPath, (err, files) => {
28128
+ fs$5.readdir(directoryPath, (err, files) => {
27859
28129
  if (err) reject(err);
27860
28130
  if (files) {
27861
28131
  files.forEach((file) => {
27862
- fs$4.unlinkSync(path$8.join(directoryPath, file));
28132
+ fs$5.unlinkSync(path$8.join(directoryPath, file));
27863
28133
  });
27864
28134
  resolve();
27865
28135
  }
@@ -27878,7 +28148,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
27878
28148
  ) {
27879
28149
  try {
27880
28150
  // read the directory...
27881
- const files = await fs$4.readdirSync(batchFilepath);
28151
+ const files = await fs$5.readdirSync(batchFilepath);
27882
28152
  let results = [];
27883
28153
  for (const fileIndex in files) {
27884
28154
  // for each file lets read the file and then push to algolia
@@ -27907,7 +28177,7 @@ let AlgoliaIndex$1 = class AlgoliaIndex {
27907
28177
 
27908
28178
  async readFile(filepath) {
27909
28179
  return await new Promise((resolve, reject) => {
27910
- fs$4.readFile(filepath, "utf8", (err, data) => {
28180
+ fs$5.readFile(filepath, "utf8", (err, data) => {
27911
28181
  if (err) {
27912
28182
  reject(err);
27913
28183
  }
@@ -28057,7 +28327,7 @@ var algolia = AlgoliaIndex$1;
28057
28327
  const algoliasearch = require$$2$3;
28058
28328
  const events$3 = events$8;
28059
28329
  const AlgoliaIndex = algolia;
28060
- var fs$3 = require$$0$2;
28330
+ var fs$4 = require$$0$2;
28061
28331
  const { safePath, getAllowedRoots } = safePath_1;
28062
28332
 
28063
28333
  const algoliaController$1 = {
@@ -28166,7 +28436,7 @@ const algoliaController$1 = {
28166
28436
  // init the Algolia Index helper
28167
28437
  const a = new AlgoliaIndex(appId, apiKey, indexName);
28168
28438
  // create the write stream to store the hits
28169
- const writeStream = fs$3.createWriteStream(toFilename);
28439
+ const writeStream = fs$4.createWriteStream(toFilename);
28170
28440
  writeStream.write("[");
28171
28441
 
28172
28442
  let sep = "";
@@ -28476,25 +28746,6 @@ const menuItemsController$1 = {
28476
28746
 
28477
28747
  var menuItemsController_1 = menuItemsController$1;
28478
28748
 
28479
- const path$6 = require$$1$1;
28480
- const { app: app$4 } = require$$0$1;
28481
-
28482
- const pluginController$1 = {
28483
- install: (win, packageName, filepath) => {
28484
- try {
28485
- const rootPath = path$6.join(
28486
- app$4.getPath("userData"),
28487
- "plugins",
28488
- packageName,
28489
- );
28490
- } catch (e) {
28491
- win.webContents.send("plugin-install-error", { error: e.message });
28492
- }
28493
- },
28494
- };
28495
-
28496
- var pluginController_1 = pluginController$1;
28497
-
28498
28749
  var mcp = {};
28499
28750
 
28500
28751
  var server$1 = {};
@@ -45747,7 +45998,7 @@ const completable_js_1 = completable;
45747
45998
  const uriTemplate_js_1 = uriTemplate;
45748
45999
  const toolNameValidation_js_1 = toolNameValidation;
45749
46000
  const mcp_server_js_1 = mcpServer$1;
45750
- const zod_1 = require$$8$2;
46001
+ const zod_1 = require$$8$1;
45751
46002
  /**
45752
46003
  * High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
45753
46004
  * For advanced usage (like sending notifications or setting custom request handlers), use the underlying
@@ -48278,8 +48529,8 @@ streamableHttp.StreamableHTTPServerTransport = StreamableHTTPServerTransport$1;
48278
48529
  * https.createServer({ key, cert }, handler);
48279
48530
  */
48280
48531
 
48281
- const fs$2 = require$$0$2;
48282
- const path$5 = require$$1$1;
48532
+ const fs$3 = require$$0$2;
48533
+ const path$6 = require$$1$1;
48283
48534
  const forge = require$$2$4;
48284
48535
 
48285
48536
  /**
@@ -48288,14 +48539,14 @@ const forge = require$$2$4;
48288
48539
  * @returns {{ cert: string, key: string }} PEM-encoded certificate and private key
48289
48540
  */
48290
48541
  function getOrCreateCert$1(certsDir) {
48291
- const certPath = path$5.join(certsDir, "cert.pem");
48292
- const keyPath = path$5.join(certsDir, "key.pem");
48542
+ const certPath = path$6.join(certsDir, "cert.pem");
48543
+ const keyPath = path$6.join(certsDir, "key.pem");
48293
48544
 
48294
48545
  // Return existing cert if valid
48295
- if (fs$2.existsSync(certPath) && fs$2.existsSync(keyPath)) {
48546
+ if (fs$3.existsSync(certPath) && fs$3.existsSync(keyPath)) {
48296
48547
  try {
48297
- const cert = fs$2.readFileSync(certPath, "utf8");
48298
- const key = fs$2.readFileSync(keyPath, "utf8");
48548
+ const cert = fs$3.readFileSync(certPath, "utf8");
48549
+ const key = fs$3.readFileSync(keyPath, "utf8");
48299
48550
  // Verify cert is not expired
48300
48551
  const parsed = forge.pki.certificateFromPem(cert);
48301
48552
  if (parsed.validity.notAfter > new Date()) {
@@ -48361,9 +48612,9 @@ function getOrCreateCert$1(certsDir) {
48361
48612
  const keyPem = forge.pki.privateKeyToPem(keys.privateKey);
48362
48613
 
48363
48614
  // Write to disk
48364
- fs$2.mkdirSync(certsDir, { recursive: true });
48365
- fs$2.writeFileSync(certPath, certPem, { mode: 0o644 });
48366
- fs$2.writeFileSync(keyPath, keyPem, { mode: 0o600 });
48615
+ fs$3.mkdirSync(certsDir, { recursive: true });
48616
+ fs$3.writeFileSync(certPath, certPem, { mode: 0o644 });
48617
+ fs$3.writeFileSync(keyPath, keyPem, { mode: 0o600 });
48367
48618
 
48368
48619
  console.log(`[tlsCert] Certificate saved to ${certsDir}`);
48369
48620
 
@@ -48380,7 +48631,7 @@ var tlsCert = { getOrCreateCert: getOrCreateCert$1 };
48380
48631
  * for Zod schemas in tool input validation (safeParseAsync).
48381
48632
  */
48382
48633
 
48383
- const z$1 = require$$8$2;
48634
+ const z$1 = require$$8$1;
48384
48635
 
48385
48636
  /**
48386
48637
  * Convert a JSON Schema property definition to a Zod v3 schema.
@@ -48473,7 +48724,7 @@ var jsonSchemaToZod_1 = { jsonSchemaToZod: jsonSchemaToZod$1, jsonSchemaProperty
48473
48724
  * - Rate limiting via token bucket (60 req/min)
48474
48725
  */
48475
48726
 
48476
- const https$1 = require$$10;
48727
+ const https$1 = require$$11;
48477
48728
  const { randomUUID } = require$$3$4;
48478
48729
  const { BrowserWindow: BrowserWindow$1 } = require$$0$1;
48479
48730
  const { McpServer } = mcp;
@@ -48604,7 +48855,7 @@ function registerPrompt$1(promptDef) {
48604
48855
  registeredPrompts.push(promptDef);
48605
48856
  }
48606
48857
 
48607
- const z = require$$8$2;
48858
+ const z = require$$8$1;
48608
48859
  const { jsonSchemaToZod } = jsonSchemaToZod_1;
48609
48860
 
48610
48861
  /**
@@ -50282,7 +50533,7 @@ var themeFromUrlErrors$1 = {
50282
50533
 
50283
50534
  const css = require$$0$9;
50284
50535
  const { Vibrant } = require$$1$6;
50285
- const https = require$$10;
50536
+ const https = require$$11;
50286
50537
  const http = require$$0$8;
50287
50538
  const { URL: URL$1 } = require$$4$1;
50288
50539
  const {
@@ -57023,8 +57274,8 @@ var dashboardConfigUtils$1 = {
57023
57274
  * Handles publishing packages and generating registry URLs.
57024
57275
  */
57025
57276
 
57026
- const fs$1 = require$$0$2;
57027
- const path$4 = require$$1$1;
57277
+ const fs$2 = require$$0$2;
57278
+ const path$5 = require$$1$1;
57028
57279
  const { getStoredToken: getStoredToken$2 } = registryAuthController$2;
57029
57280
 
57030
57281
  const REGISTRY_BASE_URL =
@@ -57050,14 +57301,14 @@ async function publishToRegistry$1(zipPath, manifest) {
57050
57301
 
57051
57302
  try {
57052
57303
  // Read the ZIP file
57053
- const zipBuffer = fs$1.readFileSync(zipPath);
57304
+ const zipBuffer = fs$2.readFileSync(zipPath);
57054
57305
 
57055
57306
  // Create FormData with the ZIP and manifest
57056
57307
  const formData = new FormData();
57057
57308
  formData.append(
57058
57309
  "file",
57059
57310
  new Blob([zipBuffer], { type: "application/zip" }),
57060
- path$4.basename(zipPath),
57311
+ path$5.basename(zipPath),
57061
57312
  );
57062
57313
  formData.append("manifest", JSON.stringify(manifest));
57063
57314
 
@@ -57299,8 +57550,8 @@ function requireWidgetPublishManifest () {
57299
57550
  * Mirrors dashboardConfigController patterns for ZIP creation, manifest generation,
57300
57551
  * and registry interaction.
57301
57552
  */
57302
- const path$3 = require$$1$1;
57303
- const { app: app$3, dialog: dialog$1 } = require$$0$1;
57553
+ const path$4 = require$$1$1;
57554
+ const { app: app$4, dialog: dialog$1 } = require$$0$1;
57304
57555
  const AdmZip$2 = require$$3$2;
57305
57556
 
57306
57557
  const themeController$3 = themeController_1;
@@ -57805,7 +58056,7 @@ async function installThemeFromRegistry$1(win, appId, packageName) {
57805
58056
  // Validate entry path (security: prevent path traversal)
57806
58057
  if (
57807
58058
  themeEntry.entryName.includes("..") ||
57808
- path$3.isAbsolute(themeEntry.entryName)
58059
+ path$4.isAbsolute(themeEntry.entryName)
57809
58060
  ) {
57810
58061
  return {
57811
58062
  success: false,
@@ -58038,8 +58289,8 @@ var themeRegistryController$1 = {
58038
58289
  * applies event wiring. (Import is implemented in DASH-13.)
58039
58290
  */
58040
58291
 
58041
- const { app: app$2, dialog } = require$$0$1;
58042
- const path$2 = require$$1$1;
58292
+ const { app: app$3, dialog } = require$$0$1;
58293
+ const path$3 = require$$1$1;
58043
58294
  const AdmZip$1 = require$$3$2;
58044
58295
  const { getFileContents: getFileContents$1 } = file;
58045
58296
  const {
@@ -58088,8 +58339,8 @@ async function exportDashboardConfig$1(
58088
58339
  ) {
58089
58340
  try {
58090
58341
  // 1. Read workspace from workspaces.json
58091
- const filename = path$2.join(
58092
- app$2.getPath("userData"),
58342
+ const filename = path$3.join(
58343
+ app$3.getPath("userData"),
58093
58344
  appName$1,
58094
58345
  appId,
58095
58346
  configFilename,
@@ -58202,8 +58453,8 @@ async function exportDashboardConfig$1(
58202
58453
 
58203
58454
  const { canceled, filePath } = await dialog.showSaveDialog(win, {
58204
58455
  title: "Export Dashboard as ZIP",
58205
- defaultPath: path$2.join(
58206
- app$2.getPath("desktop"),
58456
+ defaultPath: path$3.join(
58457
+ app$3.getPath("desktop"),
58207
58458
  `dashboard-${sanitizedName}.zip`,
58208
58459
  ),
58209
58460
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
@@ -58268,7 +58519,7 @@ async function selectDashboardFile$1(win) {
58268
58519
 
58269
58520
  // Extract and validate
58270
58521
  const zip = new AdmZip$1(zipPath);
58271
- const tempDir = path$2.join(app$2.getPath("temp"), "dash-import");
58522
+ const tempDir = path$3.join(app$3.getPath("temp"), "dash-import");
58272
58523
  const { validateZipEntries } = widgetRegistryExports;
58273
58524
  validateZipEntries(zip, tempDir);
58274
58525
 
@@ -58378,7 +58629,7 @@ async function importDashboardConfig$1(
58378
58629
  const zip = new AdmZip$1(zipPath);
58379
58630
 
58380
58631
  // Validate ZIP entries for path traversal
58381
- const tempDir = path$2.join(app$2.getPath("temp"), "dash-import");
58632
+ const tempDir = path$3.join(app$3.getPath("temp"), "dash-import");
58382
58633
  const { validateZipEntries } = widgetRegistryExports;
58383
58634
  validateZipEntries(zip, tempDir);
58384
58635
 
@@ -59018,7 +59269,7 @@ async function installDashboardFromRegistry$1(
59018
59269
  const zip = new AdmZip$1(zipBuffer);
59019
59270
 
59020
59271
  // 3. Validate ZIP entries
59021
- const tempDir = path$2.join(app$2.getPath("temp"), "dash-registry-import");
59272
+ const tempDir = path$3.join(app$3.getPath("temp"), "dash-registry-import");
59022
59273
  const { validateZipEntries } = widgetRegistryExports;
59023
59274
  validateZipEntries(zip, tempDir);
59024
59275
 
@@ -59154,8 +59405,8 @@ async function collectDashboardDependencies$1(
59154
59405
  ) {
59155
59406
  try {
59156
59407
  // 1. Read workspace
59157
- const filename = path$2.join(
59158
- app$2.getPath("userData"),
59408
+ const filename = path$3.join(
59409
+ app$3.getPath("userData"),
59159
59410
  appName$1,
59160
59411
  appId,
59161
59412
  configFilename,
@@ -59433,8 +59684,8 @@ async function prepareDashboardForPublish$1(
59433
59684
  const { resolveNextVersion } = requireWidgetPublishManifest();
59434
59685
 
59435
59686
  // 1. Read workspace
59436
- const filename = path$2.join(
59437
- app$2.getPath("userData"),
59687
+ const filename = path$3.join(
59688
+ app$3.getPath("userData"),
59438
59689
  appName$1,
59439
59690
  appId,
59440
59691
  configFilename,
@@ -59711,8 +59962,8 @@ async function prepareDashboardForPublish$1(
59711
59962
  const sanitizedName = manifest.name;
59712
59963
  const { canceled, filePath } = await dialog.showSaveDialog(win, {
59713
59964
  title: "Save Dashboard Package for Registry",
59714
- defaultPath: path$2.join(
59715
- app$2.getPath("desktop"),
59965
+ defaultPath: path$3.join(
59966
+ app$3.getPath("desktop"),
59716
59967
  `dashboard-${sanitizedName}-v${manifest.version}.zip`,
59717
59968
  ),
59718
59969
  filters: [{ name: "ZIP Archive", extensions: ["zip"] }],
@@ -59879,8 +60130,8 @@ async function checkDashboardUpdatesForApp$1(appId) {
59879
60130
  const { fetchRegistryIndex } = registryController$3;
59880
60131
 
59881
60132
  try {
59882
- const filename = path$2.join(
59883
- app$2.getPath("userData"),
60133
+ const filename = path$3.join(
60134
+ app$3.getPath("userData"),
59884
60135
  appName$1,
59885
60136
  appId,
59886
60137
  configFilename,
@@ -59950,8 +60201,8 @@ function getProviderSetupManifest$1(appId, requiredProviders = []) {
59950
60201
  */
59951
60202
  function getDashboardPublishPreview$1(appId, workspaceId, widgetRegistry = null) {
59952
60203
  try {
59953
- const filename = path$2.join(
59954
- app$2.getPath("userData"),
60204
+ const filename = path$3.join(
60205
+ app$3.getPath("userData"),
59955
60206
  appName$1,
59956
60207
  appId,
59957
60208
  configFilename,
@@ -60259,9 +60510,50 @@ var notificationController_1 = notificationController$2;
60259
60510
  *
60260
60511
  * Uses the `ws` package (installed in dash-electron) for WebSocket clients.
60261
60512
  * Multiple widgets referencing the same provider share a single socket.
60513
+ *
60514
+ * Phase 3 (network domain JIT) gates `connect` by hostname when a
60515
+ * widgetId is supplied. Once a connection exists, `send` /
60516
+ * `disconnect` / `getStatus` / `getAll` operate on the
60517
+ * already-authorized socket and are intentionally NOT re-gated —
60518
+ * connections are designed to be shared across widgets via the
60519
+ * `consumers: Set` field, and re-gating sends would break that.
60262
60520
  */
60263
60521
 
60264
- const WebSocket = require$$0$b;
60522
+ const { app: app$2 } = require$$0$1;
60523
+ const fs$1 = require$$0$2;
60524
+ const path$2 = require$$1$1;
60525
+ const WebSocket = require$$3$5;
60526
+ const {
60527
+ gateNetworkCall,
60528
+ gateNetworkCallWithJit,
60529
+ } = networkGate;
60530
+ const { readEnforceFlag, readJitFlag } = securityFlags;
60531
+
60532
+ function _loadFlags() {
60533
+ try {
60534
+ const settingsPath = path$2.join(
60535
+ app$2.getPath("userData"),
60536
+ "Dashboard",
60537
+ "settings.json",
60538
+ );
60539
+ if (!fs$1.existsSync(settingsPath)) return null;
60540
+ return JSON.parse(fs$1.readFileSync(settingsPath, "utf8"));
60541
+ } catch (_e) {
60542
+ return null;
60543
+ }
60544
+ }
60545
+
60546
+ async function _runNetworkGate(action, widgetId, args) {
60547
+ const settings = _loadFlags();
60548
+ if (!readEnforceFlag(settings)) return { allow: true };
60549
+ if (!widgetId) return { allow: true }; // legacy callers
60550
+ return readJitFlag(settings)
60551
+ ? await gateNetworkCallWithJit(
60552
+ { widgetId, action, args },
60553
+ { enableJit: true },
60554
+ )
60555
+ : gateNetworkCall({ widgetId, action, args });
60556
+ }
60265
60557
 
60266
60558
  /**
60267
60559
  * Active WebSocket connections
@@ -60692,7 +60984,26 @@ const webSocketController$1 = {
60692
60984
  * @param {object} config - { url, headers, subprotocols, credentials }
60693
60985
  * @returns {{ success, providerName, status } | { error, message }}
60694
60986
  */
60695
- connect: async (win, providerName, config) => {
60987
+ connect: async (win, providerName, config, widgetId = null) => {
60988
+ // Phase 3 network gate — fires only when an explicit widgetId is
60989
+ // supplied. The interpolated URL (with credentials substituted) is
60990
+ // what we actually open the socket to, so the gate uses it for
60991
+ // hostname extraction.
60992
+ const interpolatedForGate = config?.credentials
60993
+ ? interpolate(config.url, config.credentials)
60994
+ : config?.url;
60995
+ const gateResult = await _runNetworkGate("wsConnect", widgetId, {
60996
+ url: interpolatedForGate,
60997
+ });
60998
+ if (!gateResult.allow) {
60999
+ return {
61000
+ error: true,
61001
+ message: "network permission gate: " + gateResult.reason,
61002
+ providerName,
61003
+ status: STATUS.ERROR,
61004
+ };
61005
+ }
61006
+
60696
61007
  // 1. Already connected? Return existing connection
60697
61008
  const existing = activeConnections.get(providerName);
60698
61009
  if (existing && existing.status === STATUS.CONNECTED) {
@@ -62412,7 +62723,6 @@ const {
62412
62723
  saveMenuItemForApplication,
62413
62724
  listMenuItemsForApplication,
62414
62725
  } = menuItemsController_1;
62415
- const { install: pluginInstall } = pluginController_1;
62416
62726
  const {
62417
62727
  exportDashboardConfig,
62418
62728
  selectDashboardFile,
@@ -62514,7 +62824,6 @@ var controller = {
62514
62824
  describeImage,
62515
62825
  saveMenuItemForApplication,
62516
62826
  listMenuItemsForApplication,
62517
- pluginInstall,
62518
62827
  searchIndex,
62519
62828
  exportDashboardConfig,
62520
62829
  selectDashboardFile,
@@ -62566,7 +62875,7 @@ var controller = {
62566
62875
  mcpDashServerController: mcpDashServerController$2,
62567
62876
  };
62568
62877
 
62569
- const { ipcRenderer: ipcRenderer$p } = require$$0$1;
62878
+ const { ipcRenderer: ipcRenderer$o } = require$$0$1;
62570
62879
  const { SECURE_STORE_ENCRYPTION_CHECK } = events$8;
62571
62880
  /**
62572
62881
  * secureStoreApi
@@ -62588,7 +62897,7 @@ const { SECURE_STORE_ENCRYPTION_CHECK } = events$8;
62588
62897
  */
62589
62898
  const secureStoreApi$2 = {
62590
62899
  isEncryptionAvailable: () =>
62591
- ipcRenderer$p.invoke(SECURE_STORE_ENCRYPTION_CHECK, {}),
62900
+ ipcRenderer$o.invoke(SECURE_STORE_ENCRYPTION_CHECK, {}),
62592
62901
  };
62593
62902
 
62594
62903
  var secureStoreApi_1 = secureStoreApi$2;
@@ -62599,7 +62908,7 @@ var secureStoreApi_1 = secureStoreApi$2;
62599
62908
  * Handle the workspace configuration file
62600
62909
  */
62601
62910
 
62602
- const { ipcRenderer: ipcRenderer$o } = require$$0$1;
62911
+ const { ipcRenderer: ipcRenderer$n } = require$$0$1;
62603
62912
  const {
62604
62913
  WORKSPACE_LIST,
62605
62914
  WORKSPACE_SAVE,
@@ -62616,7 +62925,7 @@ const workspaceApi$2 = {
62616
62925
  */
62617
62926
  listWorkspacesForApplication: (appId) => {
62618
62927
  console.log("listWorkspacesForApplication called with appId:", appId);
62619
- return ipcRenderer$o.invoke(WORKSPACE_LIST, { appId });
62928
+ return ipcRenderer$n.invoke(WORKSPACE_LIST, { appId });
62620
62929
  },
62621
62930
 
62622
62931
  /**
@@ -62627,7 +62936,7 @@ const workspaceApi$2 = {
62627
62936
  * @returns
62628
62937
  */
62629
62938
  saveWorkspaceForApplication: (appId, data) =>
62630
- ipcRenderer$o.invoke(WORKSPACE_SAVE, { appId, data }),
62939
+ ipcRenderer$n.invoke(WORKSPACE_SAVE, { appId, data }),
62631
62940
 
62632
62941
  /**
62633
62942
  * deleteWorkspaceForApplication
@@ -62637,7 +62946,7 @@ const workspaceApi$2 = {
62637
62946
  * @returns
62638
62947
  */
62639
62948
  deleteWorkspaceForApplication: (appId, workspaceId) =>
62640
- ipcRenderer$o.invoke(WORKSPACE_DELETE, { appId, workspaceId }),
62949
+ ipcRenderer$n.invoke(WORKSPACE_DELETE, { appId, workspaceId }),
62641
62950
  };
62642
62951
 
62643
62952
  var workspaceApi_1 = workspaceApi$2;
@@ -62649,13 +62958,13 @@ var workspaceApi_1 = workspaceApi$2;
62649
62958
  */
62650
62959
 
62651
62960
  // ipcRenderer that must be used to invoke the events
62652
- const { ipcRenderer: ipcRenderer$n } = require$$0$1;
62961
+ const { ipcRenderer: ipcRenderer$m } = require$$0$1;
62653
62962
 
62654
62963
  const { LAYOUT_LIST } = events$8;
62655
62964
 
62656
62965
  const layoutApi$2 = {
62657
62966
  listLayoutsForApplication: (appId) =>
62658
- ipcRenderer$n.invoke(LAYOUT_LIST, { appId }),
62967
+ ipcRenderer$m.invoke(LAYOUT_LIST, { appId }),
62659
62968
  };
62660
62969
 
62661
62970
  var layoutApi_1 = layoutApi$2;
@@ -62667,7 +62976,7 @@ var layoutApi_1 = layoutApi$2;
62667
62976
  */
62668
62977
 
62669
62978
  // ipcRenderer that must be used to invoke the events
62670
- const { ipcRenderer: ipcRenderer$m } = require$$0$1;
62979
+ const { ipcRenderer: ipcRenderer$l } = require$$0$1;
62671
62980
 
62672
62981
  const {
62673
62982
  DATA_JSON_TO_CSV_FILE,
@@ -62685,7 +62994,7 @@ const {
62685
62994
  const dataApi$2 = {
62686
62995
  // convert a json array of objects to a csv string and save to file
62687
62996
  convertJsonToCsvFile: (appId, jsonObject, filename) =>
62688
- ipcRenderer$m.invoke(DATA_JSON_TO_CSV_FILE, {
62997
+ ipcRenderer$l.invoke(DATA_JSON_TO_CSV_FILE, {
62689
62998
  appId,
62690
62999
  jsonObject,
62691
63000
  filename,
@@ -62693,10 +63002,10 @@ const dataApi$2 = {
62693
63002
 
62694
63003
  // convert a json array of objects to a csv string and return a string
62695
63004
  convertJsonToCsvString: (appId, jsonObject) =>
62696
- ipcRenderer$m.invoke(DATA_JSON_TO_CSV_STRING, { appId, jsonObject }),
63005
+ ipcRenderer$l.invoke(DATA_JSON_TO_CSV_STRING, { appId, jsonObject }),
62697
63006
 
62698
63007
  parseXMLStream: (filepath, outpath, start) =>
62699
- ipcRenderer$m.invoke(PARSE_XML_STREAM, {
63008
+ ipcRenderer$l.invoke(PARSE_XML_STREAM, {
62700
63009
  filepath,
62701
63010
  outpath,
62702
63011
  start,
@@ -62710,7 +63019,7 @@ const dataApi$2 = {
62710
63019
  headers = null,
62711
63020
  limit = null,
62712
63021
  ) => {
62713
- ipcRenderer$m.invoke(PARSE_CSV_STREAM, {
63022
+ ipcRenderer$l.invoke(PARSE_CSV_STREAM, {
62714
63023
  filepath,
62715
63024
  outpath,
62716
63025
  delimiter,
@@ -62721,15 +63030,15 @@ const dataApi$2 = {
62721
63030
  },
62722
63031
 
62723
63032
  readLinesFromFile: (filepath, lineCount) => {
62724
- ipcRenderer$m.invoke(READ_LINES, { filepath, lineCount });
63033
+ ipcRenderer$l.invoke(READ_LINES, { filepath, lineCount });
62725
63034
  },
62726
63035
 
62727
63036
  readJSONFromFile: (filepath, objectCount = null) => {
62728
- ipcRenderer$m.invoke(READ_JSON, { filepath, objectCount });
63037
+ ipcRenderer$l.invoke(READ_JSON, { filepath, objectCount });
62729
63038
  },
62730
63039
 
62731
- readDataFromURL: (url, toFilepath) => {
62732
- ipcRenderer$m.invoke(READ_DATA_URL, { url, toFilepath });
63040
+ readDataFromURL: (url, toFilepath, widgetId = null) => {
63041
+ ipcRenderer$l.invoke(READ_DATA_URL, { url, toFilepath, widgetId });
62733
63042
  },
62734
63043
 
62735
63044
  /*
@@ -62738,7 +63047,7 @@ const dataApi$2 = {
62738
63047
  * @param {object} returnEmpty the return empty object
62739
63048
  */
62740
63049
  saveData: (data, filename, append, returnEmpty, widgetId = null) =>
62741
- ipcRenderer$m.invoke(DATA_SAVE_TO_FILE, {
63050
+ ipcRenderer$l.invoke(DATA_SAVE_TO_FILE, {
62742
63051
  data,
62743
63052
  filename,
62744
63053
  append,
@@ -62756,7 +63065,7 @@ const dataApi$2 = {
62756
63065
  * gates the gate itself).
62757
63066
  */
62758
63067
  readData: (filename, returnEmpty = [], widgetId = null) =>
62759
- ipcRenderer$m.invoke(DATA_READ_FROM_FILE, {
63068
+ ipcRenderer$l.invoke(DATA_READ_FROM_FILE, {
62760
63069
  filename,
62761
63070
  returnEmpty,
62762
63071
  widgetId,
@@ -62767,7 +63076,7 @@ const dataApi$2 = {
62767
63076
  * @returns
62768
63077
  */
62769
63078
  transformFile: (filepath, outFilepath, mappingFunctionBody, args) => {
62770
- ipcRenderer$m.invoke(TRANSFORM_FILE, {
63079
+ ipcRenderer$l.invoke(TRANSFORM_FILE, {
62771
63080
  filepath,
62772
63081
  outFilepath,
62773
63082
  mappingFunctionBody,
@@ -62785,7 +63094,7 @@ var dataApi_1 = dataApi$2;
62785
63094
  */
62786
63095
 
62787
63096
  // ipcRenderer that must be used to invoke the events
62788
- const { ipcRenderer: ipcRenderer$l } = require$$0$1;
63097
+ const { ipcRenderer: ipcRenderer$k } = require$$0$1;
62789
63098
 
62790
63099
  const {
62791
63100
  SETTINGS_GET,
@@ -62796,14 +63105,14 @@ const {
62796
63105
  } = events$8;
62797
63106
 
62798
63107
  const settingsApi$2 = {
62799
- getSettingsForApplication: () => ipcRenderer$l.invoke(SETTINGS_GET, {}),
63108
+ getSettingsForApplication: () => ipcRenderer$k.invoke(SETTINGS_GET, {}),
62800
63109
  saveSettingsForApplication: (data) =>
62801
- ipcRenderer$l.invoke(SETTINGS_SAVE, { data }),
62802
- getDataDirectory: () => ipcRenderer$l.invoke(SETTINGS_GET_DATA_DIR, {}),
63110
+ ipcRenderer$k.invoke(SETTINGS_SAVE, { data }),
63111
+ getDataDirectory: () => ipcRenderer$k.invoke(SETTINGS_GET_DATA_DIR, {}),
62803
63112
  setDataDirectory: (dataDirectory) =>
62804
- ipcRenderer$l.invoke(SETTINGS_SET_DATA_DIR, { dataDirectory }),
63113
+ ipcRenderer$k.invoke(SETTINGS_SET_DATA_DIR, { dataDirectory }),
62805
63114
  migrateDataDirectory: (oldDirectory, newDirectory) =>
62806
- ipcRenderer$l.invoke(SETTINGS_MIGRATE_DATA_DIR, {
63115
+ ipcRenderer$k.invoke(SETTINGS_MIGRATE_DATA_DIR, {
62807
63116
  oldDirectory,
62808
63117
  newDirectory,
62809
63118
  }),
@@ -62818,7 +63127,7 @@ var settingsApi_1 = settingsApi$2;
62818
63127
  * Provides file/folder chooser dialogs.
62819
63128
  */
62820
63129
 
62821
- const { ipcRenderer: ipcRenderer$k } = require$$0$1;
63130
+ const { ipcRenderer: ipcRenderer$j } = require$$0$1;
62822
63131
 
62823
63132
  const { CHOOSE_FILE } = events$8;
62824
63133
 
@@ -62831,7 +63140,7 @@ const dialogApi$2 = {
62831
63140
  * @returns {Promise<string|null>} selected file/folder path, or null if cancelled
62832
63141
  */
62833
63142
  chooseFile: (allowFile = true, extensions = ["*"]) => {
62834
- return ipcRenderer$k.invoke(CHOOSE_FILE, { allowFile, extensions });
63143
+ return ipcRenderer$j.invoke(CHOOSE_FILE, { allowFile, extensions });
62835
63144
  },
62836
63145
 
62837
63146
  /**
@@ -62856,7 +63165,7 @@ const dialogApi$2 = {
62856
63165
  typeof options.allowFile === "boolean" ? options.allowFile : allowFile;
62857
63166
  const resolvedExtensions = options.extensions || extensions;
62858
63167
 
62859
- const filePath = await ipcRenderer$k.invoke(CHOOSE_FILE, {
63168
+ const filePath = await ipcRenderer$j.invoke(CHOOSE_FILE, {
62860
63169
  allowFile: resolvedAllowFile,
62861
63170
  extensions: resolvedExtensions,
62862
63171
  });
@@ -62883,7 +63192,7 @@ var dialogApi_1 = dialogApi$2;
62883
63192
  * mainApi.widgets.uninstall('Weather')
62884
63193
  */
62885
63194
 
62886
- const { ipcRenderer: ipcRenderer$j } = require$$0$1;
63195
+ const { ipcRenderer: ipcRenderer$i } = require$$0$1;
62887
63196
 
62888
63197
  const widgetApi$2 = {
62889
63198
  /**
@@ -62892,7 +63201,7 @@ const widgetApi$2 = {
62892
63201
  */
62893
63202
  list: async () => {
62894
63203
  try {
62895
- return await ipcRenderer$j.invoke("widget:list");
63204
+ return await ipcRenderer$i.invoke("widget:list");
62896
63205
  } catch (error) {
62897
63206
  console.error("[WidgetApi] Error listing widgets:", error);
62898
63207
  throw error;
@@ -62906,7 +63215,7 @@ const widgetApi$2 = {
62906
63215
  */
62907
63216
  get: async (widgetName) => {
62908
63217
  try {
62909
- return await ipcRenderer$j.invoke("widget:get", widgetName);
63218
+ return await ipcRenderer$i.invoke("widget:get", widgetName);
62910
63219
  } catch (error) {
62911
63220
  console.error(`[WidgetApi] Error getting widget ${widgetName}:`, error);
62912
63221
  throw error;
@@ -62937,7 +63246,7 @@ const widgetApi$2 = {
62937
63246
  console.log(
62938
63247
  `[WidgetApi] Installing widget: ${widgetName} from ${downloadUrl}`,
62939
63248
  );
62940
- const config = await ipcRenderer$j.invoke(
63249
+ const config = await ipcRenderer$i.invoke(
62941
63250
  "widget:install",
62942
63251
  widgetName,
62943
63252
  downloadUrl,
@@ -62977,7 +63286,7 @@ const widgetApi$2 = {
62977
63286
  console.log(
62978
63287
  `[WidgetApi] Installing local widget: ${widgetName} from ${localPath}`,
62979
63288
  );
62980
- const config = await ipcRenderer$j.invoke(
63289
+ const config = await ipcRenderer$i.invoke(
62981
63290
  "widget:install-local",
62982
63291
  widgetName,
62983
63292
  localPath,
@@ -63008,7 +63317,7 @@ const widgetApi$2 = {
63008
63317
  loadFolder: async (folderPath) => {
63009
63318
  try {
63010
63319
  console.log(`[WidgetApi] Loading widgets from folder: ${folderPath}`);
63011
- const results = await ipcRenderer$j.invoke(
63320
+ const results = await ipcRenderer$i.invoke(
63012
63321
  "widget:load-folder",
63013
63322
  folderPath,
63014
63323
  );
@@ -63032,7 +63341,7 @@ const widgetApi$2 = {
63032
63341
  uninstall: async (widgetName) => {
63033
63342
  try {
63034
63343
  console.log(`[WidgetApi] Uninstalling widget: ${widgetName}`);
63035
- const success = await ipcRenderer$j.invoke("widget:uninstall", widgetName);
63344
+ const success = await ipcRenderer$i.invoke("widget:uninstall", widgetName);
63036
63345
  if (success) {
63037
63346
  console.log(`[WidgetApi] ✓ Widget ${widgetName} uninstalled`);
63038
63347
  } else {
@@ -63055,7 +63364,7 @@ const widgetApi$2 = {
63055
63364
  */
63056
63365
  getCachePath: async () => {
63057
63366
  try {
63058
- return await ipcRenderer$j.invoke("widget:cache-path");
63367
+ return await ipcRenderer$i.invoke("widget:cache-path");
63059
63368
  } catch (error) {
63060
63369
  console.error("[WidgetApi] Error getting cache path:", error);
63061
63370
  throw error;
@@ -63069,7 +63378,7 @@ const widgetApi$2 = {
63069
63378
  */
63070
63379
  getStoragePath: async () => {
63071
63380
  try {
63072
- return await ipcRenderer$j.invoke("widget:storage-path");
63381
+ return await ipcRenderer$i.invoke("widget:storage-path");
63073
63382
  } catch (error) {
63074
63383
  console.error("[WidgetApi] Error getting storage path:", error);
63075
63384
  throw error;
@@ -63086,7 +63395,7 @@ const widgetApi$2 = {
63086
63395
  setStoragePath: async (customPath) => {
63087
63396
  try {
63088
63397
  console.log(`[WidgetApi] Setting storage path to: ${customPath}`);
63089
- const result = await ipcRenderer$j.invoke(
63398
+ const result = await ipcRenderer$i.invoke(
63090
63399
  "widget:set-storage-path",
63091
63400
  customPath,
63092
63401
  );
@@ -63108,7 +63417,7 @@ const widgetApi$2 = {
63108
63417
  */
63109
63418
  getComponentConfigs: async () => {
63110
63419
  try {
63111
- return await ipcRenderer$j.invoke("widget:get-component-configs");
63420
+ return await ipcRenderer$i.invoke("widget:get-component-configs");
63112
63421
  } catch (error) {
63113
63422
  console.error("[WidgetApi] Error getting component configs:", error);
63114
63423
  return [];
@@ -63123,7 +63432,7 @@ const widgetApi$2 = {
63123
63432
  */
63124
63433
  readBundle: async (widgetName) => {
63125
63434
  try {
63126
- return await ipcRenderer$j.invoke("widget:read-bundle", widgetName);
63435
+ return await ipcRenderer$i.invoke("widget:read-bundle", widgetName);
63127
63436
  } catch (error) {
63128
63437
  console.error(
63129
63438
  `[WidgetApi] Error reading bundle for ${widgetName}:`,
@@ -63142,7 +63451,7 @@ const widgetApi$2 = {
63142
63451
  */
63143
63452
  readSources: async (widgetName, componentName) => {
63144
63453
  try {
63145
- return await ipcRenderer$j.invoke("widget:read-sources", {
63454
+ return await ipcRenderer$i.invoke("widget:read-sources", {
63146
63455
  widgetName,
63147
63456
  componentName,
63148
63457
  });
@@ -63162,7 +63471,7 @@ const widgetApi$2 = {
63162
63471
  */
63163
63472
  readAllBundles: async () => {
63164
63473
  try {
63165
- return await ipcRenderer$j.invoke("widget:read-all-bundles");
63474
+ return await ipcRenderer$i.invoke("widget:read-all-bundles");
63166
63475
  } catch (error) {
63167
63476
  console.error("[WidgetApi] Error reading all bundles:", error);
63168
63477
  return [];
@@ -63182,7 +63491,7 @@ const widgetApi$2 = {
63182
63491
  * });
63183
63492
  */
63184
63493
  onInstalled: (callback) => {
63185
- ipcRenderer$j.on("widget:installed", (event, data) => {
63494
+ ipcRenderer$i.on("widget:installed", (event, data) => {
63186
63495
  callback(data);
63187
63496
  });
63188
63497
  },
@@ -63199,7 +63508,7 @@ const widgetApi$2 = {
63199
63508
  * });
63200
63509
  */
63201
63510
  onUninstalled: (callback) => {
63202
- ipcRenderer$j.on("widget:uninstalled", (event, data) => {
63511
+ ipcRenderer$i.on("widget:uninstalled", (event, data) => {
63203
63512
  callback(data);
63204
63513
  });
63205
63514
  },
@@ -63217,7 +63526,7 @@ const widgetApi$2 = {
63217
63526
  * });
63218
63527
  */
63219
63528
  onLoaded: (callback) => {
63220
- ipcRenderer$j.on("widgets:loaded", (event, data) => {
63529
+ ipcRenderer$i.on("widgets:loaded", (event, data) => {
63221
63530
  callback(data);
63222
63531
  });
63223
63532
  },
@@ -63228,7 +63537,7 @@ const widgetApi$2 = {
63228
63537
  * @param {Function} callback - The callback to remove
63229
63538
  */
63230
63539
  removeInstalledListener: (callback) => {
63231
- ipcRenderer$j.removeListener("widget:installed", callback);
63540
+ ipcRenderer$i.removeListener("widget:installed", callback);
63232
63541
  },
63233
63542
 
63234
63543
  /**
@@ -63237,7 +63546,7 @@ const widgetApi$2 = {
63237
63546
  * @param {Function} callback - The callback to remove
63238
63547
  */
63239
63548
  removeUninstalledListener: (callback) => {
63240
- ipcRenderer$j.removeListener("widget:uninstalled", callback);
63549
+ ipcRenderer$i.removeListener("widget:uninstalled", callback);
63241
63550
  },
63242
63551
 
63243
63552
  /**
@@ -63246,7 +63555,7 @@ const widgetApi$2 = {
63246
63555
  * @param {Function} callback - The callback to remove
63247
63556
  */
63248
63557
  removeLoadedListener: (callback) => {
63249
- ipcRenderer$j.removeListener("widgets:loaded", callback);
63558
+ ipcRenderer$i.removeListener("widgets:loaded", callback);
63250
63559
  },
63251
63560
  };
63252
63561
 
@@ -63259,7 +63568,7 @@ var widgetApi_1 = widgetApi$2;
63259
63568
  * Communicates with main process via IPC to handle encryption and file storage
63260
63569
  */
63261
63570
 
63262
- const { ipcRenderer: ipcRenderer$i } = require$$0$1;
63571
+ const { ipcRenderer: ipcRenderer$h } = require$$0$1;
63263
63572
  const {
63264
63573
  PROVIDER_SAVE,
63265
63574
  PROVIDER_LIST,
@@ -63297,7 +63606,7 @@ const providerApi$2 = {
63297
63606
  // value, preserve what's on disk" from "caller explicitly unset it".
63298
63607
  isDefaultForType = undefined,
63299
63608
  ) =>
63300
- ipcRenderer$i.invoke(PROVIDER_SAVE, {
63609
+ ipcRenderer$h.invoke(PROVIDER_SAVE, {
63301
63610
  appId,
63302
63611
  providerName,
63303
63612
  providerType,
@@ -63317,7 +63626,7 @@ const providerApi$2 = {
63317
63626
  * @param {String} appId - the appId specified in the dash initialization
63318
63627
  * @returns {Promise<Array>} Array of provider objects with name, type, credentials
63319
63628
  */
63320
- listProviders: (appId) => ipcRenderer$i.invoke(PROVIDER_LIST, { appId }),
63629
+ listProviders: (appId) => ipcRenderer$h.invoke(PROVIDER_LIST, { appId }),
63321
63630
 
63322
63631
  /**
63323
63632
  * getProvider
@@ -63329,7 +63638,7 @@ const providerApi$2 = {
63329
63638
  * @returns {Promise<Object>} Provider object with name, type, credentials
63330
63639
  */
63331
63640
  getProvider: (appId, providerName) =>
63332
- ipcRenderer$i.invoke(PROVIDER_GET, { appId, providerName }),
63641
+ ipcRenderer$h.invoke(PROVIDER_GET, { appId, providerName }),
63333
63642
 
63334
63643
  /**
63335
63644
  * deleteProvider
@@ -63341,7 +63650,7 @@ const providerApi$2 = {
63341
63650
  * @returns {Promise}
63342
63651
  */
63343
63652
  deleteProvider: (appId, providerName) =>
63344
- ipcRenderer$i.invoke(PROVIDER_DELETE, { appId, providerName }),
63653
+ ipcRenderer$h.invoke(PROVIDER_DELETE, { appId, providerName }),
63345
63654
 
63346
63655
  /**
63347
63656
  * listProvidersForApplication
@@ -63351,14 +63660,14 @@ const providerApi$2 = {
63351
63660
  * @param {String} appId - the appId specified in the dash initialization
63352
63661
  */
63353
63662
  listProvidersForApplication: (appId) => {
63354
- ipcRenderer$i
63663
+ ipcRenderer$h
63355
63664
  .invoke(PROVIDER_LIST, { appId })
63356
63665
  .then((result) => {
63357
63666
  // Emit the event for ElectronDashboardApi to listen to
63358
- ipcRenderer$i.send("PROVIDER_LIST_COMPLETE", result);
63667
+ ipcRenderer$h.send("PROVIDER_LIST_COMPLETE", result);
63359
63668
  })
63360
63669
  .catch((error) => {
63361
- ipcRenderer$i.send("PROVIDER_LIST_ERROR", {
63670
+ ipcRenderer$h.send("PROVIDER_LIST_ERROR", {
63362
63671
  error: error.message,
63363
63672
  });
63364
63673
  });
@@ -63375,7 +63684,7 @@ const providerApi$2 = {
63375
63684
  providerType,
63376
63685
  credentials,
63377
63686
  ) => {
63378
- ipcRenderer$i
63687
+ ipcRenderer$h
63379
63688
  .invoke(PROVIDER_SAVE, {
63380
63689
  appId,
63381
63690
  providerName,
@@ -63383,10 +63692,10 @@ const providerApi$2 = {
63383
63692
  credentials,
63384
63693
  })
63385
63694
  .then((result) => {
63386
- ipcRenderer$i.send("PROVIDER_SAVE_COMPLETE", result);
63695
+ ipcRenderer$h.send("PROVIDER_SAVE_COMPLETE", result);
63387
63696
  })
63388
63697
  .catch((error) => {
63389
- ipcRenderer$i.send("PROVIDER_SAVE_ERROR", {
63698
+ ipcRenderer$h.send("PROVIDER_SAVE_ERROR", {
63390
63699
  error: error.message,
63391
63700
  });
63392
63701
  });
@@ -63398,13 +63707,13 @@ const providerApi$2 = {
63398
63707
  * Event-listener-based version for use with ElectronDashboardApi
63399
63708
  */
63400
63709
  getProviderForApplication: (appId, providerName) => {
63401
- ipcRenderer$i
63710
+ ipcRenderer$h
63402
63711
  .invoke(PROVIDER_GET, { appId, providerName })
63403
63712
  .then((result) => {
63404
- ipcRenderer$i.send("PROVIDER_GET_COMPLETE", result);
63713
+ ipcRenderer$h.send("PROVIDER_GET_COMPLETE", result);
63405
63714
  })
63406
63715
  .catch((error) => {
63407
- ipcRenderer$i.send("PROVIDER_GET_ERROR", {
63716
+ ipcRenderer$h.send("PROVIDER_GET_ERROR", {
63408
63717
  error: error.message,
63409
63718
  });
63410
63719
  });
@@ -63416,13 +63725,13 @@ const providerApi$2 = {
63416
63725
  * Event-listener-based version for use with ElectronDashboardApi
63417
63726
  */
63418
63727
  deleteProviderForApplication: (appId, providerName) => {
63419
- ipcRenderer$i
63728
+ ipcRenderer$h
63420
63729
  .invoke(PROVIDER_DELETE, { appId, providerName })
63421
63730
  .then((result) => {
63422
- ipcRenderer$i.send("PROVIDER_DELETE_COMPLETE", result);
63731
+ ipcRenderer$h.send("PROVIDER_DELETE_COMPLETE", result);
63423
63732
  })
63424
63733
  .catch((error) => {
63425
- ipcRenderer$i.send("PROVIDER_DELETE_ERROR", {
63734
+ ipcRenderer$h.send("PROVIDER_DELETE_ERROR", {
63426
63735
  error: error.message,
63427
63736
  });
63428
63737
  });
@@ -63438,7 +63747,7 @@ var providerApi_1 = providerApi$2;
63438
63747
  * Communicates with main process via IPC to manage MCP server lifecycle.
63439
63748
  */
63440
63749
 
63441
- const { ipcRenderer: ipcRenderer$h } = require$$0$1;
63750
+ const { ipcRenderer: ipcRenderer$g } = require$$0$1;
63442
63751
  const {
63443
63752
  MCP_START_SERVER,
63444
63753
  MCP_STOP_SERVER,
@@ -63477,7 +63786,7 @@ const mcpApi$2 = {
63477
63786
  workspaceId = null,
63478
63787
  pathScope = null,
63479
63788
  ) =>
63480
- ipcRenderer$h.invoke(MCP_START_SERVER, {
63789
+ ipcRenderer$g.invoke(MCP_START_SERVER, {
63481
63790
  serverName,
63482
63791
  mcpConfig,
63483
63792
  credentials,
@@ -63494,7 +63803,7 @@ const mcpApi$2 = {
63494
63803
  * @returns {Promise<{ success, serverName } | { error, message }>}
63495
63804
  */
63496
63805
  stopServer: (serverName, workspaceId = null) =>
63497
- ipcRenderer$h.invoke(MCP_STOP_SERVER, { serverName, workspaceId }),
63806
+ ipcRenderer$g.invoke(MCP_STOP_SERVER, { serverName, workspaceId }),
63498
63807
 
63499
63808
  /**
63500
63809
  * listTools
@@ -63505,7 +63814,7 @@ const mcpApi$2 = {
63505
63814
  * @returns {Promise<{ tools } | { error, message }>}
63506
63815
  */
63507
63816
  listTools: (serverName, workspaceId = null) =>
63508
- ipcRenderer$h.invoke(MCP_LIST_TOOLS, { serverName, workspaceId }),
63817
+ ipcRenderer$g.invoke(MCP_LIST_TOOLS, { serverName, workspaceId }),
63509
63818
 
63510
63819
  /**
63511
63820
  * callTool
@@ -63533,7 +63842,7 @@ const mcpApi$2 = {
63533
63842
  widgetId = null,
63534
63843
  workspaceId = null,
63535
63844
  ) =>
63536
- ipcRenderer$h.invoke(MCP_CALL_TOOL, {
63845
+ ipcRenderer$g.invoke(MCP_CALL_TOOL, {
63537
63846
  serverName,
63538
63847
  toolName,
63539
63848
  args,
@@ -63551,7 +63860,7 @@ const mcpApi$2 = {
63551
63860
  * @returns {Promise<{ resources } | { error, message }>}
63552
63861
  */
63553
63862
  listResources: (serverName, workspaceId = null) =>
63554
- ipcRenderer$h.invoke(MCP_LIST_RESOURCES, { serverName, workspaceId }),
63863
+ ipcRenderer$g.invoke(MCP_LIST_RESOURCES, { serverName, workspaceId }),
63555
63864
 
63556
63865
  /**
63557
63866
  * readResource
@@ -63563,7 +63872,7 @@ const mcpApi$2 = {
63563
63872
  * @returns {Promise<{ resource } | { error, message }>}
63564
63873
  */
63565
63874
  readResource: (serverName, uri, workspaceId = null) =>
63566
- ipcRenderer$h.invoke(MCP_READ_RESOURCE, { serverName, uri, workspaceId }),
63875
+ ipcRenderer$g.invoke(MCP_READ_RESOURCE, { serverName, uri, workspaceId }),
63567
63876
 
63568
63877
  /**
63569
63878
  * getServerStatus
@@ -63574,7 +63883,7 @@ const mcpApi$2 = {
63574
63883
  * @returns {Promise<{ status, tools, error }>}
63575
63884
  */
63576
63885
  getServerStatus: (serverName, workspaceId = null) =>
63577
- ipcRenderer$h.invoke(MCP_SERVER_STATUS, { serverName, workspaceId }),
63886
+ ipcRenderer$g.invoke(MCP_SERVER_STATUS, { serverName, workspaceId }),
63578
63887
 
63579
63888
  /**
63580
63889
  * getCatalog
@@ -63582,7 +63891,7 @@ const mcpApi$2 = {
63582
63891
  *
63583
63892
  * @returns {Promise<{ catalog } | { error, message }>}
63584
63893
  */
63585
- getCatalog: () => ipcRenderer$h.invoke(MCP_GET_CATALOG),
63894
+ getCatalog: () => ipcRenderer$g.invoke(MCP_GET_CATALOG),
63586
63895
 
63587
63896
  /**
63588
63897
  * getKnownExternalCatalog
@@ -63594,7 +63903,7 @@ const mcpApi$2 = {
63594
63903
  *
63595
63904
  * @returns {Promise<{ success, servers } | { error, message, servers }>}
63596
63905
  */
63597
- getKnownExternalCatalog: () => ipcRenderer$h.invoke(MCP_GET_KNOWN_EXTERNAL),
63906
+ getKnownExternalCatalog: () => ipcRenderer$g.invoke(MCP_GET_KNOWN_EXTERNAL),
63598
63907
 
63599
63908
  /**
63600
63909
  * onInstallKnownExternalConfirm
@@ -63608,9 +63917,9 @@ const mcpApi$2 = {
63608
63917
  */
63609
63918
  onInstallKnownExternalConfirm: (callback) => {
63610
63919
  const handler = (_e, data) => callback(data);
63611
- ipcRenderer$h.on(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
63920
+ ipcRenderer$g.on(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
63612
63921
  return () =>
63613
- ipcRenderer$h.removeListener(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
63922
+ ipcRenderer$g.removeListener(MCP_INSTALL_KNOWN_EXTERNAL_CONFIRM$1, handler);
63614
63923
  },
63615
63924
 
63616
63925
  /**
@@ -63621,7 +63930,7 @@ const mcpApi$2 = {
63621
63930
  * @param {{ confirmed: boolean, credentials?: object, error?: string }} result
63622
63931
  */
63623
63932
  sendInstallKnownExternalResult: (requestId, result) =>
63624
- ipcRenderer$h.send(MCP_INSTALL_KNOWN_EXTERNAL_RESULT$1, { requestId, result }),
63933
+ ipcRenderer$g.send(MCP_INSTALL_KNOWN_EXTERNAL_RESULT$1, { requestId, result }),
63625
63934
 
63626
63935
  /**
63627
63936
  * runAuth
@@ -63633,7 +63942,7 @@ const mcpApi$2 = {
63633
63942
  * @returns {Promise<{ success } | { error, message }>}
63634
63943
  */
63635
63944
  runAuth: (mcpConfig, credentials, authCommand) =>
63636
- ipcRenderer$h.invoke(MCP_RUN_AUTH, { mcpConfig, credentials, authCommand }),
63945
+ ipcRenderer$g.invoke(MCP_RUN_AUTH, { mcpConfig, credentials, authCommand }),
63637
63946
  };
63638
63947
 
63639
63948
  var mcpApi_1 = mcpApi$2;
@@ -63651,7 +63960,7 @@ var mcpApi_1 = mcpApi$2;
63651
63960
  * mainApi.registry.checkUpdates([{ name: "weather-widgets", version: "1.0.0" }])
63652
63961
  */
63653
63962
 
63654
- const { ipcRenderer: ipcRenderer$g } = require$$0$1;
63963
+ const { ipcRenderer: ipcRenderer$f } = require$$0$1;
63655
63964
 
63656
63965
  const registryApi$2 = {
63657
63966
  /**
@@ -63661,7 +63970,7 @@ const registryApi$2 = {
63661
63970
  */
63662
63971
  fetchIndex: async (forceRefresh = false) => {
63663
63972
  try {
63664
- return await ipcRenderer$g.invoke("registry:fetch-index", forceRefresh);
63973
+ return await ipcRenderer$f.invoke("registry:fetch-index", forceRefresh);
63665
63974
  } catch (error) {
63666
63975
  console.error("[RegistryApi] Error fetching index:", error);
63667
63976
  throw error;
@@ -63676,7 +63985,7 @@ const registryApi$2 = {
63676
63985
  */
63677
63986
  search: async (query = "", filters = {}) => {
63678
63987
  try {
63679
- return await ipcRenderer$g.invoke("registry:search", query, filters);
63988
+ return await ipcRenderer$f.invoke("registry:search", query, filters);
63680
63989
  } catch (error) {
63681
63990
  console.error("[RegistryApi] Error searching registry:", error);
63682
63991
  throw error;
@@ -63690,7 +63999,7 @@ const registryApi$2 = {
63690
63999
  */
63691
64000
  getPackage: async (packageName) => {
63692
64001
  try {
63693
- return await ipcRenderer$g.invoke("registry:get-package", packageName);
64002
+ return await ipcRenderer$f.invoke("registry:get-package", packageName);
63694
64003
  } catch (error) {
63695
64004
  console.error(
63696
64005
  `[RegistryApi] Error getting package ${packageName}:`,
@@ -63707,7 +64016,7 @@ const registryApi$2 = {
63707
64016
  */
63708
64017
  checkUpdates: async (installedWidgets = []) => {
63709
64018
  try {
63710
- return await ipcRenderer$g.invoke(
64019
+ return await ipcRenderer$f.invoke(
63711
64020
  "registry:check-updates",
63712
64021
  installedWidgets,
63713
64022
  );
@@ -63725,7 +64034,7 @@ const registryApi$2 = {
63725
64034
  */
63726
64035
  searchDashboards: async (query = "", filters = {}) => {
63727
64036
  try {
63728
- return await ipcRenderer$g.invoke(
64037
+ return await ipcRenderer$f.invoke(
63729
64038
  "registry:search-dashboards",
63730
64039
  query,
63731
64040
  filters,
@@ -63744,7 +64053,7 @@ const registryApi$2 = {
63744
64053
  */
63745
64054
  searchThemes: async (query = "", filters = {}) => {
63746
64055
  try {
63747
- return await ipcRenderer$g.invoke("registry:search-themes", query, filters);
64056
+ return await ipcRenderer$f.invoke("registry:search-themes", query, filters);
63748
64057
  } catch (error) {
63749
64058
  console.error("[RegistryApi] Error searching themes:", error);
63750
64059
  throw error;
@@ -63766,7 +64075,7 @@ const registryApi$2 = {
63766
64075
  */
63767
64076
  publishWidget: async (appId, packageId, options = {}) => {
63768
64077
  try {
63769
- return await ipcRenderer$g.invoke("registry:publish-widget", {
64078
+ return await ipcRenderer$f.invoke("registry:publish-widget", {
63770
64079
  appId,
63771
64080
  packageId,
63772
64081
  options,
@@ -63787,7 +64096,7 @@ const registryApi$2 = {
63787
64096
  */
63788
64097
  inspectWidgetPackage: async (packageId) => {
63789
64098
  try {
63790
- return await ipcRenderer$g.invoke("registry:inspect-widget-package", {
64099
+ return await ipcRenderer$f.invoke("registry:inspect-widget-package", {
63791
64100
  packageId,
63792
64101
  });
63793
64102
  } catch (error) {
@@ -63808,7 +64117,7 @@ const registryApi$2 = {
63808
64117
  */
63809
64118
  scanWidgetDefaults: async (packageId) => {
63810
64119
  try {
63811
- return await ipcRenderer$g.invoke("registry:scan-widget-defaults", {
64120
+ return await ipcRenderer$f.invoke("registry:scan-widget-defaults", {
63812
64121
  packageId,
63813
64122
  });
63814
64123
  } catch (error) {
@@ -63831,7 +64140,7 @@ const registryApi$2 = {
63831
64140
  */
63832
64141
  previewFetch: async (packageName, componentName = null) => {
63833
64142
  try {
63834
- return await ipcRenderer$g.invoke(
64143
+ return await ipcRenderer$f.invoke(
63835
64144
  "registry:preview-fetch",
63836
64145
  packageName,
63837
64146
  componentName,
@@ -63854,7 +64163,7 @@ var registryApi_1 = registryApi$2;
63854
64163
  * Handle the theme configuration file
63855
64164
  */
63856
64165
 
63857
- const { ipcRenderer: ipcRenderer$f } = require$$0$1;
64166
+ const { ipcRenderer: ipcRenderer$e } = require$$0$1;
63858
64167
 
63859
64168
  const {
63860
64169
  THEME_LIST,
@@ -63867,17 +64176,17 @@ const {
63867
64176
 
63868
64177
  const themeApi$2 = {
63869
64178
  listThemesForApplication: (appId) =>
63870
- ipcRenderer$f.invoke(THEME_LIST, { appId }),
64179
+ ipcRenderer$e.invoke(THEME_LIST, { appId }),
63871
64180
  saveThemeForApplication: (appId, themeName, themeObject) =>
63872
- ipcRenderer$f.invoke(THEME_SAVE, { appId, themeName, themeObject }),
64181
+ ipcRenderer$e.invoke(THEME_SAVE, { appId, themeName, themeObject }),
63873
64182
  deleteThemeForApplication: (appId, themeKey) =>
63874
- ipcRenderer$f.invoke(THEME_DELETE, { appId, themeKey }),
64183
+ ipcRenderer$e.invoke(THEME_DELETE, { appId, themeKey }),
63875
64184
  publishTheme: (appId, themeKey, options) =>
63876
- ipcRenderer$f.invoke(THEME_PUBLISH, { appId, themeKey, options }),
64185
+ ipcRenderer$e.invoke(THEME_PUBLISH, { appId, themeKey, options }),
63877
64186
  installThemeFromRegistry: (appId, packageName) =>
63878
- ipcRenderer$f.invoke(THEME_INSTALL_FROM_REGISTRY, { appId, packageName }),
64187
+ ipcRenderer$e.invoke(THEME_INSTALL_FROM_REGISTRY, { appId, packageName }),
63879
64188
  getThemePublishPreview: (appId, themeKey) =>
63880
- ipcRenderer$f.invoke(THEME_PUBLISH_PREVIEW, { appId, themeKey }),
64189
+ ipcRenderer$e.invoke(THEME_PUBLISH_PREVIEW, { appId, themeKey }),
63881
64190
  };
63882
64191
 
63883
64192
  var themeApi_1 = themeApi$2;
@@ -63889,7 +64198,7 @@ var themeApi_1 = themeApi$2;
63889
64198
  */
63890
64199
 
63891
64200
  // ipcRenderer that must be used to invoke the events
63892
- const { ipcRenderer: ipcRenderer$e } = require$$0$1;
64201
+ const { ipcRenderer: ipcRenderer$d } = require$$0$1;
63893
64202
 
63894
64203
  const {
63895
64204
  ALGOLIA_LIST_INDICES,
@@ -63902,10 +64211,10 @@ const {
63902
64211
 
63903
64212
  const algoliaApi$2 = {
63904
64213
  listIndices: (application) =>
63905
- ipcRenderer$e.invoke(ALGOLIA_LIST_INDICES, application),
64214
+ ipcRenderer$d.invoke(ALGOLIA_LIST_INDICES, application),
63906
64215
 
63907
64216
  browseObjects: (appId, apiKey, indexName) => {
63908
- ipcRenderer$e.invoke(ALGOLIA_BROWSE_OBJECTS, {
64217
+ ipcRenderer$d.invoke(ALGOLIA_BROWSE_OBJECTS, {
63909
64218
  appId,
63910
64219
  apiKey,
63911
64220
  indexName,
@@ -63914,7 +64223,7 @@ const algoliaApi$2 = {
63914
64223
  },
63915
64224
 
63916
64225
  getAnalyticsForQuery: (application, indexName, query) =>
63917
- ipcRenderer$e.invoke(ALGOLIA_ANALYTICS_FOR_QUERY, {
64226
+ ipcRenderer$d.invoke(ALGOLIA_ANALYTICS_FOR_QUERY, {
63918
64227
  application,
63919
64228
  indexName,
63920
64229
  query,
@@ -63927,7 +64236,7 @@ const algoliaApi$2 = {
63927
64236
  dir,
63928
64237
  createIfNotExists = false,
63929
64238
  ) =>
63930
- ipcRenderer$e.invoke(ALGOLIA_PARTIAL_UPDATE_OBJECTS, {
64239
+ ipcRenderer$d.invoke(ALGOLIA_PARTIAL_UPDATE_OBJECTS, {
63931
64240
  appId,
63932
64241
  apiKey,
63933
64242
  indexName,
@@ -63936,7 +64245,7 @@ const algoliaApi$2 = {
63936
64245
  }),
63937
64246
 
63938
64247
  createBatchesFromFile: (filepath, batchFilepath, batchSize) => {
63939
- ipcRenderer$e.invoke(ALGOLIA_CREATE_BATCH, {
64248
+ ipcRenderer$d.invoke(ALGOLIA_CREATE_BATCH, {
63940
64249
  filepath,
63941
64250
  batchFilepath,
63942
64251
  batchSize,
@@ -63944,7 +64253,7 @@ const algoliaApi$2 = {
63944
64253
  },
63945
64254
 
63946
64255
  browseObjectsToFile: (appId, apiKey, indexName, toFilename, query = "") => {
63947
- ipcRenderer$e.invoke(ALGOLIA_BROWSE_OBJECTS, {
64256
+ ipcRenderer$d.invoke(ALGOLIA_BROWSE_OBJECTS, {
63948
64257
  appId,
63949
64258
  apiKey,
63950
64259
  indexName,
@@ -63954,7 +64263,7 @@ const algoliaApi$2 = {
63954
64263
  },
63955
64264
 
63956
64265
  search: (appId, apiKey, indexName, query = "", options = {}) =>
63957
- ipcRenderer$e.invoke(ALGOLIA_SEARCH, {
64266
+ ipcRenderer$d.invoke(ALGOLIA_SEARCH, {
63958
64267
  appId,
63959
64268
  apiKey,
63960
64269
  indexName,
@@ -63969,14 +64278,14 @@ var algoliaApi_1 = algoliaApi$2;
63969
64278
  * openAI
63970
64279
  */
63971
64280
 
63972
- const { ipcRenderer: ipcRenderer$d } = require$$0$1;
64281
+ const { ipcRenderer: ipcRenderer$c } = require$$0$1;
63973
64282
 
63974
64283
  const { OPENAI_DESCRIBE_IMAGE } = openaiEvents$1;
63975
64284
 
63976
64285
  const openaiApi$2 = {
63977
64286
  // convert a json array of objects to a csv string and save to file
63978
64287
  describeImage: (imageUrl, apiKey, prompt = "What's in this image?") =>
63979
- ipcRenderer$d.invoke(OPENAI_DESCRIBE_IMAGE, { imageUrl, apiKey, prompt }),
64288
+ ipcRenderer$c.invoke(OPENAI_DESCRIBE_IMAGE, { imageUrl, apiKey, prompt }),
63980
64289
  };
63981
64290
 
63982
64291
  var openaiApi_1 = openaiApi$2;
@@ -63987,35 +64296,18 @@ var openaiApi_1 = openaiApi$2;
63987
64296
  */
63988
64297
 
63989
64298
  // ipcRenderer that must be used to invoke the events
63990
- const { ipcRenderer: ipcRenderer$c } = require$$0$1;
64299
+ const { ipcRenderer: ipcRenderer$b } = require$$0$1;
63991
64300
 
63992
64301
  const { MENU_ITEMS_SAVE, MENU_ITEMS_LIST } = events$8;
63993
64302
 
63994
64303
  const menuItemsApi$2 = {
63995
64304
  saveMenuItem: (appId, menuItem) =>
63996
- ipcRenderer$c.invoke(MENU_ITEMS_SAVE, { appId, menuItem }),
63997
- listMenuItems: (appId) => ipcRenderer$c.invoke(MENU_ITEMS_LIST, { appId }),
64305
+ ipcRenderer$b.invoke(MENU_ITEMS_SAVE, { appId, menuItem }),
64306
+ listMenuItems: (appId) => ipcRenderer$b.invoke(MENU_ITEMS_LIST, { appId }),
63998
64307
  };
63999
64308
 
64000
64309
  var menuItemsApi_1 = menuItemsApi$2;
64001
64310
 
64002
- /**
64003
- * pluginApi.js
64004
- *
64005
- * Plugin management API for the renderer process.
64006
- */
64007
-
64008
- // ipcRenderer that must be used to invoke the events
64009
- const { ipcRenderer: ipcRenderer$b } = require$$0$1;
64010
-
64011
- const pluginApi$2 = {
64012
- install: (packageName, filepath) =>
64013
- ipcRenderer$b.invoke("plugin-install", { packageName, filepath }),
64014
- uninstall: (filepath) => ipcRenderer$b.invoke("plugin-uninstall", filepath),
64015
- };
64016
-
64017
- var pluginApi_1 = pluginApi$2;
64018
-
64019
64311
  /**
64020
64312
  * llmApi.js
64021
64313
  *
@@ -64732,8 +65024,8 @@ const webSocketApi$2 = {
64732
65024
  * @param {object} config { url, headers, subprotocols, credentials }
64733
65025
  * @returns {Promise<{ success, providerName, status } | { error, message }>}
64734
65026
  */
64735
- connect: (providerName, config) =>
64736
- ipcRenderer$4.invoke(WS_CONNECT, { providerName, config }),
65027
+ connect: (providerName, config, widgetId = null) =>
65028
+ ipcRenderer$4.invoke(WS_CONNECT, { providerName, config, widgetId }),
64737
65029
 
64738
65030
  /**
64739
65031
  * disconnect
@@ -66108,7 +66400,6 @@ const themeApi$1 = themeApi_1;
66108
66400
  const algoliaApi$1 = algoliaApi_1;
66109
66401
  const openaiApi$1 = openaiApi_1;
66110
66402
  const menuItemsApi$1 = menuItemsApi_1;
66111
- const pluginApi$1 = pluginApi_1;
66112
66403
  const llmApi$1 = llmApi_1;
66113
66404
  const dashboardConfigApi$1 = dashboardConfigApi_1;
66114
66405
  const dashboardRatingsApi = dashboardRatingsApi_1;
@@ -66188,7 +66479,6 @@ function createMainApi$1(extensions = {}) {
66188
66479
  algolia: algoliaApi$1,
66189
66480
  openai: openaiApi$1,
66190
66481
  menuItems: menuItemsApi$1,
66191
- plugins: pluginApi$1,
66192
66482
  dashboardConfig: dashboardConfigApi$1,
66193
66483
  dashboardRatings: dashboardRatingsApi,
66194
66484
  registryAuth: registryAuthApi$1,
@@ -66241,7 +66531,6 @@ const registryController = registryController$3;
66241
66531
  const algoliaController = algoliaController_1;
66242
66532
  const openaiController = openaiController_1;
66243
66533
  const menuItemsController = menuItemsController_1;
66244
- const pluginController = pluginController_1;
66245
66534
  const llmController = llmController_1;
66246
66535
  const cliController = cliController_1;
66247
66536
  const dashboardConfigController = dashboardConfigController$1;
@@ -66284,7 +66573,6 @@ const themeApi = themeApi_1;
66284
66573
  const algoliaApi = algoliaApi_1;
66285
66574
  const openaiApi = openaiApi_1;
66286
66575
  const menuItemsApi = menuItemsApi_1;
66287
- const pluginApi = pluginApi_1;
66288
66576
  const llmApi = llmApi_1;
66289
66577
  const dashboardConfigApi = dashboardConfigApi_1;
66290
66578
  const registryAuthApi = registryAuthApi_1;
@@ -66346,7 +66634,6 @@ var electron = {
66346
66634
  algoliaController,
66347
66635
  openaiController,
66348
66636
  menuItemsController,
66349
- pluginController,
66350
66637
  llmController,
66351
66638
  cliController,
66352
66639
  dashboardConfigController,
@@ -66381,7 +66668,6 @@ var electron = {
66381
66668
  algoliaApi,
66382
66669
  openaiApi,
66383
66670
  menuItemsApi,
66384
- pluginApi,
66385
66671
  llmApi,
66386
66672
  dashboardConfigApi,
66387
66673
  registryAuthApi,