@trops/dash-core 0.1.489 → 0.1.491

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1644,9 +1644,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1644
1644
  key: "mcpStartServer",
1645
1645
  value: function mcpStartServer(serverName, mcpConfig, credentials, onSuccess, onError) {
1646
1646
  var _this20 = this;
1647
+ var workspaceId = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
1647
1648
  if (this.api !== null) {
1648
1649
  try {
1649
- this.api.mcp.startServer(serverName, mcpConfig, credentials).then(function (result) {
1650
+ this.api.mcp.startServer(serverName, mcpConfig, credentials, workspaceId).then(function (result) {
1650
1651
  onSuccess(_this20.events.MCP_START_SERVER_COMPLETE, result);
1651
1652
  })["catch"](function (error) {
1652
1653
  onError(_this20.events.MCP_START_SERVER_ERROR, error);
@@ -1665,9 +1666,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1665
1666
  key: "mcpStopServer",
1666
1667
  value: function mcpStopServer(serverName, onSuccess, onError) {
1667
1668
  var _this21 = this;
1669
+ var workspaceId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
1668
1670
  if (this.api !== null) {
1669
1671
  try {
1670
- this.api.mcp.stopServer(serverName).then(function (result) {
1672
+ this.api.mcp.stopServer(serverName, workspaceId).then(function (result) {
1671
1673
  onSuccess(_this21.events.MCP_STOP_SERVER_COMPLETE, result);
1672
1674
  })["catch"](function (error) {
1673
1675
  onError(_this21.events.MCP_STOP_SERVER_ERROR, error);
@@ -1686,9 +1688,13 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1686
1688
  key: "mcpCallTool",
1687
1689
  value: function mcpCallTool(serverName, toolName, args, allowedTools, onSuccess, onError) {
1688
1690
  var _this22 = this;
1691
+ var workspaceId = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
1689
1692
  if (this.api !== null) {
1690
1693
  try {
1691
- this.api.mcp.callTool(serverName, toolName, args, allowedTools).then(function (result) {
1694
+ // widgetId is not threaded here; mcpApi.callTool defaults it to
1695
+ // null. Slice 3a: workspaceId scopes the MCP server process per
1696
+ // workspace.
1697
+ this.api.mcp.callTool(serverName, toolName, args, allowedTools, null, workspaceId).then(function (result) {
1692
1698
  onSuccess(_this22.events.MCP_CALL_TOOL_COMPLETE, result);
1693
1699
  })["catch"](function (error) {
1694
1700
  onError(_this22.events.MCP_CALL_TOOL_ERROR, error);
@@ -1707,9 +1713,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1707
1713
  key: "mcpListTools",
1708
1714
  value: function mcpListTools(serverName, onSuccess, onError) {
1709
1715
  var _this23 = this;
1716
+ var workspaceId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
1710
1717
  if (this.api !== null) {
1711
1718
  try {
1712
- this.api.mcp.listTools(serverName).then(function (result) {
1719
+ this.api.mcp.listTools(serverName, workspaceId).then(function (result) {
1713
1720
  onSuccess(_this23.events.MCP_LIST_TOOLS_COMPLETE, result);
1714
1721
  })["catch"](function (error) {
1715
1722
  onError(_this23.events.MCP_LIST_TOOLS_ERROR, error);
@@ -1728,9 +1735,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1728
1735
  key: "mcpListResources",
1729
1736
  value: function mcpListResources(serverName, onSuccess, onError) {
1730
1737
  var _this24 = this;
1738
+ var workspaceId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
1731
1739
  if (this.api !== null) {
1732
1740
  try {
1733
- this.api.mcp.listResources(serverName).then(function (result) {
1741
+ this.api.mcp.listResources(serverName, workspaceId).then(function (result) {
1734
1742
  onSuccess(_this24.events.MCP_LIST_RESOURCES_COMPLETE, result);
1735
1743
  })["catch"](function (error) {
1736
1744
  onError(_this24.events.MCP_LIST_RESOURCES_ERROR, error);
@@ -1749,9 +1757,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1749
1757
  key: "mcpReadResource",
1750
1758
  value: function mcpReadResource(serverName, uri, onSuccess, onError) {
1751
1759
  var _this25 = this;
1760
+ var workspaceId = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
1752
1761
  if (this.api !== null) {
1753
1762
  try {
1754
- this.api.mcp.readResource(serverName, uri).then(function (result) {
1763
+ this.api.mcp.readResource(serverName, uri, workspaceId).then(function (result) {
1755
1764
  onSuccess(_this25.events.MCP_READ_RESOURCE_COMPLETE, result);
1756
1765
  })["catch"](function (error) {
1757
1766
  onError(_this25.events.MCP_READ_RESOURCE_ERROR, error);
@@ -1770,9 +1779,10 @@ var ElectronDashboardApi = /*#__PURE__*/function () {
1770
1779
  key: "mcpGetServerStatus",
1771
1780
  value: function mcpGetServerStatus(serverName, onSuccess, onError) {
1772
1781
  var _this26 = this;
1782
+ var workspaceId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
1773
1783
  if (this.api !== null) {
1774
1784
  try {
1775
- this.api.mcp.getServerStatus(serverName).then(function (result) {
1785
+ this.api.mcp.getServerStatus(serverName, workspaceId).then(function (result) {
1776
1786
  onSuccess(_this26.events.MCP_SERVER_STATUS_COMPLETE, result);
1777
1787
  })["catch"](function (error) {
1778
1788
  onError(_this26.events.MCP_SERVER_STATUS_ERROR, error);
@@ -29120,17 +29130,27 @@ var useWidgetProviders = function useWidgetProviders() {
29120
29130
 
29121
29131
  /**
29122
29132
  * Module-level shared state for MCP server connections.
29123
- * Prevents multiple hook instances (e.g., 4 widgets using "slack") from
29124
- * each firing their own IPC startServer call.
29133
+ * Prevents multiple hook instances (e.g., 4 widgets on the same dashboard
29134
+ * using "slack") from each firing their own IPC startServer call.
29125
29135
  *
29126
- * serverStates: tracks connection result + consumer reference count per server
29127
- * pendingConnects: deduplicates in-flight IPC calls so only 1 fires per server
29136
+ * Slice 3a: keys are scoped per `(workspaceId, serverName)` so two
29137
+ * dashboards using the same provider name don't share renderer state
29138
+ * (the main process spawns separate server instances for each).
29139
+ *
29140
+ * serverStates: tracks connection result + consumer reference count
29141
+ * pendingConnects: deduplicates in-flight IPC calls
29128
29142
  */
29129
29143
  var serverStates = new Map();
29130
- // Map<serverName, { status, tools, resources, consumerCount }>
29144
+ // Map<`${workspaceId}::${serverName}`, { status, tools, resources, consumerCount }>
29131
29145
 
29132
29146
  var pendingConnects$1 = new Map();
29133
- // Map<serverName, Promise<result>>
29147
+ // Map<`${workspaceId}::${serverName}`, Promise<result>>
29148
+
29149
+ var NO_WORKSPACE = "__no_workspace__";
29150
+ function rendererStateKey(workspaceId, serverName) {
29151
+ var wid = workspaceId && typeof workspaceId === "string" ? workspaceId : NO_WORKSPACE;
29152
+ return wid + "::" + serverName;
29153
+ }
29134
29154
 
29135
29155
  /**
29136
29156
  * useMcpProvider Hook
@@ -29299,7 +29319,8 @@ var useMcpProvider = function useMcpProvider(providerType) {
29299
29319
  * even when multiple hook instances call connect() simultaneously.
29300
29320
  */
29301
29321
  var connect = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
29302
- var cached, statusResult, result, state, connectPromise, _result, _t2, _t3;
29322
+ var _workspace$workspaceD2;
29323
+ var workspaceId, stateKey, cached, statusResult, result, state, connectPromise, _result, _t2, _t3;
29303
29324
  return _regeneratorRuntime.wrap(function (_context) {
29304
29325
  while (1) switch (_context.prev = _context.next) {
29305
29326
  case 0:
@@ -29330,9 +29351,15 @@ var useMcpProvider = function useMcpProvider(providerType) {
29330
29351
  setError("Provider \"".concat(selectedProviderName, "\" has no MCP configuration"));
29331
29352
  return _context.abrupt("return");
29332
29353
  case 4:
29333
- // 1. Already connected at module level? Verify with main process before trusting cache.
29354
+ // Slice 3a: scope state per (workspace, provider). Two dashboards
29355
+ // using the same provider name get separate server instances in the
29356
+ // main process, so the renderer state must mirror that or one
29357
+ // dashboard's "connected" cache will short-circuit a second
29358
+ // dashboard's connect that needs its own backing process.
29359
+ workspaceId = (workspace === null || workspace === void 0 || (_workspace$workspaceD2 = workspace.workspaceData) === null || _workspace$workspaceD2 === void 0 ? void 0 : _workspace$workspaceD2.id) || null;
29360
+ stateKey = rendererStateKey(workspaceId, selectedProviderName); // 1. Already connected at module level? Verify with main process before trusting cache.
29334
29361
  // The server may have been stopped externally (e.g., Test Connection in settings).
29335
- cached = serverStates.get(selectedProviderName);
29362
+ cached = serverStates.get(stateKey);
29336
29363
  if (!(cached && cached.status === "connected")) {
29337
29364
  _context.next = 9;
29338
29365
  break;
@@ -29344,7 +29371,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29344
29371
  return resolve(result);
29345
29372
  }, function (event, err) {
29346
29373
  return reject(err);
29347
- });
29374
+ }, workspaceId);
29348
29375
  });
29349
29376
  case 6:
29350
29377
  statusResult = _context.sent;
@@ -29357,25 +29384,25 @@ var useMcpProvider = function useMcpProvider(providerType) {
29357
29384
  return _context.abrupt("return");
29358
29385
  case 7:
29359
29386
  // Server was stopped externally — clear stale cache and reconnect
29360
- serverStates["delete"](selectedProviderName);
29387
+ serverStates["delete"](stateKey);
29361
29388
  _context.next = 9;
29362
29389
  break;
29363
29390
  case 8:
29364
29391
  _context.prev = 8;
29365
29392
  _context["catch"](5);
29366
- serverStates["delete"](selectedProviderName);
29393
+ serverStates["delete"](stateKey);
29367
29394
  case 9:
29368
29395
  setIsConnecting(true);
29369
29396
  setError(null);
29370
29397
 
29371
29398
  // 2. Another hook instance already connecting? Piggyback on its promise
29372
- if (!pendingConnects$1.has(selectedProviderName)) {
29399
+ if (!pendingConnects$1.has(stateKey)) {
29373
29400
  _context.next = 17;
29374
29401
  break;
29375
29402
  }
29376
29403
  _context.prev = 10;
29377
29404
  _context.next = 11;
29378
- return pendingConnects$1.get(selectedProviderName);
29405
+ return pendingConnects$1.get(stateKey);
29379
29406
  case 11:
29380
29407
  result = _context.sent;
29381
29408
  if (mountedRef.current) {
@@ -29394,7 +29421,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29394
29421
  return _context.abrupt("return");
29395
29422
  case 13:
29396
29423
  // Increment consumer count and apply
29397
- state = serverStates.get(selectedProviderName);
29424
+ state = serverStates.get(stateKey);
29398
29425
  if (state) state.consumerCount++;
29399
29426
  applyResult(result);
29400
29427
  _context.next = 16;
@@ -29417,9 +29444,9 @@ var useMcpProvider = function useMcpProvider(providerType) {
29417
29444
  // 3. First caller — fire the IPC call and share the promise
29418
29445
  connectPromise = new Promise(function (resolve, reject) {
29419
29446
  dashApi.mcpStartServer(selectedProviderName, provider.mcpConfig, provider.credentials, function (event, result) {
29420
- pendingConnects$1["delete"](selectedProviderName);
29447
+ pendingConnects$1["delete"](stateKey);
29421
29448
  if (result.error) {
29422
- serverStates.set(selectedProviderName, {
29449
+ serverStates.set(stateKey, {
29423
29450
  status: "error",
29424
29451
  tools: [],
29425
29452
  resources: [],
@@ -29430,7 +29457,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29430
29457
  }
29431
29458
 
29432
29459
  // Store in module-level shared state
29433
- serverStates.set(selectedProviderName, {
29460
+ serverStates.set(stateKey, {
29434
29461
  status: "connected",
29435
29462
  tools: result.tools || [],
29436
29463
  resources: result.resources || [],
@@ -29438,17 +29465,17 @@ var useMcpProvider = function useMcpProvider(providerType) {
29438
29465
  });
29439
29466
  resolve(result);
29440
29467
  }, function (event, err) {
29441
- pendingConnects$1["delete"](selectedProviderName);
29442
- serverStates.set(selectedProviderName, {
29468
+ pendingConnects$1["delete"](stateKey);
29469
+ serverStates.set(stateKey, {
29443
29470
  status: "error",
29444
29471
  tools: [],
29445
29472
  resources: [],
29446
29473
  consumerCount: 0
29447
29474
  });
29448
29475
  reject(err);
29449
- });
29476
+ }, workspaceId);
29450
29477
  });
29451
- pendingConnects$1.set(selectedProviderName, connectPromise);
29478
+ pendingConnects$1.set(stateKey, connectPromise);
29452
29479
  _context.prev = 18;
29453
29480
  _context.next = 19;
29454
29481
  return connectPromise;
@@ -29489,14 +29516,15 @@ var useMcpProvider = function useMcpProvider(providerType) {
29489
29516
  return _context.stop();
29490
29517
  }
29491
29518
  }, _callee, null, [[5, 8], [10, 14], [18, 22]]);
29492
- })), [dashApi, provider, providerType, selectedProviderName, applyResult]);
29519
+ })), [dashApi, provider, providerType, selectedProviderName, applyResult, workspace]);
29493
29520
 
29494
29521
  /**
29495
29522
  * Disconnect from the MCP server.
29496
29523
  * Only sends the IPC stop call when this is the last consumer.
29497
29524
  */
29498
29525
  var disconnect = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
29499
- var state;
29526
+ var _workspace$workspaceD3;
29527
+ var workspaceId, stateKey, state;
29500
29528
  return _regeneratorRuntime.wrap(function (_context2) {
29501
29529
  while (1) switch (_context2.prev = _context2.next) {
29502
29530
  case 0:
@@ -29506,7 +29534,9 @@ var useMcpProvider = function useMcpProvider(providerType) {
29506
29534
  }
29507
29535
  return _context2.abrupt("return");
29508
29536
  case 1:
29509
- state = serverStates.get(selectedProviderName);
29537
+ workspaceId = (workspace === null || workspace === void 0 || (_workspace$workspaceD3 = workspace.workspaceData) === null || _workspace$workspaceD3 === void 0 ? void 0 : _workspace$workspaceD3.id) || null;
29538
+ stateKey = rendererStateKey(workspaceId, selectedProviderName);
29539
+ state = serverStates.get(stateKey);
29510
29540
  if (!state) {
29511
29541
  _context2.next = 3;
29512
29542
  break;
@@ -29525,7 +29555,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29525
29555
  return _context2.abrupt("return");
29526
29556
  case 2:
29527
29557
  // Last consumer — actually stop the server
29528
- serverStates["delete"](selectedProviderName);
29558
+ serverStates["delete"](stateKey);
29529
29559
  case 3:
29530
29560
  // Clear state synchronously BEFORE the IPC call so that
29531
29561
  // a subsequent connect() won't short-circuit on stale connectedRef
@@ -29534,29 +29564,31 @@ var useMcpProvider = function useMcpProvider(providerType) {
29534
29564
  setResources([]);
29535
29565
  setStatus("disconnected");
29536
29566
  connectedRef.current = false;
29537
- pendingConnects$1["delete"](selectedProviderName);
29567
+ pendingConnects$1["delete"](stateKey);
29538
29568
  return _context2.abrupt("return", new Promise(function (resolve) {
29539
29569
  dashApi.mcpStopServer(selectedProviderName, function () {
29540
29570
  return resolve();
29541
29571
  }, function (event, err) {
29542
29572
  resolve();
29543
- });
29573
+ }, workspaceId);
29544
29574
  }));
29545
29575
  case 4:
29546
29576
  case "end":
29547
29577
  return _context2.stop();
29548
29578
  }
29549
29579
  }, _callee2);
29550
- })), [dashApi, selectedProviderName]);
29580
+ })), [dashApi, selectedProviderName, workspace]);
29551
29581
 
29552
29582
  /**
29553
29583
  * Call a tool on the MCP server
29554
29584
  */
29555
29585
  var callTool = React.useCallback(/*#__PURE__*/function () {
29556
29586
  var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(toolName) {
29587
+ var _workspace$workspaceD4;
29557
29588
  var args,
29558
29589
  widgetRequiredTools,
29559
29590
  isRequired,
29591
+ workspaceId,
29560
29592
  _args3 = arguments;
29561
29593
  return _regeneratorRuntime.wrap(function (_context3) {
29562
29594
  while (1) switch (_context3.prev = _context3.next) {
@@ -29583,6 +29615,10 @@ var useMcpProvider = function useMcpProvider(providerType) {
29583
29615
  isRequired = widgetRequiredTools === null || widgetRequiredTools === void 0 ? void 0 : widgetRequiredTools.includes(toolName);
29584
29616
  throw new Error("Tool \"".concat(toolName, "\" is not allowed for this widget. Allowed tools: ").concat(effectiveAllowedTools.join(", ")).concat(isRequired ? ". Note: \"".concat(toolName, "\" is declared as a required tool by this widget \u2014 update the provider's allowed tools in Settings \u2192 Providers.") : ""));
29585
29617
  case 2:
29618
+ // Slice 3a: scope the MCP server process per workspace. The
29619
+ // workspace UUID is the canonical "current dashboard" identity
29620
+ // (see useNotifications, useScheduler for the same pattern).
29621
+ workspaceId = (workspace === null || workspace === void 0 || (_workspace$workspaceD4 = workspace.workspaceData) === null || _workspace$workspaceD4 === void 0 ? void 0 : _workspace$workspaceD4.id) || null;
29586
29622
  return _context3.abrupt("return", new Promise(function (resolve, reject) {
29587
29623
  var timeout = setTimeout(function () {
29588
29624
  reject(new Error("Tool call \"".concat(toolName, "\" timed out after 30s")));
@@ -29597,7 +29633,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29597
29633
  }, function (event, err) {
29598
29634
  clearTimeout(timeout);
29599
29635
  reject(new Error((err === null || err === void 0 ? void 0 : err.message) || "Failed to call MCP tool"));
29600
- });
29636
+ }, workspaceId);
29601
29637
  }));
29602
29638
  case 3:
29603
29639
  case "end":
@@ -29608,7 +29644,7 @@ var useMcpProvider = function useMcpProvider(providerType) {
29608
29644
  return function (_x) {
29609
29645
  return _ref3.apply(this, arguments);
29610
29646
  };
29611
- }(), [dashApi, selectedProviderName, effectiveAllowedTools, widgetData, providerType]);
29647
+ }(), [dashApi, selectedProviderName, effectiveAllowedTools, widgetData, providerType, workspace]);
29612
29648
 
29613
29649
  /**
29614
29650
  * Read a resource from the MCP server
@@ -29666,7 +29702,10 @@ var useMcpProvider = function useMcpProvider(providerType) {
29666
29702
 
29667
29703
  // Decrement consumer count; only stop server if last consumer
29668
29704
  if (connectedRef.current && dashApi && selectedProviderName) {
29669
- var state = serverStates.get(selectedProviderName);
29705
+ var _workspace$workspaceD5;
29706
+ var workspaceId = (workspace === null || workspace === void 0 || (_workspace$workspaceD5 = workspace.workspaceData) === null || _workspace$workspaceD5 === void 0 ? void 0 : _workspace$workspaceD5.id) || null;
29707
+ var stateKey = rendererStateKey(workspaceId, selectedProviderName);
29708
+ var state = serverStates.get(stateKey);
29670
29709
  if (state) {
29671
29710
  state.consumerCount = Math.max(0, state.consumerCount - 1);
29672
29711
  if (state.consumerCount > 0) {
@@ -29675,12 +29714,12 @@ var useMcpProvider = function useMcpProvider(providerType) {
29675
29714
  }
29676
29715
 
29677
29716
  // Last consumer — stop the server
29678
- serverStates["delete"](selectedProviderName);
29717
+ serverStates["delete"](stateKey);
29679
29718
  }
29680
- dashApi.mcpStopServer(selectedProviderName, function () {}, function () {});
29719
+ dashApi.mcpStopServer(selectedProviderName, function () {}, function () {}, workspaceId);
29681
29720
  }
29682
29721
  };
29683
- }, [dashApi, selectedProviderName]);
29722
+ }, [dashApi, selectedProviderName, workspace]);
29684
29723
  return {
29685
29724
  isConnected: isConnected,
29686
29725
  isConnecting: isConnecting,
@@ -48570,6 +48609,243 @@ var AiAssistantSection = function AiAssistantSection() {
48570
48609
  });
48571
48610
  };
48572
48611
 
48612
+ var PrivacySecuritySection = function PrivacySecuritySection() {
48613
+ var _useState = React.useState([]),
48614
+ _useState2 = _slicedToArray(_useState, 2),
48615
+ rows = _useState2[0],
48616
+ setRows = _useState2[1];
48617
+ var _useState3 = React.useState(true),
48618
+ _useState4 = _slicedToArray(_useState3, 2),
48619
+ loading = _useState4[0],
48620
+ setLoading = _useState4[1];
48621
+ var _useState5 = React.useState(null),
48622
+ _useState6 = _slicedToArray(_useState5, 2),
48623
+ error = _useState6[0],
48624
+ setError = _useState6[1];
48625
+ var reload = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
48626
+ var _api$widgetMcp, api, result, _t;
48627
+ return _regeneratorRuntime.wrap(function (_context) {
48628
+ while (1) switch (_context.prev = _context.next) {
48629
+ case 0:
48630
+ setError(null);
48631
+ _context.prev = 1;
48632
+ api = typeof window !== "undefined" ? window.mainApi : null;
48633
+ if (api !== null && api !== void 0 && (_api$widgetMcp = api.widgetMcp) !== null && _api$widgetMcp !== void 0 && _api$widgetMcp.listAll) {
48634
+ _context.next = 2;
48635
+ break;
48636
+ }
48637
+ setRows([]);
48638
+ setLoading(false);
48639
+ return _context.abrupt("return");
48640
+ case 2:
48641
+ _context.next = 3;
48642
+ return api.widgetMcp.listAll();
48643
+ case 3:
48644
+ result = _context.sent;
48645
+ setRows(Array.isArray(result) ? result : []);
48646
+ _context.next = 5;
48647
+ break;
48648
+ case 4:
48649
+ _context.prev = 4;
48650
+ _t = _context["catch"](1);
48651
+ setError((_t === null || _t === void 0 ? void 0 : _t.message) || String(_t));
48652
+ case 5:
48653
+ _context.prev = 5;
48654
+ setLoading(false);
48655
+ return _context.finish(5);
48656
+ case 6:
48657
+ case "end":
48658
+ return _context.stop();
48659
+ }
48660
+ }, _callee, null, [[1, 4, 5, 6]]);
48661
+ })), []);
48662
+ React.useEffect(function () {
48663
+ reload();
48664
+ }, [reload]);
48665
+ var revokeWidget = /*#__PURE__*/function () {
48666
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(widgetId) {
48667
+ var _window$mainApi, _window$mainApi$revok, _t2;
48668
+ return _regeneratorRuntime.wrap(function (_context2) {
48669
+ while (1) switch (_context2.prev = _context2.next) {
48670
+ case 0:
48671
+ _context2.prev = 0;
48672
+ _context2.next = 1;
48673
+ return (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.widgetMcp) === null || _window$mainApi === void 0 || (_window$mainApi$revok = _window$mainApi.revoke) === null || _window$mainApi$revok === void 0 ? void 0 : _window$mainApi$revok.call(_window$mainApi, widgetId);
48674
+ case 1:
48675
+ reload();
48676
+ _context2.next = 3;
48677
+ break;
48678
+ case 2:
48679
+ _context2.prev = 2;
48680
+ _t2 = _context2["catch"](0);
48681
+ setError((_t2 === null || _t2 === void 0 ? void 0 : _t2.message) || String(_t2));
48682
+ case 3:
48683
+ case "end":
48684
+ return _context2.stop();
48685
+ }
48686
+ }, _callee2, null, [[0, 2]]);
48687
+ }));
48688
+ return function revokeWidget(_x) {
48689
+ return _ref2.apply(this, arguments);
48690
+ };
48691
+ }();
48692
+ var revokeServer = /*#__PURE__*/function () {
48693
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(widgetId, serverName) {
48694
+ var _window$mainApi2, _window$mainApi2$revo, _t3;
48695
+ return _regeneratorRuntime.wrap(function (_context3) {
48696
+ while (1) switch (_context3.prev = _context3.next) {
48697
+ case 0:
48698
+ _context3.prev = 0;
48699
+ _context3.next = 1;
48700
+ return (_window$mainApi2 = window.mainApi) === null || _window$mainApi2 === void 0 || (_window$mainApi2 = _window$mainApi2.widgetMcp) === null || _window$mainApi2 === void 0 || (_window$mainApi2$revo = _window$mainApi2.revokeServer) === null || _window$mainApi2$revo === void 0 ? void 0 : _window$mainApi2$revo.call(_window$mainApi2, widgetId, serverName);
48701
+ case 1:
48702
+ reload();
48703
+ _context3.next = 3;
48704
+ break;
48705
+ case 2:
48706
+ _context3.prev = 2;
48707
+ _t3 = _context3["catch"](0);
48708
+ setError((_t3 === null || _t3 === void 0 ? void 0 : _t3.message) || String(_t3));
48709
+ case 3:
48710
+ case "end":
48711
+ return _context3.stop();
48712
+ }
48713
+ }, _callee3, null, [[0, 2]]);
48714
+ }));
48715
+ return function revokeServer(_x2, _x3) {
48716
+ return _ref3.apply(this, arguments);
48717
+ };
48718
+ }();
48719
+ if (loading) {
48720
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
48721
+ className: "flex flex-col p-6",
48722
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
48723
+ className: "text-sm opacity-60",
48724
+ children: "Loading\u2026"
48725
+ })
48726
+ });
48727
+ }
48728
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
48729
+ className: "flex flex-col space-y-6 p-6",
48730
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48731
+ className: "flex flex-col space-y-2",
48732
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.SubHeading3, {
48733
+ title: "Widget MCP permissions",
48734
+ padding: false
48735
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
48736
+ className: "text-xs opacity-60",
48737
+ children: "Tools and paths each widget is allowed to call via MCP. Granted paths are visible to other widgets in the same dashboard that use the same MCP server. Revoke any time."
48738
+ })]
48739
+ }), error && /*#__PURE__*/jsxRuntime.jsx("div", {
48740
+ className: "text-xs text-red-400 bg-red-900 bg-opacity-20 border border-red-700 rounded p-3",
48741
+ children: error
48742
+ }), rows.length === 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
48743
+ className: "text-sm opacity-60",
48744
+ children: "No widgets have requested MCP permissions yet."
48745
+ }), rows.map(function (_ref4) {
48746
+ var widgetId = _ref4.widgetId,
48747
+ declared = _ref4.declared,
48748
+ granted = _ref4.granted;
48749
+ return /*#__PURE__*/jsxRuntime.jsx(WidgetGrantRow, {
48750
+ widgetId: widgetId,
48751
+ declared: declared,
48752
+ granted: granted,
48753
+ onRevokeWidget: function onRevokeWidget() {
48754
+ return revokeWidget(widgetId);
48755
+ },
48756
+ onRevokeServer: function onRevokeServer(serverName) {
48757
+ return revokeServer(widgetId, serverName);
48758
+ }
48759
+ }, widgetId);
48760
+ })]
48761
+ });
48762
+ };
48763
+ var WidgetGrantRow = function WidgetGrantRow(_ref5) {
48764
+ var widgetId = _ref5.widgetId,
48765
+ declared = _ref5.declared,
48766
+ granted = _ref5.granted,
48767
+ onRevokeWidget = _ref5.onRevokeWidget,
48768
+ onRevokeServer = _ref5.onRevokeServer;
48769
+ var declaredServers = declared && declared.servers || {};
48770
+ var grantedServers = granted && granted.servers || {};
48771
+ var allServerNames = Array.from(new Set([].concat(_toConsumableArray(Object.keys(declaredServers)), _toConsumableArray(Object.keys(grantedServers)))));
48772
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
48773
+ className: "flex flex-col space-y-3 border border-gray-700 rounded p-3",
48774
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48775
+ className: "flex flex-row items-center justify-between",
48776
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
48777
+ className: "text-sm font-mono break-all",
48778
+ children: widgetId
48779
+ }), Object.keys(grantedServers).length > 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48780
+ title: "Revoke all",
48781
+ onClick: onRevokeWidget
48782
+ })]
48783
+ }), !declared && !granted && /*#__PURE__*/jsxRuntime.jsx("span", {
48784
+ className: "text-xs opacity-50",
48785
+ children: "(no manifest, no grant \u2014 should not happen)"
48786
+ }), allServerNames.map(function (serverName) {
48787
+ var decl = declaredServers[serverName] || {};
48788
+ var grant = grantedServers[serverName];
48789
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
48790
+ className: "flex flex-col space-y-2 border-t border-gray-800 pt-2",
48791
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48792
+ className: "flex flex-row items-center justify-between",
48793
+ children: [/*#__PURE__*/jsxRuntime.jsxs("span", {
48794
+ className: "text-xs uppercase tracking-wider opacity-70",
48795
+ children: [serverName, !grant && /*#__PURE__*/jsxRuntime.jsx("span", {
48796
+ className: "ml-2 text-amber-400 normal-case tracking-normal",
48797
+ children: "(declared, not granted)"
48798
+ })]
48799
+ }), grant && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48800
+ title: "Revoke server",
48801
+ onClick: function onClick() {
48802
+ return onRevokeServer(serverName);
48803
+ }
48804
+ })]
48805
+ }), /*#__PURE__*/jsxRuntime.jsx(PermsList, {
48806
+ label: "Tools",
48807
+ declaredItems: decl.tools || [],
48808
+ grantedItems: (grant === null || grant === void 0 ? void 0 : grant.tools) || []
48809
+ }), /*#__PURE__*/jsxRuntime.jsx(PermsList, {
48810
+ label: "Read paths",
48811
+ declaredItems: decl.readPaths || [],
48812
+ grantedItems: (grant === null || grant === void 0 ? void 0 : grant.readPaths) || []
48813
+ }), /*#__PURE__*/jsxRuntime.jsx(PermsList, {
48814
+ label: "Write paths",
48815
+ declaredItems: decl.writePaths || [],
48816
+ grantedItems: (grant === null || grant === void 0 ? void 0 : grant.writePaths) || []
48817
+ })]
48818
+ }, serverName);
48819
+ })]
48820
+ });
48821
+ };
48822
+ var PermsList = function PermsList(_ref6) {
48823
+ var label = _ref6.label,
48824
+ declaredItems = _ref6.declaredItems,
48825
+ grantedItems = _ref6.grantedItems;
48826
+ if (declaredItems.length === 0 && grantedItems.length === 0) return null;
48827
+ var grantedSet = new Set(grantedItems);
48828
+ var declaredSet = new Set(declaredItems);
48829
+ var all = Array.from(new Set([].concat(_toConsumableArray(declaredItems), _toConsumableArray(grantedItems))));
48830
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
48831
+ className: "flex flex-col space-y-1",
48832
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
48833
+ className: "text-xs opacity-50",
48834
+ children: label
48835
+ }), all.map(function (item) {
48836
+ var isGranted = grantedSet.has(item);
48837
+ var isDeclared = declaredSet.has(item);
48838
+ return /*#__PURE__*/jsxRuntime.jsxs("span", {
48839
+ className: "text-xs font-mono break-all ".concat(isGranted ? "opacity-100" : isDeclared ? "opacity-50 line-through" : "opacity-100 text-amber-400"),
48840
+ children: [item, !isDeclared && isGranted && /*#__PURE__*/jsxRuntime.jsx("span", {
48841
+ className: "ml-2 opacity-60",
48842
+ children: "(no longer declared)"
48843
+ })]
48844
+ }, item);
48845
+ })]
48846
+ });
48847
+ };
48848
+
48573
48849
  var SECTIONS = [{
48574
48850
  key: "general",
48575
48851
  label: "General",
@@ -48610,6 +48886,10 @@ var SECTIONS = [{
48610
48886
  key: "ai-assistant",
48611
48887
  label: "AI Assistant",
48612
48888
  icon: "wand-magic-sparkles"
48889
+ }, {
48890
+ key: "privacy-security",
48891
+ label: "Privacy & Security",
48892
+ icon: "shield-halved"
48613
48893
  }];
48614
48894
  var AppSettingsModal = function AppSettingsModal(_ref) {
48615
48895
  var isOpen = _ref.isOpen,
@@ -48797,6 +49077,9 @@ var AppSettingsModal = function AppSettingsModal(_ref) {
48797
49077
  }), activeSection === "ai-assistant" && /*#__PURE__*/jsxRuntime.jsx("div", {
48798
49078
  className: "flex-1 overflow-y-auto p-6 ".concat(panelStyles.textColor || "text-gray-200"),
48799
49079
  children: /*#__PURE__*/jsxRuntime.jsx(AiAssistantSection, {})
49080
+ }), activeSection === "privacy-security" && /*#__PURE__*/jsxRuntime.jsx("div", {
49081
+ className: "flex-1 overflow-y-auto ".concat(panelStyles.textColor || "text-gray-200"),
49082
+ children: /*#__PURE__*/jsxRuntime.jsx(PrivacySecuritySection, {})
48800
49083
  })]
48801
49084
  }), /*#__PURE__*/jsxRuntime.jsx(DashReact.SettingsModal.Footer, {
48802
49085
  children: /*#__PURE__*/jsxRuntime.jsx("div", {