@trops/dash-core 0.1.492 → 0.1.493

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
@@ -48733,6 +48733,223 @@ var AiAssistantSection = function AiAssistantSection() {
48733
48733
  });
48734
48734
  };
48735
48735
 
48736
+ var GrantManuallyModal = function GrantManuallyModal(_ref) {
48737
+ var isOpen = _ref.isOpen,
48738
+ setIsOpen = _ref.setIsOpen,
48739
+ widgetId = _ref.widgetId,
48740
+ _ref$knownServerNames = _ref.knownServerNames,
48741
+ knownServerNames = _ref$knownServerNames === void 0 ? [] : _ref$knownServerNames,
48742
+ onGranted = _ref.onGranted;
48743
+ var _useState = React.useState(""),
48744
+ _useState2 = _slicedToArray(_useState, 2),
48745
+ serverName = _useState2[0],
48746
+ setServerName = _useState2[1];
48747
+ var _useState3 = React.useState(""),
48748
+ _useState4 = _slicedToArray(_useState3, 2),
48749
+ toolsText = _useState4[0],
48750
+ setToolsText = _useState4[1];
48751
+ var _useState5 = React.useState(""),
48752
+ _useState6 = _slicedToArray(_useState5, 2),
48753
+ readPathsText = _useState6[0],
48754
+ setReadPathsText = _useState6[1];
48755
+ var _useState7 = React.useState(""),
48756
+ _useState8 = _slicedToArray(_useState7, 2),
48757
+ writePathsText = _useState8[0],
48758
+ setWritePathsText = _useState8[1];
48759
+ var _useState9 = React.useState(null),
48760
+ _useState0 = _slicedToArray(_useState9, 2),
48761
+ error = _useState0[0],
48762
+ setError = _useState0[1];
48763
+ var _useState1 = React.useState(false),
48764
+ _useState10 = _slicedToArray(_useState1, 2),
48765
+ isSubmitting = _useState10[0],
48766
+ setIsSubmitting = _useState10[1];
48767
+ React.useEffect(function () {
48768
+ if (isOpen) {
48769
+ setServerName("");
48770
+ setToolsText("");
48771
+ setReadPathsText("");
48772
+ setWritePathsText("");
48773
+ setError(null);
48774
+ setIsSubmitting(false);
48775
+ }
48776
+ }, [isOpen]);
48777
+ var splitLines = function splitLines(s) {
48778
+ return s.split(/\r?\n/).map(function (l) {
48779
+ return l.trim();
48780
+ }).filter(Boolean);
48781
+ };
48782
+ var splitCsv = function splitCsv(s) {
48783
+ return s.split(",").map(function (t) {
48784
+ return t.trim();
48785
+ }).filter(Boolean);
48786
+ };
48787
+ var handleGrant = /*#__PURE__*/function () {
48788
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
48789
+ var tools, perms, _window$mainApi, _window$mainApi$setGr, ok, _t;
48790
+ return _regeneratorRuntime.wrap(function (_context) {
48791
+ while (1) switch (_context.prev = _context.next) {
48792
+ case 0:
48793
+ setError(null);
48794
+ if (serverName.trim()) {
48795
+ _context.next = 1;
48796
+ break;
48797
+ }
48798
+ setError("Server name is required.");
48799
+ return _context.abrupt("return");
48800
+ case 1:
48801
+ tools = splitCsv(toolsText);
48802
+ if (!(tools.length === 0)) {
48803
+ _context.next = 2;
48804
+ break;
48805
+ }
48806
+ setError("At least one tool name is required.");
48807
+ return _context.abrupt("return");
48808
+ case 2:
48809
+ perms = {
48810
+ grantOrigin: "manual",
48811
+ servers: _defineProperty({}, serverName.trim(), {
48812
+ tools: tools,
48813
+ readPaths: splitLines(readPathsText),
48814
+ writePaths: splitLines(writePathsText)
48815
+ })
48816
+ };
48817
+ setIsSubmitting(true);
48818
+ _context.prev = 3;
48819
+ _context.next = 4;
48820
+ return typeof window !== "undefined" ? (_window$mainApi = window.mainApi) === null || _window$mainApi === void 0 || (_window$mainApi = _window$mainApi.widgetMcp) === null || _window$mainApi === void 0 || (_window$mainApi$setGr = _window$mainApi.setGrant) === null || _window$mainApi$setGr === void 0 ? void 0 : _window$mainApi$setGr.call(_window$mainApi, widgetId, perms) : null;
48821
+ case 4:
48822
+ ok = _context.sent;
48823
+ if (!(ok === false)) {
48824
+ _context.next = 5;
48825
+ break;
48826
+ }
48827
+ setError("Could not save grant.");
48828
+ setIsSubmitting(false);
48829
+ return _context.abrupt("return");
48830
+ case 5:
48831
+ if (typeof onGranted === "function") onGranted();
48832
+ setIsOpen(false);
48833
+ _context.next = 7;
48834
+ break;
48835
+ case 6:
48836
+ _context.prev = 6;
48837
+ _t = _context["catch"](3);
48838
+ setError((_t === null || _t === void 0 ? void 0 : _t.message) || String(_t));
48839
+ setIsSubmitting(false);
48840
+ case 7:
48841
+ case "end":
48842
+ return _context.stop();
48843
+ }
48844
+ }, _callee, null, [[3, 6]]);
48845
+ }));
48846
+ return function handleGrant() {
48847
+ return _ref2.apply(this, arguments);
48848
+ };
48849
+ }();
48850
+ if (!widgetId) return null;
48851
+ return /*#__PURE__*/jsxRuntime.jsx(DashReact.Modal, {
48852
+ isOpen: isOpen,
48853
+ setIsOpen: setIsOpen,
48854
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
48855
+ className: "flex flex-col w-full max-w-xl ring-2 ring-amber-500",
48856
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48857
+ className: "px-5 py-4 border-b border-gray-700",
48858
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48859
+ className: "text-base font-semibold",
48860
+ children: ["Grant manually: ", widgetId]
48861
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
48862
+ className: "text-xs opacity-60 mt-1",
48863
+ children: "This widget did not declare its MCP needs and the install-time scanner found nothing. You are granting access based on your own judgment \u2014 be conservative. Revoke any time."
48864
+ })]
48865
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
48866
+ className: "flex flex-col gap-4 px-5 py-4 max-h-96 overflow-y-auto",
48867
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48868
+ className: "flex flex-col gap-1",
48869
+ children: [/*#__PURE__*/jsxRuntime.jsx("label", {
48870
+ className: "text-xs uppercase tracking-wider opacity-60",
48871
+ children: "Server name"
48872
+ }), /*#__PURE__*/jsxRuntime.jsx("input", {
48873
+ type: "text",
48874
+ list: "known-mcp-servers",
48875
+ value: serverName,
48876
+ onChange: function onChange(e) {
48877
+ return setServerName(e.target.value);
48878
+ },
48879
+ placeholder: "e.g. filesystem, github, slack",
48880
+ className: "text-xs px-2 py-1.5 rounded bg-gray-800 border border-gray-700"
48881
+ }), /*#__PURE__*/jsxRuntime.jsx("datalist", {
48882
+ id: "known-mcp-servers",
48883
+ children: knownServerNames.map(function (n) {
48884
+ return /*#__PURE__*/jsxRuntime.jsx("option", {
48885
+ value: n
48886
+ }, n);
48887
+ })
48888
+ })]
48889
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
48890
+ className: "flex flex-col gap-1",
48891
+ children: [/*#__PURE__*/jsxRuntime.jsx("label", {
48892
+ className: "text-xs uppercase tracking-wider opacity-60",
48893
+ children: "Tools (comma-separated)"
48894
+ }), /*#__PURE__*/jsxRuntime.jsx("input", {
48895
+ type: "text",
48896
+ value: toolsText,
48897
+ onChange: function onChange(e) {
48898
+ return setToolsText(e.target.value);
48899
+ },
48900
+ placeholder: "e.g. read_file, list_directory",
48901
+ className: "text-xs px-2 py-1.5 rounded bg-gray-800 border border-gray-700 font-mono"
48902
+ })]
48903
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
48904
+ className: "flex flex-col gap-1",
48905
+ children: [/*#__PURE__*/jsxRuntime.jsx("label", {
48906
+ className: "text-xs uppercase tracking-wider opacity-60",
48907
+ children: "Read paths (one per line, optional)"
48908
+ }), /*#__PURE__*/jsxRuntime.jsx("textarea", {
48909
+ value: readPathsText,
48910
+ onChange: function onChange(e) {
48911
+ return setReadPathsText(e.target.value);
48912
+ },
48913
+ placeholder: "/Users/jane/Documents\n/tmp/notes",
48914
+ rows: 3,
48915
+ className: "text-xs px-2 py-1.5 rounded bg-gray-800 border border-gray-700 font-mono"
48916
+ })]
48917
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
48918
+ className: "flex flex-col gap-1",
48919
+ children: [/*#__PURE__*/jsxRuntime.jsx("label", {
48920
+ className: "text-xs uppercase tracking-wider opacity-60",
48921
+ children: "Write paths (one per line, optional)"
48922
+ }), /*#__PURE__*/jsxRuntime.jsx("textarea", {
48923
+ value: writePathsText,
48924
+ onChange: function onChange(e) {
48925
+ return setWritePathsText(e.target.value);
48926
+ },
48927
+ placeholder: "/tmp/output",
48928
+ rows: 3,
48929
+ className: "text-xs px-2 py-1.5 rounded bg-gray-800 border border-gray-700 font-mono"
48930
+ })]
48931
+ }), error && /*#__PURE__*/jsxRuntime.jsx("div", {
48932
+ className: "text-xs text-red-400 bg-red-900 bg-opacity-20 border border-red-700 rounded px-3 py-2",
48933
+ children: error
48934
+ })]
48935
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
48936
+ className: "flex justify-end gap-2 px-5 py-3 border-t border-gray-700",
48937
+ children: [/*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48938
+ title: "Cancel",
48939
+ onClick: function onClick() {
48940
+ return setIsOpen(false);
48941
+ },
48942
+ disabled: isSubmitting
48943
+ }), /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48944
+ title: "Grant",
48945
+ onClick: handleGrant,
48946
+ disabled: isSubmitting
48947
+ })]
48948
+ })]
48949
+ })
48950
+ });
48951
+ };
48952
+
48736
48953
  var PrivacySecuritySection = function PrivacySecuritySection() {
48737
48954
  var _useState = React.useState([]),
48738
48955
  _useState2 = _slicedToArray(_useState, 2),
@@ -48746,6 +48963,14 @@ var PrivacySecuritySection = function PrivacySecuritySection() {
48746
48963
  _useState6 = _slicedToArray(_useState5, 2),
48747
48964
  error = _useState6[0],
48748
48965
  setError = _useState6[1];
48966
+ var _useState7 = React.useState(null),
48967
+ _useState8 = _slicedToArray(_useState7, 2),
48968
+ manualGrantWidgetId = _useState8[0],
48969
+ setManualGrantWidgetId = _useState8[1];
48970
+ var _useState9 = React.useState([]),
48971
+ _useState0 = _slicedToArray(_useState9, 2),
48972
+ knownServerNames = _useState0[0],
48973
+ setKnownServerNames = _useState0[1];
48749
48974
  var reload = React.useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
48750
48975
  var _api$widgetMcp, api, result, _t;
48751
48976
  return _regeneratorRuntime.wrap(function (_context) {
@@ -48786,42 +49011,55 @@ var PrivacySecuritySection = function PrivacySecuritySection() {
48786
49011
  React.useEffect(function () {
48787
49012
  reload();
48788
49013
  }, [reload]);
48789
- var revokeWidget = /*#__PURE__*/function () {
48790
- var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(widgetId) {
48791
- var _window$mainApi, _window$mainApi$revok, _t2;
49014
+
49015
+ // Pull catalog server names once, used as a datalist hint in the
49016
+ // manual-grant modal. Best-effort — if the API isn't there, the
49017
+ // datalist is just empty.
49018
+ React.useEffect(function () {
49019
+ var cancelled = false;
49020
+ _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
49021
+ var _api$mcp, _api$mcp$getCatalog, api, result, servers;
48792
49022
  return _regeneratorRuntime.wrap(function (_context2) {
48793
49023
  while (1) switch (_context2.prev = _context2.next) {
48794
49024
  case 0:
48795
49025
  _context2.prev = 0;
49026
+ api = typeof window !== "undefined" ? window.mainApi : null;
48796
49027
  _context2.next = 1;
48797
- 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);
49028
+ return api === null || api === void 0 || (_api$mcp = api.mcp) === null || _api$mcp === void 0 || (_api$mcp$getCatalog = _api$mcp.getCatalog) === null || _api$mcp$getCatalog === void 0 ? void 0 : _api$mcp$getCatalog.call(_api$mcp);
48798
49029
  case 1:
48799
- reload();
49030
+ result = _context2.sent;
49031
+ servers = (result === null || result === void 0 ? void 0 : result.catalog) || [];
49032
+ if (!cancelled && Array.isArray(servers)) {
49033
+ setKnownServerNames(servers.map(function (s) {
49034
+ return s === null || s === void 0 ? void 0 : s.name;
49035
+ }).filter(function (n) {
49036
+ return typeof n === "string";
49037
+ }));
49038
+ }
48800
49039
  _context2.next = 3;
48801
49040
  break;
48802
49041
  case 2:
48803
49042
  _context2.prev = 2;
48804
- _t2 = _context2["catch"](0);
48805
- setError((_t2 === null || _t2 === void 0 ? void 0 : _t2.message) || String(_t2));
49043
+ _context2["catch"](0);
48806
49044
  case 3:
48807
49045
  case "end":
48808
49046
  return _context2.stop();
48809
49047
  }
48810
49048
  }, _callee2, null, [[0, 2]]);
48811
- }));
48812
- return function revokeWidget(_x) {
48813
- return _ref2.apply(this, arguments);
49049
+ }))();
49050
+ return function () {
49051
+ cancelled = true;
48814
49052
  };
48815
- }();
48816
- var revokeServer = /*#__PURE__*/function () {
48817
- var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(widgetId, serverName) {
48818
- var _window$mainApi2, _window$mainApi2$revo, _t3;
49053
+ }, []);
49054
+ var revokeWidget = /*#__PURE__*/function () {
49055
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3(widgetId) {
49056
+ var _window$mainApi, _window$mainApi$revok, _t3;
48819
49057
  return _regeneratorRuntime.wrap(function (_context3) {
48820
49058
  while (1) switch (_context3.prev = _context3.next) {
48821
49059
  case 0:
48822
49060
  _context3.prev = 0;
48823
49061
  _context3.next = 1;
48824
- 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);
49062
+ 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);
48825
49063
  case 1:
48826
49064
  reload();
48827
49065
  _context3.next = 3;
@@ -48836,10 +49074,37 @@ var PrivacySecuritySection = function PrivacySecuritySection() {
48836
49074
  }
48837
49075
  }, _callee3, null, [[0, 2]]);
48838
49076
  }));
48839
- return function revokeServer(_x2, _x3) {
49077
+ return function revokeWidget(_x) {
48840
49078
  return _ref3.apply(this, arguments);
48841
49079
  };
48842
49080
  }();
49081
+ var revokeServer = /*#__PURE__*/function () {
49082
+ var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee4(widgetId, serverName) {
49083
+ var _window$mainApi2, _window$mainApi2$revo, _t4;
49084
+ return _regeneratorRuntime.wrap(function (_context4) {
49085
+ while (1) switch (_context4.prev = _context4.next) {
49086
+ case 0:
49087
+ _context4.prev = 0;
49088
+ _context4.next = 1;
49089
+ 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);
49090
+ case 1:
49091
+ reload();
49092
+ _context4.next = 3;
49093
+ break;
49094
+ case 2:
49095
+ _context4.prev = 2;
49096
+ _t4 = _context4["catch"](0);
49097
+ setError((_t4 === null || _t4 === void 0 ? void 0 : _t4.message) || String(_t4));
49098
+ case 3:
49099
+ case "end":
49100
+ return _context4.stop();
49101
+ }
49102
+ }, _callee4, null, [[0, 2]]);
49103
+ }));
49104
+ return function revokeServer(_x2, _x3) {
49105
+ return _ref4.apply(this, arguments);
49106
+ };
49107
+ }();
48843
49108
  if (loading) {
48844
49109
  return /*#__PURE__*/jsxRuntime.jsx("div", {
48845
49110
  className: "flex flex-col p-6",
@@ -48865,48 +49130,83 @@ var PrivacySecuritySection = function PrivacySecuritySection() {
48865
49130
  children: error
48866
49131
  }), rows.length === 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
48867
49132
  className: "text-sm opacity-60",
48868
- children: "No widgets have requested MCP permissions yet."
48869
- }), rows.map(function (_ref4) {
48870
- var widgetId = _ref4.widgetId,
48871
- declared = _ref4.declared,
48872
- granted = _ref4.granted;
49133
+ children: "No widgets installed."
49134
+ }), rows.map(function (_ref5) {
49135
+ var widgetId = _ref5.widgetId,
49136
+ declared = _ref5.declared,
49137
+ granted = _ref5.granted,
49138
+ hasManifest = _ref5.hasManifest,
49139
+ grantOrigin = _ref5.grantOrigin;
48873
49140
  return /*#__PURE__*/jsxRuntime.jsx(WidgetGrantRow, {
48874
49141
  widgetId: widgetId,
48875
49142
  declared: declared,
48876
49143
  granted: granted,
49144
+ hasManifest: hasManifest,
49145
+ grantOrigin: grantOrigin,
48877
49146
  onRevokeWidget: function onRevokeWidget() {
48878
49147
  return revokeWidget(widgetId);
48879
49148
  },
48880
49149
  onRevokeServer: function onRevokeServer(serverName) {
48881
49150
  return revokeServer(widgetId, serverName);
49151
+ },
49152
+ onGrantManually: function onGrantManually() {
49153
+ return setManualGrantWidgetId(widgetId);
48882
49154
  }
48883
49155
  }, widgetId);
49156
+ }), /*#__PURE__*/jsxRuntime.jsx(GrantManuallyModal, {
49157
+ isOpen: !!manualGrantWidgetId,
49158
+ setIsOpen: function setIsOpen(open) {
49159
+ if (!open) setManualGrantWidgetId(null);
49160
+ },
49161
+ widgetId: manualGrantWidgetId,
49162
+ knownServerNames: knownServerNames,
49163
+ onGranted: function onGranted() {
49164
+ setManualGrantWidgetId(null);
49165
+ reload();
49166
+ }
48884
49167
  })]
48885
49168
  });
48886
49169
  };
48887
- var WidgetGrantRow = function WidgetGrantRow(_ref5) {
48888
- var widgetId = _ref5.widgetId,
48889
- declared = _ref5.declared,
48890
- granted = _ref5.granted,
48891
- onRevokeWidget = _ref5.onRevokeWidget,
48892
- onRevokeServer = _ref5.onRevokeServer;
49170
+ var WidgetGrantRow = function WidgetGrantRow(_ref6) {
49171
+ var widgetId = _ref6.widgetId,
49172
+ declared = _ref6.declared,
49173
+ granted = _ref6.granted,
49174
+ hasManifest = _ref6.hasManifest,
49175
+ grantOrigin = _ref6.grantOrigin,
49176
+ onRevokeWidget = _ref6.onRevokeWidget,
49177
+ onRevokeServer = _ref6.onRevokeServer,
49178
+ onGrantManually = _ref6.onGrantManually;
48893
49179
  var declaredServers = declared && declared.servers || {};
48894
49180
  var grantedServers = granted && granted.servers || {};
48895
49181
  var allServerNames = Array.from(new Set([].concat(_toConsumableArray(Object.keys(declaredServers)), _toConsumableArray(Object.keys(grantedServers)))));
48896
49182
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
48897
49183
  className: "flex flex-col space-y-3 border border-gray-700 rounded p-3",
48898
49184
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
48899
- className: "flex flex-row items-center justify-between",
48900
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
48901
- className: "text-sm font-mono break-all",
48902
- children: widgetId
48903
- }), Object.keys(grantedServers).length > 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
48904
- title: "Revoke all",
48905
- onClick: onRevokeWidget
49185
+ className: "flex flex-row items-center justify-between gap-2",
49186
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
49187
+ className: "flex flex-row items-center gap-2 min-w-0",
49188
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
49189
+ className: "text-sm font-mono break-all",
49190
+ children: widgetId
49191
+ }), grantOrigin && /*#__PURE__*/jsxRuntime.jsx(GrantOriginBadge, {
49192
+ origin: grantOrigin
49193
+ }), !hasManifest && !granted && /*#__PURE__*/jsxRuntime.jsx("span", {
49194
+ className: "text-xs uppercase tracking-wider text-amber-400",
49195
+ children: "no manifest"
49196
+ })]
49197
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
49198
+ className: "flex flex-row gap-2",
49199
+ children: [!hasManifest && !granted && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
49200
+ title: "Grant manually",
49201
+ onClick: onGrantManually
49202
+ }), Object.keys(grantedServers).length > 0 && /*#__PURE__*/jsxRuntime.jsx(DashReact.Button, {
49203
+ title: "Revoke all",
49204
+ onClick: onRevokeWidget
49205
+ })]
48906
49206
  })]
48907
49207
  }), !declared && !granted && /*#__PURE__*/jsxRuntime.jsx("span", {
48908
49208
  className: "text-xs opacity-50",
48909
- children: "(no manifest, no grant \u2014 should not happen)"
49209
+ children: "This widget did not declare MCP permissions and the install-time scanner found nothing. Use Grant manually if you trust it."
48910
49210
  }), allServerNames.map(function (serverName) {
48911
49211
  var decl = declaredServers[serverName] || {};
48912
49212
  var grant = grantedServers[serverName];
@@ -48943,10 +49243,10 @@ var WidgetGrantRow = function WidgetGrantRow(_ref5) {
48943
49243
  })]
48944
49244
  });
48945
49245
  };
48946
- var PermsList = function PermsList(_ref6) {
48947
- var label = _ref6.label,
48948
- declaredItems = _ref6.declaredItems,
48949
- grantedItems = _ref6.grantedItems;
49246
+ var PermsList = function PermsList(_ref7) {
49247
+ var label = _ref7.label,
49248
+ declaredItems = _ref7.declaredItems,
49249
+ grantedItems = _ref7.grantedItems;
48950
49250
  if (declaredItems.length === 0 && grantedItems.length === 0) return null;
48951
49251
  var grantedSet = new Set(grantedItems);
48952
49252
  var declaredSet = new Set(declaredItems);
@@ -48970,6 +49270,36 @@ var PermsList = function PermsList(_ref6) {
48970
49270
  });
48971
49271
  };
48972
49272
 
49273
+ /**
49274
+ * Renders a small badge showing how the user got to this grant. Helps
49275
+ * the user audit grants that were approved against a scanner guess
49276
+ * rather than the developer's explicit declaration.
49277
+ */
49278
+ var GrantOriginBadge = function GrantOriginBadge(_ref8) {
49279
+ var origin = _ref8.origin;
49280
+ var styles = {
49281
+ declared: {
49282
+ label: "declared",
49283
+ color: "text-green-400"
49284
+ },
49285
+ discovered: {
49286
+ label: "discovered",
49287
+ color: "text-amber-400"
49288
+ },
49289
+ manual: {
49290
+ label: "manual",
49291
+ color: "text-blue-400"
49292
+ }
49293
+ };
49294
+ var style = styles[origin];
49295
+ if (!style) return null;
49296
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
49297
+ className: "text-xs uppercase tracking-wider ".concat(style.color),
49298
+ title: "Origin: ".concat(origin),
49299
+ children: style.label
49300
+ });
49301
+ };
49302
+
48973
49303
  var SECTIONS = [{
48974
49304
  key: "general",
48975
49305
  label: "General",